Import Geant4 10.2.0 source tree
This commit is contained in:
@@ -8,14 +8,20 @@
|
||||
#
|
||||
# Generated on : 24/9/2010
|
||||
#
|
||||
# $Id: CMakeLists.txt 80313 2014-04-10 12:21:49Z gcosmo $
|
||||
# $Id: CMakeLists.txt 93451 2015-10-22 14:53:57Z gcosmo $
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
if (GEANT4_USE_FREETYPE)
|
||||
add_definitions(-DTOOLS_USE_FREETYPE)
|
||||
add_definitions(-DTOOLS_USE_EXPAT)
|
||||
endif()
|
||||
|
||||
add_subdirectory(csv)
|
||||
add_subdirectory(g4tools)
|
||||
add_subdirectory(hntools)
|
||||
add_subdirectory(management)
|
||||
add_subdirectory(parameters)
|
||||
add_subdirectory(root)
|
||||
add_subdirectory(xml)
|
||||
|
||||
@@ -27,7 +33,21 @@ if(NOT GEANT4_BUILD_GRANULAR_LIBS)
|
||||
g4tools/sources.cmake
|
||||
hntools/sources.cmake
|
||||
management/sources.cmake
|
||||
parameters/sources.cmake
|
||||
root/sources.cmake
|
||||
xml/sources.cmake
|
||||
)
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Install fonts
|
||||
#
|
||||
if (GEANT4_USE_FREETYPE)
|
||||
install(DIRECTORY fonts/
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/Geant4-${Geant4_VERSION}/fonts
|
||||
PATTERN ".svn" EXCLUDE
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# $Id: GNUmakefile 87171 2014-11-26 09:37:08Z gcosmo $
|
||||
# $Id: GNUmakefile 94591 2015-11-25 11:13:33Z gcosmo $
|
||||
# --------------------------------------------------------------
|
||||
#
|
||||
|
||||
@@ -18,8 +18,8 @@ endif
|
||||
|
||||
include $(G4INSTALL)/config/architecture.gmk
|
||||
|
||||
SUBDIRS = g4tools management hntools csv root xml
|
||||
SUBLIBS = G4tools G4analysismng G4hntools G4csv G4root G4xml
|
||||
SUBDIRS = g4tools management hntools csv root xml parameters
|
||||
SUBLIBS = G4tools G4analysismng G4hntools G4csv G4root G4xml G4parameters
|
||||
|
||||
include $(G4INSTALL)/config/globlib.gmk
|
||||
|
||||
|
||||
+278
-1
@@ -1,4 +1,4 @@
|
||||
$Id: History 87071 2014-11-24 14:05:16Z gcosmo $
|
||||
$Id: History 94599 2015-11-25 13:00:41Z gcosmo $
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=========================================================
|
||||
@@ -17,6 +17,283 @@ committal in the SVN repository !
|
||||
* Reverse chronological order (last date on top), please *
|
||||
----------------------------------------------------------
|
||||
|
||||
November 25, 2015 I. Hrivnacova (analysis-V10-01-47)
|
||||
- Adding GNUmakefile in parameters sub-category
|
||||
|
||||
November 25, 2015 I. Hrivnacova (analysis-V10-01-46)
|
||||
- Updated GNUmakefile for added parameters sub-category
|
||||
|
||||
November 20, 2015 I. Hrivnacova (analysis-V10-01-45)
|
||||
- Fix compiler warning about unused parameter 'size' observed on MacOS/clang
|
||||
(Guy Barrand)
|
||||
|
||||
November 6, 2015 I. Hrivnacova (analysis-V10-01-44)
|
||||
- Fixed default viewer settings and finalized supported plotting
|
||||
configurations:
|
||||
- Updated to g4tools 1.26.2 (G. Barrand):
|
||||
- See History_tools for the complete list of modifications.
|
||||
- Extended viewplot.cpp with a test which mimics usage in analysis category
|
||||
- Set limits for layout parameters which can be changed via UI commands
|
||||
|
||||
November 3, 2015 I. Hrivnacova (analysis-V10-00-46)
|
||||
- Fixed handling ntuples created in MT mode on master thread
|
||||
This fixes the problem reported in hypernews (#495) and the problem
|
||||
of deleting non-empty Root file containing only ntuples.
|
||||
|
||||
November 2, 2015 I. Hrivnacova (analysis-V10-01-43)
|
||||
- Fixed G4Parameter constructor
|
||||
|
||||
Oct 30, 2015 I. Hrivnacova (analysis-V10-01-42)
|
||||
- Fixed handling ntuples created in MT mode on master thread
|
||||
This fixes the problem reported in hypernews (#495) and the problem
|
||||
of deleting non-empty Root file containing only ntuples.
|
||||
|
||||
Oct 22, 2015 I. Hrivnacova (analysis-V10-01-41)
|
||||
- Updated to g4tools 1.26.0 (Guy Barrand):
|
||||
with added support for using freetype rendering in plotting
|
||||
See History_tools for the complete list of modifications.
|
||||
- Implemented support for freetype in G4PlotManager
|
||||
- Added G4PlotParameters and G4PlotMessenger classes which
|
||||
define the plot configuration parameters that can be set via UI
|
||||
commands
|
||||
- Removed unused include of G4PlotManager in hntools/src/G4ToolsAnalysisReader.cc
|
||||
|
||||
Sep 23, 2015 I. Hrivnacova (analysis-V10-01-40)
|
||||
- Fixed compiler warning
|
||||
|
||||
Sep 23, 2015 I. Hrivnacova (analysis-V10-01-39)
|
||||
- Added G4AnalysisOutput type (as class enum) and
|
||||
G4AnalysisManager functions needed to connect analysis to Geant4 scorers:
|
||||
static G4bool IsInstance();
|
||||
G4bool IsOpenFile() const;
|
||||
- Two more minor fixes
|
||||
|
||||
Sep 21, 2015 I. Hrivnacova (analysis-V10-01-38)
|
||||
- Implemented setPlotting commands and added G4HnManager::SetPlotting() function
|
||||
to set plotting to all objects
|
||||
- Fixed false warning issued from G4TNtupleManager
|
||||
- Fixed plotting in more pages
|
||||
|
||||
Sep 18, 2015 I. Hrivnacova (analysis-V10-01-37)
|
||||
- Fixed return value also in FillNtupleTColumn() in G4TNtupleManager.icc
|
||||
|
||||
Sep 18, 2015 I. Hrivnacova (analysis-V10-01-36)
|
||||
- Fixed return value in FillNtupleTColumn() in G4RootNtupleManager.hh
|
||||
|
||||
Sep 18, 2015 I. Hrivnacova (analysis-V10-01-35)
|
||||
- Updated to g4tools 1.24.2 (Guy Barrand):
|
||||
- tools/wcsv_ntuple, tools/wroot/ntuple : have class icol public.
|
||||
- tools/mpi/wrmpi : fixed use of TOOLS_USE_MPI_PACK_NOT_CONST
|
||||
- See History_tools for the complete list of modifications.
|
||||
- Use tools ntuple column base type (icol, iobj), which access is now enabled in tools,
|
||||
to avoid casting to/from void* and type check in FillNtupleXColumn (where both column type and
|
||||
column Id must be consistent with ntuple definition)
|
||||
- Simplified definitions of G4TNtupleManager pure virtual functions
|
||||
|
||||
Sep 16, 2015 I. Hrivnacova (analysis-V10-01-34)
|
||||
- In G4TNtupleManager::FillNtupleTColumn:
|
||||
changed Tvalue in const T& value to match exactlly with fill()
|
||||
functions in tools
|
||||
|
||||
Sep 15, 2015 I. Hrivnacova (analysis-V10-01-33)
|
||||
- Do not delete ntuple with Root output type
|
||||
|
||||
Sep 14, 2015 I. Hrivnacova (analysis-V10-01-32)
|
||||
- One more fix in G4RootNtupleManager - exact match of arguments in
|
||||
template specialization
|
||||
|
||||
Sep 14, 2015 I. Hrivnacova (analysis-V10-01-31)
|
||||
- Added declaration for template specializations in G4RootNtupleManager.hh;
|
||||
Trying to fix vc12 compiler error:
|
||||
'none of the 5 overloads could convert all the argument types'
|
||||
|
||||
Sep 14, 2015 I. Hrivnacova (analysis-V10-01-30)
|
||||
- Added scope G4Analysis:: to all calls to make_unique
|
||||
(to avoid ambiguity error on vc12 with std::make_unique )
|
||||
|
||||
Sep 14, 2015 I. Hrivnacova (analysis-V10-01-29)
|
||||
- Replaced constexpr (not supported on vc12) with const definitions
|
||||
|
||||
Sep 12, 2015 I. Hrivnacova (analysis-V10-01-28)
|
||||
- Removed G4CsvNtupleManager.icc file, not used
|
||||
|
||||
Sep 11, 2015 I. Hrivnacova (analysis-V10-01-27)
|
||||
- Fixed compilation warnings about unused variables
|
||||
|
||||
Sep 11, 2015 I. Hrivnacova (analysis-V10-01-26)
|
||||
- Fixed compilation with gcc 5.1:
|
||||
Added #include <memory> where missing
|
||||
|
||||
Sep 11, 2015 I. Hrivnacova (analysis-V10-01-25)
|
||||
Merged developments from analysis_c++11 branch:
|
||||
- Introduced C++11 features
|
||||
- Added classes for common handling of tools objects
|
||||
to avoid code duplication:
|
||||
- G4ToolsAnalysisManager, ToolsAnalysisReader; G4THnAnalysisManager (templated)
|
||||
- Improved G4XNtupleManager classes:
|
||||
- Introduced template functions to avoid code duplication and added
|
||||
G4TNtupleManager class template with a common implementation
|
||||
for all output types
|
||||
- G4BaseToolsManager class replaced with G4Analysis namespace utility functions,
|
||||
defined in G4BaseHistoUtilies
|
||||
- Added new sub-category parameters
|
||||
with first implementation of G4ParameterManager (still to be finalized)
|
||||
|
||||
Sep 03, 2015 I. Hrivnacova (analysis-V10-01-24)
|
||||
- Updated to g4tools 1.24.1 (Guy Barrand):
|
||||
Added ability to handle old MPI_[Pack,UnPack] signature;
|
||||
make whbook.cpp test compiling with tools in Geant4;
|
||||
Coverity fixes.
|
||||
See History_tools for the complete list of modifications.
|
||||
|
||||
Aug 27, 2015 I. Hrivnacova (analysis-V10-01-23)
|
||||
- Removed profile directory; the profiles are put in the histograms directory,
|
||||
if its name is set by the user.
|
||||
|
||||
Aug 17, 2015 I. Hrivnacova (analysis-V10-01-22)
|
||||
- Updated exception_classification:
|
||||
Added Analysis_W041: Requested feature is not available with selected output.
|
||||
|
||||
Aug 12, 2015 I. Hrivnacova (analysis-V10-01-21)
|
||||
- Fixed parameter range in setAscii command
|
||||
(thanks to Mihaly Novak for reporting this problem)
|
||||
|
||||
Jul 01, 2015 I. Hrivnacova (analysis-V10-01-20)
|
||||
- Updated to g4tools 1.23.1 (Guy Barrand):
|
||||
Finalize interfaces to MPI;
|
||||
prepare the ground for plot style files.
|
||||
See History_tools for the complete list of modifications.
|
||||
- Added G4VAnalysisManager::Merge(tools::histo::hmpi*)
|
||||
and G4MMPIToolsManager class which implements histogram & profiles
|
||||
MPI merging using tools/histo/hmpi interface
|
||||
|
||||
Jun 23, 2015 I. Hrivnacova (analysis-V10-00-45)
|
||||
- Fixed G4Analysis::Tokenize() which was failing when processsing a string
|
||||
containing opening double quota without a closing one.
|
||||
|
||||
Jun 23, 2015 I. Hrivnacova (analysis-V10-01-19)
|
||||
- Revised while loops and fixed G4Analysis::Tokenize()
|
||||
|
||||
Jun 10, 2015 I. Hrivnacova (analysis-V10-01-18)
|
||||
- Make new functions SetNtupleSColumn() in G4VRNtupleManager
|
||||
pure virtual.
|
||||
|
||||
Jun 03, 2015 I. Hrivnacova (analysis-V10-01-17)
|
||||
- Updated to g4tools 1.22.1 (Guy Barrand):
|
||||
Revisit structure for plotting related code.
|
||||
Added methods for writing multiple pages in a file.
|
||||
- Integrated changes in g4tools:
|
||||
generating a single plot file with multiple pages.
|
||||
|
||||
Jun 03, 2015 I. Hrivnacova (analysis-V10-01-16)
|
||||
- Added functions for batch plotting:
|
||||
o to activate batch plotting of a selected hitsogram/profile:
|
||||
analysisManger->SetH1Plotting(id, true);
|
||||
o the output .ps file is then create on Write() call
|
||||
in addition to standard output files
|
||||
o Plotting available for 1D, 2D histograms
|
||||
- Updated to g4tools 1.21.0 (Guy Barrand):
|
||||
Revisit #include paths to avoid too much -I when compiling.
|
||||
|
||||
May 19, 2015 I. Hrivnacova (analysis-V10-01-15)
|
||||
- Updated to g4tools 1.20.0 (Guy Barrand):
|
||||
Added "batch plotting" facility.
|
||||
|
||||
May 6, 2015 I. Hrivnacova (analysis-V10-01-14)
|
||||
- Fixed command directory names and code clean-up.
|
||||
|
||||
May 6, 2015 I. Hrivnacova (analysis-V10-01-13)
|
||||
- Attempt to fix a compilation error on Windows:
|
||||
replaced use of string operator [] with substr()
|
||||
|
||||
May 6, 2015 I. Hrivnacova (analysis-V10-01-12)
|
||||
- Attempt to fix a compilation error on Windows.
|
||||
|
||||
May 5, 2015 I. Hrivnacova (analysis-V10-01-11)
|
||||
- Implemented activation of ntuples
|
||||
- Implemented setX,Y,Z commands for setting histograms/profiles
|
||||
parameters per dimensiion. They can be used as an alternative to the
|
||||
complex set commands.
|
||||
Note: The parameters per dimensions have to be set sucessively; eg.
|
||||
/analysis/h2/setX ...
|
||||
/analysis/h2/setY ...
|
||||
Incomplete or ordre-reverted setting will result in issuing a warning
|
||||
and will be ignored.
|
||||
- Restructured messenger classes to avoid code duplications.
|
||||
|
||||
May 3, 2015 I. Hrivnacova (analysis-V10-01-10)
|
||||
- Implemented support for ntuple vector columns with Csv output
|
||||
- Added Set/GetCompressionLevel() functions to G4AnalysisManager
|
||||
(used only with Root output) and changed its default value to 1 (was 9))
|
||||
|
||||
April 14, 2015 I. Hrivnacova (analysis-V10-01-09)
|
||||
- Updated to g4tools 1.19.2 (Guy Barrand):
|
||||
Fixed compilation on Mac, clang 3.4.
|
||||
See History_tools for the complete list of modifications.
|
||||
|
||||
April 13, 2015 I. Hrivnacova (analysis-V10-01-08)
|
||||
- Updated to g4tools 1.19.1 (Guy Barrand):
|
||||
csv: handle vector column if using the ntuple_booking way
|
||||
See History_tools for the complete list of modifications.
|
||||
|
||||
April 9, 2015 I. Hrivnacova (analysis-V10-00-44)
|
||||
tag to be included in the patch release:
|
||||
- Updated to g4tools 1.17.2 (Guy Barrand):
|
||||
Changes for Windows (MinGW) - fixing problem #1721 (mainly to change
|
||||
#ifdef WIN32 to #ifdef _MSC_VER, which more clean)
|
||||
|
||||
April 02, 2015 I. Hrivnacova (analysis-V10-01-07)
|
||||
- Updated to g4tools 1.19.0 (Guy Barrand):
|
||||
- Csv handles vector columns
|
||||
- Changes for Windows (MinGW) - fixing problem #1721 (mainly to change
|
||||
#ifdef WIN32 to #ifdef _MSC_VER, which more clean)
|
||||
- Various optimisations to be faster in converting numbers to strings
|
||||
(huge improvements with that around csv and xml tuples)
|
||||
- See History_tools for the complete list of modifications.
|
||||
|
||||
March 18, 2015 I. Hrivnacova (analysis-V10-00-43)
|
||||
tag to be included in the patch release:
|
||||
- Fixed reading XML ntuples with a column of a vector type
|
||||
tools do not support direct use of ntuple_bindings with a vector,
|
||||
use of a temorary sub-ntuple is needed
|
||||
|
||||
March 17, 2015 I. Hrivnacova (analysis-V10-01-06)
|
||||
- Fixed reading XML ntuples with a column of a vector type
|
||||
tools do not support direct use of ntuple_bindings with a vector,
|
||||
use of a temorary sub-ntuple is needed
|
||||
|
||||
March 13, 2015 I. Hrivnacova (analysis-V10-01-05)
|
||||
- Fixed false warnings about unknown column type when an ntuple contains
|
||||
a column of a vector type and is created via ntuple booking
|
||||
|
||||
March 13, 2015 I. Hrivnacova (analysis-V10-01-04)
|
||||
- Fixed G4AnalysisManager::IsActive() - now taken into all Hn & Pn
|
||||
managers
|
||||
|
||||
March 13, 2015 I. Hrivnacova (analysis-V10-00-42)
|
||||
tag to be included in the patch release:
|
||||
- Fixed G4AnalysisManager::IsActive() - now taken into all Hn & Pn
|
||||
managers
|
||||
|
||||
February 20, 2015 I. Hrivnacova (analysis-V10-01-03)
|
||||
- Updated to g4tools 1.18.2 (Guy Barrand):
|
||||
Added code to send/recv histos through MPI;
|
||||
see History_tools for the complete list of modifications.
|
||||
|
||||
February 04, 2015 I. Hrivnacova (analysis-V10-01-02)
|
||||
- Updated to g4tools 1.17.1 (Guy Barrand):
|
||||
Fixed resetting histograms;
|
||||
see History_tools for the complete list of modifications.
|
||||
|
||||
January 21, 2015 I. Hrivnacova (analysis-V10-01-01)
|
||||
- Updated to g4tools 1.17.0 (Guy Barrand):
|
||||
Fixes in the Root files output to be compatible with ROOT 6.02/x;
|
||||
see History_tools for the complete list of modifications.
|
||||
|
||||
December 5, 2014 G. Cosmo (analysis-V10-01-00)
|
||||
- Corrected csv/sources.cmake to include missing file:
|
||||
G4CsvAnalysisReader.icc
|
||||
|
||||
November 24, 2014 I. Hrivnacova (analysis-V10-00-41)
|
||||
- Fixed update to g4tools 1.16.3:
|
||||
the update of g4tools/src/csz_inflate.cc with Coverity fix
|
||||
|
||||
@@ -1,3 +1,213 @@
|
||||
1.26.2 :
|
||||
- test/cpp/viewplot.cpp : more tests to check the sg::plotter nodes reset when producing more pages and files with
|
||||
the same viewer.
|
||||
- test/cpp/viewplot.cpp : regions_style() : have a a_plotter_scale argument to have space between plotters.
|
||||
- test/cpp/viewplot.cpp : HD_style() : set also line_width on title, axis texts to handle properly hershey font
|
||||
if using on large (batch) window.
|
||||
- test/cpp/viewplot.cpp : use tools/xml/wrap_viewplot_style include-embeded style file.
|
||||
- test/cpp/viewplot.cpp : use set_current_plotter_style() instead of style_from_res().
|
||||
|
||||
- tools/xml/viewplot.style, wrap_viewplot_style : a style file (and include-embeded version) for viewplot.cpp.
|
||||
- tools/viewplot : deprecate style_from_res() and replace it with the more explicit set_current_plotter_style().
|
||||
- tools/sg/plots : init_sg() "public" and doing more initializations.
|
||||
- tools/sg/plots : plotter_scale field, to let space between sg::plotter nodes in a grid of plots.
|
||||
- tools/sg/back_area, plotter : border_line_width field, to customize border line width of plotter::infos_box.
|
||||
- tools/sg/style_color : use "parent" typedef.
|
||||
|
||||
1.26.1 :
|
||||
- test/cpp/viewplot.cpp : regions_style() function to adjust per plotter parameters (as margins)
|
||||
in case of multiple regions.
|
||||
- tools/viewplot : set_from_res() : add a verbose arg.
|
||||
|
||||
1.26.0 : prepare freetype2 + modifs and fixes coming from dev in inlib/exlib.
|
||||
- zfunc,wroot/file, ifile, rroot/file, ifile, key : zfunc -> press_func,
|
||||
zip_func -> compress_func, unzip_func -> decompress_func.
|
||||
- vdata : handle (__GNUC__ == 4 && __GNUC_MINOR__ <= 0).
|
||||
- zlib : return Z_DATA_ERROR -> return false.
|
||||
- aida_ntuple, sg/action, xml/loader, styles : std::ostream& out() now const.
|
||||
- lina/box3, box3f : for Windows : avoid the max() in std::numeric_limits<T_t>::max().
|
||||
- rtausmed, rtausmef : use typedef parent.
|
||||
graphics :
|
||||
- test/cpp/use_freetype : supress TOOLS_USE_NATIVE_FREETYPE usage.
|
||||
- test/cpp/viewplot.cpp : have view.style "embedded" (encapsulated in the style_viewplot #include).
|
||||
- sg/text_freetype : #ifndef TOOLS_USE_OUREX_FREETYPE -> #ifndef TOOLS_USE_OUREX_FREETYPE.
|
||||
- sg/bmf : optimize setValues().
|
||||
- sg/* : TOOLS_FIELD_DESC_NODE_CLASS logic.
|
||||
- img : check_gl_limit().
|
||||
|
||||
1.25.0 : material for using freetype rendering in plotting.
|
||||
- test/cpp/viewplot.style, arialbd.ttf, helvetica.ttf : material to render "a la CERN-ROOT".
|
||||
- tools/sg/text_freetype : the sg/node handling freetype.
|
||||
- tools/fmanip, nostream, sep, system : used by sg/text_freetype.
|
||||
- tools/glutess : a pure header version of the tessel code found in mesa/glu. Used by sg/text_freetype.
|
||||
|
||||
1.24.2 :
|
||||
- tools/wcsv_ntuple, tools/wroot/ntuple : have class icol public.
|
||||
- test/cpp/build, use_expat : put expat things common to raxml,viewplot.cpp in use_expat.
|
||||
- tools/mpi/wrmpi :
|
||||
#ifdef TOOLS_USE_MPI_PACK_NOT_CONST
|
||||
char* buffer() {return m_buffer;}
|
||||
#else
|
||||
const char* buffer() const {return m_buffer;}
|
||||
#endif
|
||||
- doc/g4tools_user_api.xml : file ready to go in g4 docbook documentation.
|
||||
- test/cpp/histo.cpp : example code to get all infos of a bin.
|
||||
- tools/sg/render_zb, tools/zb/buffer : handle line width to have thick lines in case of
|
||||
rendering in a high resolution viewport (needed if rendering text with freetype).
|
||||
- test/cpp/viewplot.cpp, use_freetype : prepare the ground for freetype (but not yet ready).
|
||||
|
||||
1.24.1 :
|
||||
- test/cpp/build_f77 : src_dir/close.f -> ./close.f (Ivana request).
|
||||
- src/close.f -> tests/cpp/close.f.
|
||||
- test/cpp/histo.cpp : have profile_[x,y] example code.
|
||||
- tools/histo/slice, sliced : add profile_[x,y] functions.
|
||||
- tools/histo/slice : improve readability, have :
|
||||
template <class H2,class H1>
|
||||
instead of :
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
|
||||
1.24.0 :
|
||||
- wrmpi : have :
|
||||
#ifdef TOOLS_USE_MPI_PACK_NOT_CONST
|
||||
to be able to handle old MPI_[Pack,UnPack] signature without const in the first argument.
|
||||
Not tested since we have not an old MPI at hand!
|
||||
- tools/axis : modification to quiet Coverity.
|
||||
- rroot/key : ifdef TOOLS_USE_CSZ : csz decompression code (coming from old CERN-ROOT) is used in inlib
|
||||
to read very old root file, but this functionality is not needed within g4tools. Then we "ifdef" the related
|
||||
code with TOOLS_USE_CSZ to avoid the csz dependancy by default.
|
||||
Modifications to be in sync with inlib developments but not (yet) fully used in g4tools :
|
||||
- tools/sg/visible_action,base_camera,group,matrix,node,noderef,render_action,separator : handle visible action.
|
||||
- lina/box3, box3f : have the template base box3 class.
|
||||
- fileis, file_format : handle wrl extension.
|
||||
- img : various optimizations in image concatenation.
|
||||
|
||||
1.23.1 :
|
||||
- tools/mpi directory with an implementation of the toos/impi_world and tools/histo/hmpi interfaces.
|
||||
- test/cpp/dummy_mpi.h, hmpi, mpi_world, wrmpi moved under tools/mpi.
|
||||
- tools/histo/hmpi : comm_rank(), comm_size() methods to quiet Ivana :-).
|
||||
- tools/hplot, sg/cube, sg/primitive_visitor, sg/text_hershey : minor corrections to quiet Coverity.
|
||||
|
||||
1.23.0 :
|
||||
- tools/impi_world : interface to the mpi toolkit and global functions (MPI_Init, MPI_Comm_rank, etc...).
|
||||
- test/cpp/mpi_world : implementation of the upper.
|
||||
- test/cpp/mpi.cpp : example of usage of mpi_world and the interface.
|
||||
- tools/histp/hmpi : rank() getter.
|
||||
- tools/smatch, vpair, xml/styles, xml_style, test/cpp/viewplot.cpp : prepare the ground for plot style files.
|
||||
- tools/lina/geom3, line, plane, mat, MATCOM, vec3, vec2f : modifs coming from inlib/exlib developments that
|
||||
should have, in principle, no impact on the rest of g4tools.
|
||||
|
||||
1.22.1 :
|
||||
- viewplot : open_file(), write_pate(), close_file() methods. To write multiple pages in a file.
|
||||
See test/cpp/viewplot.cpp for an example.
|
||||
- viewplot : plot(p1d). See test/cpp/viewplot.cpp for an example.
|
||||
|
||||
1.22.0 : revisit structure for plotting related code.
|
||||
- Have tools/[sg,lina,io,zb] directories to contain this code (instead of tools/plot/...).
|
||||
Extra lite files related to plotting and put under tools :
|
||||
HEADER, axis, cmemT, colorf, cstr, glprims, hershey, hls, hplot, img
|
||||
mathf, out_error, viewplot, wps.
|
||||
- tools/gzip_buffer renamed tools/zlib. Method gzip_buffer renamed compress_buffer and
|
||||
gunzip_buffer renamed decompress_buffer. In fact we had nothing of gzip in the
|
||||
previous gzip_buffer file ! (I had learn since that in fact gzip is zlib deflate/inflate
|
||||
plus a special header added when writing/reading in for a .gz file. As this header is not used
|
||||
for the root format compression, then it is better to rename things).
|
||||
|
||||
1.21.0 : tools/plot. Revisit #include paths to avoid too much -I when compiling.
|
||||
|
||||
1.20.0 : tools/plot, test/cpp/viewplot.cpp. Add "batch plotting" facility.
|
||||
|
||||
1.19.2 :
|
||||
- wcs_ntuple : constructor with ntuple_booking, rm typedef uint and use uint32.
|
||||
- rcs_ntuple : rm typedef uint which is error-prone and use uint32.
|
||||
|
||||
1.19.1 :
|
||||
- wcs_ntuple : handle vector column if using the ntuple_booking way.
|
||||
|
||||
csv handle vector columns. Windows #ifdef WIN32 -> #ifdef _MSC_VER (more clean).
|
||||
1.19.0 : csv handle vector columns. Windows #ifdef WIN32 -> #ifdef _MSC_VER (more clean).
|
||||
- wcsv_ntuple, rcsv_ntuple, test/cpp/wcsv,rcsv : handle vector columns.
|
||||
- test/cpp/waxml.cpp, wroot.cpp : use num2s.
|
||||
- waxml/histos : handle a global ostringstream to convert numbers; huge optimization.
|
||||
- waxml/ntuple : s_value(string&), instead of returning a string; faster code.
|
||||
- typedefs, vdata, snpf, wroot/date, file, rroot/file : WIN32 -> _MSC_VER.
|
||||
- histo/base_histo : restore the extra_entries() method.
|
||||
- histo/base_cloud, base_histo, dps, xml/element, tree : remove std::string title() method which is inefficient
|
||||
and error prone. Stay only with the "const" one.
|
||||
- histo/h1,h2,h3 : get_histo_data() : use *this instead of parent::base_get_data().
|
||||
- words : have an extra bool a_clear arguments to have the possibility to append words to the output vector.
|
||||
- args : add() : revisit strip logic. Remove some functions (that was only used in OpenScientist).
|
||||
- wroot/file : synchronize() : __MINGW32__ case.
|
||||
- wroot/ifile, rroot/ifile : add const to the out() method.
|
||||
- wroot/wbuf : char_p2s -> charp_out.
|
||||
- wroot/buffer : remove sout()
|
||||
- wroot/directory : long2s -> long_out. Remove sout().
|
||||
- wroot/element, rroot/info : fullName(string&) instead returning a string.
|
||||
- sout : use an object.
|
||||
- raxml : const for cls,path,name() string getters.
|
||||
- pointer : handle the case of machines on which a pointer does not match a long.
|
||||
- cids : ids for vector of basic types.
|
||||
- file : revisit the is_hippo() logic.
|
||||
- hbook/ntuple : to<> -> numas.
|
||||
- b2s, num2s, snum : revisit string to number conversion to have faster code.
|
||||
|
||||
1.18.2 : revisit mpi code related code :
|
||||
- test/cpp/wrmpi, hmpi : concrete implementation of abstract tools/impi, histo/hmpi.
|
||||
- test/cpp/dummy_mpi.h : in case of not having an mpi implementation.
|
||||
- tools/histo/hmpi to abstract the send/receive of a bunch of histos.
|
||||
- tools/histo/hd2mpi : to pack/unpack histo_data, profile_data by using impi..
|
||||
- tools/impi abstract class to abstrac MPI pack/unpacking.
|
||||
- remote tools/mpi directory.
|
||||
|
||||
1.18.1 :
|
||||
- test/cpp/use_mpi : have -DTOOLS_USE_NATIVE_MPI in case we have a MPI around.
|
||||
- tools/mpi/hd2mpi : have :
|
||||
#ifdef TOOLS_USE_NATIVE_MPI
|
||||
#include <mpi.h>
|
||||
#else
|
||||
#include "dummy/mpi.h"
|
||||
#endif
|
||||
to use dummy/mpi.h in case there is MPI implementation around.
|
||||
- tools/mpi/dummy/mpi.h : a dummy mpi.h to compile (and link test/cpp/mpi.cpp) in case there is no MPI around.
|
||||
- tools/mpi/hs2mpi : std::cout -> a_out.
|
||||
- test/cpp/mpi.cc : test the return of MPI_Init().
|
||||
- test/cpp/rroot.cpp : delete dir when finished with it.
|
||||
|
||||
1.18.0 : have code to send/recv histos through MPI. Have histo_data inheritance protected in base_histo. Fix some root streamers.
|
||||
- wcsv_histo, rcsv_histo : handle #plane_Sxyw for h2,h3.
|
||||
- wcsv_histo : revisit due to the fact that hist_data is no more publicly inherited by histos.
|
||||
|
||||
- test/cpp/rcsv.C renamed read_wcsv_csv.C.
|
||||
- test/cpp/wcsv.cpp : produce now a wcsv.csv file (instead of out.csv).
|
||||
- test/cpp/rroot.C renamed read_wroot_root.C.
|
||||
- test/cpp/wroot.cpp : out.root -> wroot.root : to help knowing from which program a .root comes from.
|
||||
|
||||
- rroot/streamers : h2, h3 : read fTsumxy,xz,yz and put on m_in_range_plane_Sxyw.
|
||||
- wroot/streamers : p1, p2 : revisit to save m_bin_Svw at the right place.
|
||||
- wroot/streamers : h2, h3 : save fTsumxy,xz,yz.
|
||||
- wroot/streamers : revisit due to the fact that hist_data is no more publicly inherited by histos.
|
||||
- wroot/to : write_histos() : to write a vector of histos at once in a directory.
|
||||
- wroot/element, infos : classes streamer_[short,uint,int,float,double,stat_t,bool] : for a better handling of the offsets.
|
||||
|
||||
- histo/base_histo : public -> protected for hist_data inheritance.
|
||||
- histo/slice : set m_in_range_plane_Sxyw to zero.
|
||||
- histo/h1,h2,h3,p1,p2 : in fill() handle m_in_range_plane_Sxyw.
|
||||
- histo/histo_data, base_histo, b1, b2, b3 : handle m_in_range_plane_Sxyw to save "fTsumxy,xz,xy" for H2, H3 at the root format.
|
||||
|
||||
- tools/histo/histos : to clear a std::vector of histos.
|
||||
- test/cpp/mpi.cpp, build, use_mpi : to test histo send/recv through mpi.
|
||||
- tools/mpi directory.
|
||||
|
||||
- other modifs due to cosmetic or to modifs in inlib/exlib but not used in tools.
|
||||
|
||||
1.17.1 : revisit the usage of std::vector::resize(), have assign() if needed (for exa in histo::reset()) :
|
||||
- tools/array, tools/histo/[base_histo,histo_data,p1,p2,profile_data], tools/rroot/streamers : revisit reset().
|
||||
|
||||
1.17.0 :
|
||||
- tools/wroot/infos : fixes in the streamer infos in order to read .root files with CERN-ROOT/6.02.03 :
|
||||
In TTree fScaleFactor -> fScalefactor.
|
||||
Replace the streamer_basic_type(OBJECT_ANY) to streamer_object_any(...).
|
||||
- rm CVS directories (no more needed since g4tools handled in git).
|
||||
|
||||
1.16.3 :
|
||||
- tools/rroot/ntuple : add also "id casting" in tools::rroot::ntuple::column<T> and column_element<T>.
|
||||
- tools/rcsv_ntuple : Windows : rcsv.cpp crashed. It came from a lack of "id casting" in the
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4CsvAnalysisManager.hh 85025 2014-10-23 09:57:57Z gcosmo $
|
||||
// $Id: G4CsvAnalysisManager.hh 92972 2015-09-23 14:36:03Z gcosmo $
|
||||
|
||||
// The main manager for Csv analysis.
|
||||
// It delegates most of functions to the object specific managers.
|
||||
@@ -33,80 +33,31 @@
|
||||
#ifndef G4CsvAnalysisManager_h
|
||||
#define G4CsvAnalysisManager_h 1
|
||||
|
||||
|
||||
#include "G4VAnalysisManager.hh"
|
||||
#include "G4CsvNtupleDescription.hh"
|
||||
#include "G4ToolsAnalysisManager.hh"
|
||||
#include "globals.hh"
|
||||
|
||||
#include "tools/histo/h1d"
|
||||
#include "tools/histo/h2d"
|
||||
#include "tools/histo/h3d"
|
||||
#include "tools/histo/p1d"
|
||||
#include "tools/histo/p2d"
|
||||
#include "tools/wcsv_ntuple"
|
||||
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class G4H1ToolsManager;
|
||||
class G4H2ToolsManager;
|
||||
class G4H3ToolsManager;
|
||||
class G4P1ToolsManager;
|
||||
class G4P2ToolsManager;
|
||||
class G4CsvFileManager;
|
||||
class G4CsvNtupleManager;
|
||||
|
||||
class G4CsvAnalysisManager : public G4VAnalysisManager
|
||||
class G4CsvAnalysisManager : public G4ToolsAnalysisManager
|
||||
{
|
||||
public:
|
||||
G4CsvAnalysisManager(G4bool isMaster = true);
|
||||
explicit G4CsvAnalysisManager(G4bool isMaster = true);
|
||||
~G4CsvAnalysisManager();
|
||||
|
||||
// static methods
|
||||
static G4CsvAnalysisManager* Instance();
|
||||
static G4bool IsInstance();
|
||||
|
||||
// Access methods
|
||||
tools::histo::h1d* GetH1(G4int id, G4bool warn = true,
|
||||
G4bool onlyIfActive = true) const;
|
||||
tools::histo::h2d* GetH2(G4int id, G4bool warn = true,
|
||||
G4bool onlyIfActive = true) const;
|
||||
tools::histo::h3d* GetH3(G4int id, G4bool warn = true,
|
||||
G4bool onlyIfActive = true) const;
|
||||
tools::histo::p1d* GetP1(G4int id, G4bool warn = true,
|
||||
G4bool onlyIfActive = true) const;
|
||||
tools::histo::p2d* GetP2(G4int id, G4bool warn = true,
|
||||
G4bool onlyIfActive = true) const;
|
||||
|
||||
tools::wcsv::ntuple* GetNtuple() const;
|
||||
tools::wcsv::ntuple* GetNtuple(G4int ntupleId) const;
|
||||
|
||||
// Iterators
|
||||
std::vector<tools::histo::h1d*>::iterator BeginH1();
|
||||
std::vector<tools::histo::h1d*>::iterator EndH1();
|
||||
std::vector<tools::histo::h1d*>::const_iterator BeginConstH1() const;
|
||||
std::vector<tools::histo::h1d*>::const_iterator EndConstH1() const;
|
||||
|
||||
std::vector<tools::histo::h2d*>::iterator BeginH2();
|
||||
std::vector<tools::histo::h2d*>::iterator EndH2();
|
||||
std::vector<tools::histo::h2d*>::const_iterator BeginConstH2() const;
|
||||
std::vector<tools::histo::h2d*>::const_iterator EndConstH2() const;
|
||||
|
||||
std::vector<tools::histo::h3d*>::iterator BeginH3();
|
||||
std::vector<tools::histo::h3d*>::iterator EndH3();
|
||||
std::vector<tools::histo::h3d*>::const_iterator BeginConstH3() const;
|
||||
std::vector<tools::histo::h3d*>::const_iterator EndConstH3() const;
|
||||
|
||||
std::vector<tools::histo::p1d*>::iterator BeginP1();
|
||||
std::vector<tools::histo::p1d*>::iterator EndP1();
|
||||
std::vector<tools::histo::p1d*>::const_iterator BeginConstP1() const;
|
||||
std::vector<tools::histo::p1d*>::const_iterator EndConstP1() const;
|
||||
|
||||
std::vector<tools::histo::p2d*>::iterator BeginP2();
|
||||
std::vector<tools::histo::p2d*>::iterator EndP2();
|
||||
std::vector<tools::histo::p2d*>::const_iterator BeginConstP2() const;
|
||||
std::vector<tools::histo::p2d*>::const_iterator EndConstP2() const;
|
||||
|
||||
std::vector<tools::wcsv::ntuple*>::iterator BeginNtuple();
|
||||
std::vector<tools::wcsv::ntuple*>::iterator EndNtuple();
|
||||
std::vector<tools::wcsv::ntuple*>::const_iterator BeginConstNtuple() const;
|
||||
@@ -118,9 +69,10 @@ class G4CsvAnalysisManager : public G4VAnalysisManager
|
||||
|
||||
protected:
|
||||
// virtual methods from base class
|
||||
virtual G4bool OpenFileImpl(const G4String& fileName);
|
||||
virtual G4bool WriteImpl();
|
||||
virtual G4bool CloseFileImpl();
|
||||
virtual G4bool OpenFileImpl(const G4String& fileName) final;
|
||||
virtual G4bool WriteImpl() final;
|
||||
virtual G4bool CloseFileImpl() final;
|
||||
virtual G4bool IsOpenFileImpl() const final;
|
||||
|
||||
private:
|
||||
// static data members
|
||||
@@ -130,6 +82,10 @@ class G4CsvAnalysisManager : public G4VAnalysisManager
|
||||
|
||||
// methods
|
||||
//
|
||||
template <typename T>
|
||||
G4bool WriteT(const std::vector<T*>& htVector,
|
||||
const std::vector<G4HnInformation*>& hnVector,
|
||||
const G4String& hnType);
|
||||
G4bool WriteH1();
|
||||
G4bool WriteH2();
|
||||
G4bool WriteH3();
|
||||
@@ -139,14 +95,8 @@ class G4CsvAnalysisManager : public G4VAnalysisManager
|
||||
G4bool Reset();
|
||||
|
||||
// data members
|
||||
//
|
||||
G4H1ToolsManager* fH1Manager;
|
||||
G4H2ToolsManager* fH2Manager;
|
||||
G4H3ToolsManager* fH3Manager;
|
||||
G4P1ToolsManager* fP1Manager;
|
||||
G4P2ToolsManager* fP2Manager;
|
||||
G4CsvNtupleManager* fNtupleManager;
|
||||
G4CsvFileManager* fFileManager;
|
||||
std::shared_ptr<G4CsvFileManager> fFileManager;
|
||||
};
|
||||
|
||||
#include "G4CsvAnalysisManager.icc"
|
||||
|
||||
@@ -25,51 +25,53 @@
|
||||
//
|
||||
// $Id: G4CsvAnalysisManager.hh 70604 2013-06-03 11:27:06Z ihrivnac $
|
||||
|
||||
#include "G4H1ToolsManager.hh"
|
||||
#include "G4H2ToolsManager.hh"
|
||||
#include "G4H3ToolsManager.hh"
|
||||
#include "G4P1ToolsManager.hh"
|
||||
#include "G4P2ToolsManager.hh"
|
||||
#include "G4CsvNtupleManager.hh"
|
||||
#include "G4CsvFileManager.hh"
|
||||
|
||||
#include "tools/wcsv_histo"
|
||||
|
||||
//_____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline
|
||||
tools::histo::h1d* G4CsvAnalysisManager::GetH1(G4int id, G4bool warn,
|
||||
G4bool onlyIfActive) const
|
||||
G4bool G4CsvAnalysisManager::WriteT(const std::vector<T*>& htVector,
|
||||
const std::vector<G4HnInformation*>& hnVector,
|
||||
const G4String& hnType)
|
||||
{
|
||||
return fH1Manager->GetH1(id, warn, onlyIfActive);
|
||||
}
|
||||
for ( G4int i=0; i<G4int(htVector.size()); ++i ) {
|
||||
auto info = hnVector[i];
|
||||
auto activation = info->GetActivation();
|
||||
auto name = info->GetName();
|
||||
// skip writing if activation is enabled and H1 is inactivated
|
||||
if ( fState.GetIsActivation() && ( ! activation ) ) continue;
|
||||
auto ht = htVector[i];
|
||||
auto fileName = fFileManager->GetHnFileName(hnType, name);
|
||||
std::ofstream hnFile(fileName);
|
||||
|
||||
auto result
|
||||
= tools::wcsv::hto(hnFile, ht->s_cls(), *ht);
|
||||
if ( ! result ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "saving " << hnType << " " << name << " failed";
|
||||
G4Exception("G4CsvAnalysisManager::Write()",
|
||||
"Analysis_W022", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
hnFile.close();
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL1() )
|
||||
fState.GetVerboseL1()->Message("write", "file", fileName);
|
||||
#endif
|
||||
fFileManager->LockHistoDirectoryName();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
tools::histo::h2d* G4CsvAnalysisManager::GetH2(G4int id, G4bool warn,
|
||||
G4bool onlyIfActive) const
|
||||
inline
|
||||
G4bool G4CsvAnalysisManager::IsOpenFileImpl() const
|
||||
{
|
||||
return fH2Manager->GetH2(id, warn, onlyIfActive);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
tools::histo::h3d* G4CsvAnalysisManager::GetH3(G4int id, G4bool warn,
|
||||
G4bool onlyIfActive) const
|
||||
{
|
||||
return fH3Manager->GetH3(id, warn, onlyIfActive);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
tools::histo::p1d* G4CsvAnalysisManager::GetP1(G4int id, G4bool warn,
|
||||
G4bool onlyIfActive) const
|
||||
{
|
||||
return fP1Manager->GetP1(id, warn, onlyIfActive);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
tools::histo::p2d* G4CsvAnalysisManager::GetP2(G4int id, G4bool warn,
|
||||
G4bool onlyIfActive) const
|
||||
{
|
||||
return fP2Manager->GetP2(id, warn, onlyIfActive);
|
||||
return fFileManager->IsOpenFile();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
@@ -86,156 +88,6 @@ tools::wcsv::ntuple* G4CsvAnalysisManager::GetNtuple(G4int ntupleId) const
|
||||
return fNtupleManager->GetNtuple(ntupleId);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h1d*>::iterator G4CsvAnalysisManager::BeginH1()
|
||||
{
|
||||
return fH1Manager->BeginH1();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h1d*>::iterator G4CsvAnalysisManager::EndH1()
|
||||
{
|
||||
return fH1Manager->EndH1();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h1d*>::const_iterator
|
||||
G4CsvAnalysisManager::BeginConstH1() const
|
||||
{
|
||||
return fH1Manager->BeginConstH1();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h1d*>::const_iterator
|
||||
G4CsvAnalysisManager::EndConstH1() const
|
||||
{
|
||||
return fH1Manager->EndConstH1();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h2d*>::iterator G4CsvAnalysisManager::BeginH2()
|
||||
{
|
||||
return fH2Manager->BeginH2();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h2d*>::iterator G4CsvAnalysisManager::EndH2()
|
||||
{
|
||||
return fH2Manager->EndH2();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h2d*>::const_iterator
|
||||
G4CsvAnalysisManager::BeginConstH2() const
|
||||
{
|
||||
return fH2Manager->BeginConstH2();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h2d*>::const_iterator
|
||||
G4CsvAnalysisManager::EndConstH2() const
|
||||
{
|
||||
return fH2Manager->EndConstH2();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h3d*>::iterator G4CsvAnalysisManager::BeginH3()
|
||||
{
|
||||
return fH3Manager->BeginH3();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h3d*>::iterator G4CsvAnalysisManager::EndH3()
|
||||
{
|
||||
return fH3Manager->EndH3();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h3d*>::const_iterator
|
||||
G4CsvAnalysisManager::BeginConstH3() const
|
||||
{
|
||||
return fH3Manager->BeginConstH3();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::h3d*>::const_iterator
|
||||
G4CsvAnalysisManager::EndConstH3() const
|
||||
{
|
||||
return fH3Manager->EndConstH3();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::p1d*>::iterator G4CsvAnalysisManager::BeginP1()
|
||||
{
|
||||
return fP1Manager->BeginP1();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::p1d*>::iterator G4CsvAnalysisManager::EndP1()
|
||||
{
|
||||
return fP1Manager->EndP1();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::p1d*>::const_iterator
|
||||
G4CsvAnalysisManager::BeginConstP1() const
|
||||
{
|
||||
return fP1Manager->BeginConstP1();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::p1d*>::const_iterator
|
||||
G4CsvAnalysisManager::EndConstP1() const
|
||||
{
|
||||
return fP1Manager->EndConstP1();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::p2d*>::iterator G4CsvAnalysisManager::BeginP2()
|
||||
{
|
||||
return fP2Manager->BeginP2();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::p2d*>::iterator G4CsvAnalysisManager::EndP2()
|
||||
{
|
||||
return fP2Manager->EndP2();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::p2d*>::const_iterator
|
||||
G4CsvAnalysisManager::BeginConstP2() const
|
||||
{
|
||||
return fP2Manager->BeginConstP2();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::histo::p2d*>::const_iterator
|
||||
G4CsvAnalysisManager::EndConstP2() const
|
||||
{
|
||||
return fP2Manager->EndConstP2();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
std::vector<tools::wcsv::ntuple*>::iterator G4CsvAnalysisManager::BeginNtuple()
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#ifndef G4CsvAnalysisReader_h
|
||||
#define G4CsvAnalysisReader_h 1
|
||||
|
||||
#include "G4VAnalysisReader.hh"
|
||||
#include "G4ToolsAnalysisReader.hh"
|
||||
#include "globals.hh"
|
||||
|
||||
#include "tools/histo/h1d"
|
||||
@@ -51,45 +51,34 @@ class G4P2ToolsManager;
|
||||
class G4CsvRNtupleManager;
|
||||
class G4CsvRFileManager;
|
||||
|
||||
class G4CsvAnalysisReader : public G4VAnalysisReader
|
||||
class G4CsvAnalysisReader : public G4ToolsAnalysisReader
|
||||
{
|
||||
public:
|
||||
G4CsvAnalysisReader(G4bool isMaster = true);
|
||||
explicit G4CsvAnalysisReader(G4bool isMaster = true);
|
||||
virtual ~G4CsvAnalysisReader();
|
||||
|
||||
// static methods
|
||||
static G4CsvAnalysisReader* Instance();
|
||||
|
||||
// Access methods
|
||||
tools::histo::h1d* GetH1(G4int id, G4bool warn = true) const;
|
||||
tools::histo::h2d* GetH2(G4int id, G4bool warn = true) const;
|
||||
tools::histo::h3d* GetH3(G4int id, G4bool warn = true) const;
|
||||
tools::histo::p1d* GetP1(G4int id, G4bool warn = true) const;
|
||||
tools::histo::p2d* GetP2(G4int id, G4bool warn = true) const;
|
||||
tools::rcsv::ntuple* GetNtuple() const;
|
||||
tools::rcsv::ntuple* GetNtuple(G4int ntupleId) const;
|
||||
using G4VAnalysisReader::GetNtuple;
|
||||
|
||||
protected:
|
||||
// virtual methods from base class
|
||||
virtual G4int ReadH1Impl(const G4String& h1Name,
|
||||
const G4String& fileName,
|
||||
G4bool isUserFileName);
|
||||
virtual G4int ReadH2Impl(const G4String& h1Name,
|
||||
const G4String& fileName,
|
||||
G4bool isUserFileName);
|
||||
virtual G4int ReadH3Impl(const G4String& h1Name,
|
||||
const G4String& fileName,
|
||||
G4bool isUserFileName);
|
||||
virtual G4int ReadP1Impl(const G4String& h1Name,
|
||||
const G4String& fileName,
|
||||
G4bool isUserFileName);
|
||||
virtual G4int ReadP2Impl(const G4String& h1Name,
|
||||
const G4String& fileName,
|
||||
G4bool isUserFileName);
|
||||
virtual G4int ReadNtupleImpl(const G4String& ntupleName,
|
||||
const G4String& fileName,
|
||||
G4bool isUserFileName);
|
||||
virtual G4int ReadH1Impl(const G4String& h1Name, const G4String& fileName,
|
||||
G4bool isUserFileName) final;
|
||||
virtual G4int ReadH2Impl(const G4String& h2Name, const G4String& fileName,
|
||||
G4bool isUserFileName) final;
|
||||
virtual G4int ReadH3Impl(const G4String& h3Name, const G4String& fileName,
|
||||
G4bool isUserFileName) final;
|
||||
virtual G4int ReadP1Impl(const G4String& p1Name, const G4String& fileName,
|
||||
G4bool isUserFileName) final;
|
||||
virtual G4int ReadP2Impl(const G4String& p2Name, const G4String& fileName,
|
||||
G4bool isUserFileName) final;
|
||||
virtual G4int ReadNtupleImpl(const G4String& ntupleName, const G4String& fileName,
|
||||
G4bool isUserFileName) final;
|
||||
|
||||
private:
|
||||
// static data members
|
||||
@@ -105,11 +94,6 @@ class G4CsvAnalysisReader : public G4VAnalysisReader
|
||||
G4bool Reset();
|
||||
|
||||
// data members
|
||||
G4H1ToolsManager* fH1Manager;
|
||||
G4H2ToolsManager* fH2Manager;
|
||||
G4H3ToolsManager* fH3Manager;
|
||||
G4P1ToolsManager* fP1Manager;
|
||||
G4P2ToolsManager* fP2Manager;
|
||||
G4CsvRNtupleManager* fNtupleManager;
|
||||
G4CsvRFileManager* fFileManager;
|
||||
};
|
||||
|
||||
@@ -27,49 +27,8 @@
|
||||
|
||||
// Author: Ivana Hrivnacova, 05/09/2014 (ivana@ipno.in2p3.fr)
|
||||
|
||||
#include "G4H1ToolsManager.hh"
|
||||
#include "G4H2ToolsManager.hh"
|
||||
#include "G4H3ToolsManager.hh"
|
||||
#include "G4P1ToolsManager.hh"
|
||||
#include "G4P2ToolsManager.hh"
|
||||
#include "G4CsvRNtupleManager.hh"
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
tools::histo::h1d* G4CsvAnalysisReader::GetH1(G4int id, G4bool warn) const
|
||||
{
|
||||
return fH1Manager->GetH1(id, warn, false);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
tools::histo::h2d* G4CsvAnalysisReader::GetH2(G4int id, G4bool warn) const
|
||||
{
|
||||
return fH2Manager->GetH2(id, warn, false);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
tools::histo::h3d* G4CsvAnalysisReader::GetH3(G4int id, G4bool warn) const
|
||||
{
|
||||
return fH3Manager->GetH3(id, warn, false);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
tools::histo::p1d* G4CsvAnalysisReader::GetP1(G4int id, G4bool warn) const
|
||||
{
|
||||
return fP1Manager->GetP1(id, warn, false);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
tools::histo::p2d* G4CsvAnalysisReader::GetP2(G4int id, G4bool warn) const
|
||||
{
|
||||
return fP2Manager->GetP2(id, warn, false);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
inline
|
||||
tools::rcsv::ntuple* G4CsvAnalysisReader::GetNtuple() const
|
||||
{
|
||||
|
||||
@@ -32,27 +32,30 @@
|
||||
#ifndef G4CsvFileManager_h
|
||||
#define G4CsvFileManager_h 1
|
||||
|
||||
|
||||
#include "G4VFileManager.hh"
|
||||
#include "G4CsvNtupleDescription.hh"
|
||||
#include "G4TNtupleDescription.hh"
|
||||
#include "globals.hh"
|
||||
|
||||
#include <fstream>
|
||||
#include "tools/wcsv_ntuple"
|
||||
|
||||
class G4CsvFileManager : public G4VFileManager
|
||||
{
|
||||
public:
|
||||
G4CsvFileManager(const G4AnalysisManagerState& state);
|
||||
explicit G4CsvFileManager(const G4AnalysisManagerState& state);
|
||||
~G4CsvFileManager();
|
||||
|
||||
// Type aliases
|
||||
using NtupleType = tools::wcsv::ntuple;
|
||||
using NtupleDescriptionType = G4TNtupleDescription<NtupleType>;
|
||||
|
||||
// Methods to manipulate files
|
||||
virtual G4bool OpenFile(const G4String& fileName);
|
||||
virtual G4bool WriteFile();
|
||||
virtual G4bool CloseFile();
|
||||
virtual G4bool OpenFile(const G4String& fileName) final;
|
||||
virtual G4bool WriteFile() final;
|
||||
virtual G4bool CloseFile() final;
|
||||
|
||||
// Specific methods for files per objects
|
||||
G4bool CreateNtupleFile(G4CsvNtupleDescription* ntupleDescription);
|
||||
G4bool CloseNtupleFile(G4CsvNtupleDescription* ntupleDescription);
|
||||
G4bool CreateNtupleFile(NtupleDescriptionType* ntupleDescription);
|
||||
G4bool CloseNtupleFile(NtupleDescriptionType* ntupleDescription);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,148 +32,65 @@
|
||||
#ifndef G4CsvNtupleManager_h
|
||||
#define G4CsvNtupleManager_h 1
|
||||
|
||||
|
||||
#include "G4VNtupleManager.hh"
|
||||
#include "G4TNtupleManager.hh"
|
||||
#include "globals.hh"
|
||||
|
||||
#include "tools/wcsv_ntuple"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
class G4CsvFileManager;
|
||||
struct G4CsvNtupleDescription;
|
||||
|
||||
class G4CsvNtupleManager : public G4VNtupleManager
|
||||
class G4CsvNtupleManager : public G4TNtupleManager<tools::wcsv::ntuple>
|
||||
{
|
||||
friend class G4CsvAnalysisManager;
|
||||
|
||||
protected:
|
||||
G4CsvNtupleManager(const G4AnalysisManagerState& state);
|
||||
public:
|
||||
explicit G4CsvNtupleManager(const G4AnalysisManagerState& state);
|
||||
~G4CsvNtupleManager();
|
||||
|
||||
|
||||
private:
|
||||
// Types alias
|
||||
using NtupleType = tools::wcsv::ntuple;
|
||||
using NtupleDescriptionType = G4TNtupleDescription<NtupleType>;
|
||||
|
||||
// Functions specific to the output type
|
||||
//
|
||||
|
||||
// Methods to manipulate ntuples
|
||||
void CreateNtuplesFromBooking();
|
||||
G4bool IsEmpty() const;
|
||||
G4bool Reset();
|
||||
|
||||
// Set methods
|
||||
void SetFileManager(G4CsvFileManager* fileManager);
|
||||
void SetFileManager(std::shared_ptr<G4CsvFileManager> fileManager);
|
||||
|
||||
// Access methods
|
||||
tools::wcsv::ntuple* GetNtuple() const;
|
||||
tools::wcsv::ntuple* GetNtuple(G4int ntupleId) const;
|
||||
|
||||
// Iterators
|
||||
std::vector<tools::wcsv::ntuple*>::iterator BeginNtuple();
|
||||
std::vector<tools::wcsv::ntuple*>::iterator EndNtuple();
|
||||
std::vector<tools::wcsv::ntuple*>::const_iterator BeginConstNtuple() const;
|
||||
std::vector<tools::wcsv::ntuple*>::const_iterator EndConstNtuple() const;
|
||||
|
||||
// Access to ntuple vector (needed for Write())
|
||||
const std::vector<G4CsvNtupleDescription*>& GetNtupleDescriptionVector() const;
|
||||
const std::vector<NtupleDescriptionType*>& GetNtupleDescriptionVector() const;
|
||||
|
||||
// Functions independent from the output type
|
||||
//
|
||||
|
||||
// Methods to create ntuples
|
||||
virtual G4int CreateNtuple(const G4String& name, const G4String& title);
|
||||
// Create columns in the last created ntuple
|
||||
virtual G4int CreateNtupleIColumn(
|
||||
const G4String& name, std::vector<int>* vector);
|
||||
virtual G4int CreateNtupleFColumn(
|
||||
const G4String& name, std::vector<float>* vector);
|
||||
virtual G4int CreateNtupleDColumn(
|
||||
const G4String& name, std::vector<double>* vector);
|
||||
virtual G4int CreateNtupleSColumn(const G4String& name);
|
||||
virtual void FinishNtuple();
|
||||
// Create columns in the ntuple with given id
|
||||
virtual G4int CreateNtupleIColumn(G4int ntupleId,
|
||||
const G4String& name, std::vector<int>* vector);
|
||||
virtual G4int CreateNtupleFColumn(G4int ntupleId,
|
||||
const G4String& name, std::vector<float>* vector);
|
||||
virtual G4int CreateNtupleDColumn(G4int ntupleId,
|
||||
const G4String& name, std::vector<double>* vector);
|
||||
virtual G4int CreateNtupleSColumn(G4int ntupleId, const G4String& name);
|
||||
virtual void FinishNtuple(G4int ntupleId);
|
||||
|
||||
// Methods to fill ntuples
|
||||
// Methods for ntuple with id = FirstNtupleId
|
||||
virtual G4bool FillNtupleIColumn(G4int columnId, G4int value);
|
||||
virtual G4bool FillNtupleFColumn(G4int columnId, G4float value);
|
||||
virtual G4bool FillNtupleDColumn(G4int columnId, G4double value);
|
||||
virtual G4bool FillNtupleSColumn(G4int columnId, const G4String& value);
|
||||
virtual G4bool AddNtupleRow();
|
||||
// Methods for ntuple with id > FirstNtupleId (when more ntuples exist)
|
||||
virtual G4bool FillNtupleIColumn(G4int ntupleId, G4int columnId, G4int value);
|
||||
virtual G4bool FillNtupleFColumn(G4int ntupleId, G4int columnId, G4float value);
|
||||
virtual G4bool FillNtupleDColumn(G4int ntupleId, G4int columnId, G4double value);
|
||||
virtual G4bool FillNtupleSColumn(G4int ntupleId, G4int columnId,
|
||||
const G4String& value);
|
||||
virtual G4bool AddNtupleRow(G4int ntupleId);
|
||||
|
||||
// Access methods
|
||||
virtual G4int GetNofNtuples() const;
|
||||
|
||||
// Csv format specific option
|
||||
void SetIsCommentedHeader(G4bool isCommentedHeader);
|
||||
void SetIsHippoHeader(G4bool isHippoHeader);
|
||||
|
||||
private:
|
||||
// methods
|
||||
// Methods from the templated base class
|
||||
//
|
||||
tools::wcsv::ntuple::column<int>*
|
||||
GetNtupleIColumn(G4int ntupleId, G4int columnId) const;
|
||||
tools::wcsv::ntuple::column<float>*
|
||||
GetNtupleFColumn(G4int ntupleId, G4int columnId) const;
|
||||
tools::wcsv::ntuple::column<double>*
|
||||
GetNtupleDColumn(G4int ntupleId, G4int columnId) const;
|
||||
tools::wcsv::ntuple::column<std::string>*
|
||||
GetNtupleSColumn(G4int ntupleId, G4int columnId) const;
|
||||
virtual void CreateTNtuple(
|
||||
NtupleDescriptionType* ntupleDescription,
|
||||
const G4String& name, const G4String& title) final;
|
||||
virtual void CreateTNtupleFromBooking(
|
||||
NtupleDescriptionType* ntupleDescription) final;
|
||||
|
||||
virtual G4CsvNtupleDescription* GetNtupleInFunction(G4int id,
|
||||
G4String function,
|
||||
G4bool warn = true,
|
||||
G4bool onlyIfActive = true) const;
|
||||
|
||||
G4bool WriteHeader(tools::wcsv::ntuple* ntuple) const;
|
||||
virtual void FinishTNtuple(
|
||||
NtupleDescriptionType* ntupleDescription) final;
|
||||
|
||||
G4bool WriteHeader(NtupleType* ntuple) const;
|
||||
|
||||
// data members
|
||||
//
|
||||
G4CsvFileManager* fFileManager;
|
||||
std::vector<G4CsvNtupleDescription*> fNtupleDescriptionVector;
|
||||
std::vector<tools::wcsv::ntuple*> fNtupleVector;
|
||||
std::shared_ptr<G4CsvFileManager> fFileManager;
|
||||
G4bool fIsCommentedHeader;
|
||||
G4bool fIsHippoHeader;
|
||||
};
|
||||
|
||||
// inline functions
|
||||
|
||||
inline void G4CsvNtupleManager::SetFileManager(G4CsvFileManager* fileManager)
|
||||
inline void
|
||||
G4CsvNtupleManager::SetFileManager(std::shared_ptr<G4CsvFileManager> fileManager)
|
||||
{ fFileManager = fileManager; }
|
||||
|
||||
inline std::vector<tools::wcsv::ntuple*>::iterator
|
||||
G4CsvNtupleManager::BeginNtuple()
|
||||
{ return fNtupleVector.begin(); }
|
||||
|
||||
inline std::vector<tools::wcsv::ntuple*>::iterator
|
||||
G4CsvNtupleManager::EndNtuple()
|
||||
{ return fNtupleVector.end(); }
|
||||
|
||||
inline std::vector<tools::wcsv::ntuple*>::const_iterator
|
||||
G4CsvNtupleManager::BeginConstNtuple() const
|
||||
{ return fNtupleVector.begin(); }
|
||||
|
||||
inline std::vector<tools::wcsv::ntuple*>::const_iterator
|
||||
G4CsvNtupleManager::EndConstNtuple() const
|
||||
{ return fNtupleVector.end(); }
|
||||
|
||||
inline G4int G4CsvNtupleManager::GetNofNtuples() const
|
||||
{ return fNtupleDescriptionVector.size(); }
|
||||
|
||||
inline const std::vector<G4CsvNtupleDescription*>&
|
||||
inline const std::vector<G4TNtupleDescription<tools::wcsv::ntuple>*>&
|
||||
G4CsvNtupleManager::GetNtupleDescriptionVector() const
|
||||
{ return fNtupleDescriptionVector; }
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class G4AnalysisManagerState;
|
||||
class G4CsvRFileManager : public G4BaseFileManager
|
||||
{
|
||||
public:
|
||||
G4CsvRFileManager(const G4AnalysisManagerState& state);
|
||||
explicit G4CsvRFileManager(const G4AnalysisManagerState& state);
|
||||
~G4CsvRFileManager();
|
||||
|
||||
// Methods to manipulate input files
|
||||
|
||||
@@ -53,15 +53,14 @@ struct G4CsvRNtupleDescription
|
||||
delete fNtuple; // CHECK
|
||||
}
|
||||
|
||||
// deleted copy constructor
|
||||
G4CsvRNtupleDescription(const G4CsvRNtupleDescription& rhs) = delete;
|
||||
// deleted assignement operator
|
||||
G4CsvRNtupleDescription& operator=(G4CsvRNtupleDescription& rhs) = delete;
|
||||
|
||||
tools::rcsv::ntuple* fNtuple;
|
||||
tools::ntuple_binding* fNtupleBinding;
|
||||
G4bool fIsInitialized;
|
||||
|
||||
private:
|
||||
// disabled (not implemented) copy constructor
|
||||
G4CsvRNtupleDescription(const G4CsvRNtupleDescription& rhs);
|
||||
// disabled (not implemented) assignement operator
|
||||
G4CsvRNtupleDescription& operator=(G4CsvRNtupleDescription& rhs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,7 @@ class G4CsvRNtupleManager : public G4VRNtupleManager
|
||||
friend class G4CsvAnalysisReader;
|
||||
|
||||
protected:
|
||||
G4CsvRNtupleManager(const G4AnalysisManagerState& state);
|
||||
explicit G4CsvRNtupleManager(const G4AnalysisManagerState& state);
|
||||
virtual ~G4CsvRNtupleManager();
|
||||
|
||||
// Methods to manipulate ntuples
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: g4csv_defs.hh 84303 2014-10-13 13:14:26Z gcosmo $
|
||||
// $Id: g4csv_defs.hh 92688 2015-09-14 07:01:13Z gcosmo $
|
||||
|
||||
// Author: Ivana Hrivnacova, 15/06/2011 (ivana@ipno.in2p3.fr)
|
||||
|
||||
@@ -42,40 +42,40 @@
|
||||
namespace G4Csv {
|
||||
|
||||
// H1 types
|
||||
typedef tools::histo::h1d G4AnaH1; // keep for backward compatibility
|
||||
typedef tools::histo::h1d G4H1;
|
||||
typedef std::vector<tools::histo::h1d*>::iterator G4H1Iterator;
|
||||
typedef std::vector<tools::histo::h1d*>::const_iterator G4H1ConstIterator;
|
||||
using G4AnaH1 = tools::histo::h1d; // keep for backward compatibility
|
||||
using G4H1 = tools::histo::h1d;
|
||||
using G4H1Iterator = std::vector<tools::histo::h1d*>::iterator;
|
||||
using G4H1ConstIterator = std::vector<tools::histo::h1d*>::const_iterator;
|
||||
|
||||
// H2 types
|
||||
typedef tools::histo::h2d G4AnaH2; // keep for backward compatibility
|
||||
typedef tools::histo::h2d G4H2;
|
||||
typedef std::vector<tools::histo::h2d*>::iterator G4H2Iterator;
|
||||
typedef std::vector<tools::histo::h2d*>::const_iterator G4H2ConstIterator;
|
||||
using G4AnaH2 = tools::histo::h2d; // keep for backward compatibility
|
||||
using G4H2 = tools::histo::h2d;
|
||||
using G4H2Iterator = std::vector<tools::histo::h2d*>::iterator;
|
||||
using G4H2ConstIterator = std::vector<tools::histo::h2d*>::const_iterator;
|
||||
|
||||
// H3 types
|
||||
typedef tools::histo::h3d G4H3;
|
||||
typedef std::vector<tools::histo::h3d*>::iterator G4H3Iterator;
|
||||
typedef std::vector<tools::histo::h3d*>::const_iterator G4H3ConstIterator;
|
||||
using G4H3 = tools::histo::h3d;
|
||||
using G4H3Iterator = std::vector<tools::histo::h3d*>::iterator;
|
||||
using G4H3ConstIterator = std::vector<tools::histo::h3d*>::const_iterator;
|
||||
|
||||
// P1 types
|
||||
typedef tools::histo::p1d G4P1;
|
||||
typedef std::vector<tools::histo::p1d*>::iterator G4P1Iterator;
|
||||
typedef std::vector<tools::histo::p1d*>::const_iterator G4P1ConstIterator;
|
||||
using G4P1 = tools::histo::p1d;
|
||||
using G4P1Iterator = std::vector<tools::histo::p1d*>::iterator;
|
||||
using G4P1ConstIterator = std::vector<tools::histo::p1d*>::const_iterator;
|
||||
|
||||
// P2 types
|
||||
typedef tools::histo::p2d G4P2;
|
||||
typedef std::vector<tools::histo::p2d*>::iterator G4P2Iterator;
|
||||
typedef std::vector<tools::histo::p2d*>::const_iterator G4P2ConstIterator;
|
||||
using G4P2 = tools::histo::p2d;
|
||||
using G4P2Iterator = std::vector<tools::histo::p2d*>::iterator;
|
||||
using G4P2ConstIterator = std::vector<tools::histo::p2d*>::const_iterator;
|
||||
|
||||
// Ntuple types
|
||||
typedef tools::wcsv::ntuple G4Ntuple;
|
||||
typedef std::vector<tools::wcsv::ntuple*>::iterator G4NtupleIterator;
|
||||
typedef std::vector<tools::wcsv::ntuple*>::const_iterator G4NtupleConstIterator;
|
||||
using G4Ntuple = tools::wcsv::ntuple;
|
||||
using G4NtupleIterator = std::vector<tools::wcsv::ntuple*>::iterator;
|
||||
using G4NtupleConstIterator = std::vector<tools::wcsv::ntuple*>::const_iterator;
|
||||
|
||||
// Managers
|
||||
typedef G4CsvAnalysisManager G4AnalysisManager;
|
||||
typedef G4CsvAnalysisReader G4AnalysisReader;
|
||||
using G4AnalysisManager = G4CsvAnalysisManager;
|
||||
using G4AnalysisReader = G4CsvAnalysisReader;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# Generated on : 15/07/2013
|
||||
#
|
||||
# $Id: sources.cmake 85025 2014-10-23 09:57:57Z gcosmo $
|
||||
# $Id: sources.cmake 92688 2015-09-14 07:01:13Z gcosmo $
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@@ -36,7 +36,6 @@ GEANT4_DEFINE_MODULE(NAME G4csv
|
||||
G4CsvAnalysisReader.hh
|
||||
G4CsvAnalysisReader.icc
|
||||
G4CsvFileManager.hh
|
||||
G4CsvNtupleDescription.hh
|
||||
G4CsvNtupleManager.hh
|
||||
G4CsvRFileManager.hh
|
||||
G4CsvRNtupleDescription.hh
|
||||
|
||||
@@ -23,17 +23,12 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4CsvAnalysisManager.cc 85317 2014-10-27 15:58:15Z gcosmo $
|
||||
// $Id: G4CsvAnalysisManager.cc 93815 2015-11-02 11:32:20Z gcosmo $
|
||||
|
||||
// Author: Ivana Hrivnacova, 18/06/2013 (ivana@ipno.in2p3.fr)
|
||||
|
||||
#include "G4CsvAnalysisManager.hh"
|
||||
#include "G4CsvFileManager.hh"
|
||||
#include "G4H1ToolsManager.hh"
|
||||
#include "G4H2ToolsManager.hh"
|
||||
#include "G4H3ToolsManager.hh"
|
||||
#include "G4P1ToolsManager.hh"
|
||||
#include "G4P2ToolsManager.hh"
|
||||
#include "G4CsvNtupleManager.hh"
|
||||
#include "G4AnalysisVerbose.hh"
|
||||
#include "G4AnalysisManagerState.hh"
|
||||
@@ -41,8 +36,6 @@
|
||||
#include "G4Threading.hh"
|
||||
#include "G4AutoLock.hh"
|
||||
|
||||
#include "tools/wcsv_histo"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// mutex in a file scope
|
||||
@@ -60,30 +53,31 @@ namespace {
|
||||
G4Mutex mergeP2Mutex = G4MUTEX_INITIALIZER;
|
||||
}
|
||||
|
||||
G4CsvAnalysisManager* G4CsvAnalysisManager::fgMasterInstance = 0;
|
||||
G4ThreadLocal G4CsvAnalysisManager* G4CsvAnalysisManager::fgInstance = 0;
|
||||
G4CsvAnalysisManager* G4CsvAnalysisManager::fgMasterInstance = nullptr;
|
||||
G4ThreadLocal G4CsvAnalysisManager* G4CsvAnalysisManager::fgInstance = nullptr;
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4CsvAnalysisManager* G4CsvAnalysisManager::Instance()
|
||||
{
|
||||
if ( fgInstance == 0 ) {
|
||||
if ( fgInstance == nullptr ) {
|
||||
G4bool isMaster = ! G4Threading::IsWorkerThread();
|
||||
fgInstance = new G4CsvAnalysisManager(isMaster);
|
||||
}
|
||||
|
||||
return fgInstance;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvAnalysisManager::IsInstance()
|
||||
{
|
||||
return ( fgInstance != 0 );
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4CsvAnalysisManager::G4CsvAnalysisManager(G4bool isMaster)
|
||||
: G4VAnalysisManager("Csv", isMaster),
|
||||
fH1Manager(0),
|
||||
fH2Manager(0),
|
||||
fH3Manager(0),
|
||||
fP1Manager(0),
|
||||
fP2Manager(0),
|
||||
fNtupleManager(0),
|
||||
fFileManager(0)
|
||||
: G4ToolsAnalysisManager("Csv", isMaster),
|
||||
fNtupleManager(nullptr),
|
||||
fFileManager(nullptr)
|
||||
{
|
||||
if ( ( isMaster && fgMasterInstance ) || ( fgInstance ) ) {
|
||||
G4ExceptionDescription description;
|
||||
@@ -96,24 +90,12 @@ G4CsvAnalysisManager::G4CsvAnalysisManager(G4bool isMaster)
|
||||
|
||||
if ( isMaster ) fgMasterInstance = this;
|
||||
fgInstance = this;
|
||||
|
||||
// Create managers
|
||||
fH1Manager = new G4H1ToolsManager(fState);
|
||||
fH2Manager = new G4H2ToolsManager(fState);
|
||||
fH3Manager = new G4H3ToolsManager(fState);
|
||||
fP1Manager = new G4P1ToolsManager(fState);
|
||||
fP2Manager = new G4P2ToolsManager(fState);
|
||||
fNtupleManager = new G4CsvNtupleManager(fState);
|
||||
fFileManager = new G4CsvFileManager(fState);
|
||||
fFileManager = std::make_shared<G4CsvFileManager>(fState);
|
||||
fNtupleManager->SetFileManager(fFileManager);
|
||||
// The managers will be deleted by the base class
|
||||
|
||||
// Set managers to base class
|
||||
SetH1Manager(fH1Manager);
|
||||
SetH2Manager(fH2Manager);
|
||||
SetH3Manager(fH3Manager);
|
||||
SetP1Manager(fP1Manager);
|
||||
SetP2Manager(fP2Manager);
|
||||
// Set managers to base class which takes then their ownreship
|
||||
SetNtupleManager(fNtupleManager);
|
||||
SetFileManager(fFileManager);
|
||||
}
|
||||
@@ -121,8 +103,8 @@ G4CsvAnalysisManager::G4CsvAnalysisManager(G4bool isMaster)
|
||||
//_____________________________________________________________________________
|
||||
G4CsvAnalysisManager::~G4CsvAnalysisManager()
|
||||
{
|
||||
if ( fState.GetIsMaster() ) fgMasterInstance = 0;
|
||||
fgInstance = 0;
|
||||
if ( fState.GetIsMaster() ) fgMasterInstance = nullptr;
|
||||
fgInstance = nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -132,15 +114,14 @@ G4CsvAnalysisManager::~G4CsvAnalysisManager()
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvAnalysisManager::CloseNtupleFiles()
|
||||
{
|
||||
const std::vector<G4CsvNtupleDescription*>& ntupleVector
|
||||
auto ntupleVector
|
||||
= fNtupleManager->GetNtupleDescriptionVector();
|
||||
|
||||
// Close ntuple files
|
||||
std::vector<G4CsvNtupleDescription*>::const_iterator it;
|
||||
for (it = ntupleVector.begin(); it != ntupleVector.end(); it++ ) {
|
||||
fFileManager->CloseNtupleFile((*it));
|
||||
for ( auto ntupleDescription : ntupleVector) {
|
||||
fFileManager->CloseNtupleFile(ntupleDescription);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -153,44 +134,19 @@ G4bool G4CsvAnalysisManager::CloseNtupleFiles()
|
||||
// private methods
|
||||
//
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvAnalysisManager::WriteH1()
|
||||
{
|
||||
const std::vector<tools::histo::h1d*>& h1Vector
|
||||
= fH1Manager->GetH1Vector();
|
||||
const std::vector<G4HnInformation*>& hnVector
|
||||
= fH1Manager->GetHnVector();
|
||||
auto h1Vector = fH1Manager->GetH1Vector();
|
||||
auto hnVector = fH1Manager->GetHnVector();
|
||||
|
||||
if ( ! h1Vector.size() ) return true;
|
||||
|
||||
auto result = true;
|
||||
|
||||
if ( ! G4Threading::IsWorkerThread() ) {
|
||||
|
||||
for ( G4int i=0; i<G4int(h1Vector.size()); ++i ) {
|
||||
G4HnInformation* info = hnVector[i];
|
||||
G4bool activation = info->GetActivation();
|
||||
G4String name = info->GetName();
|
||||
// skip writing if activation is enabled and H1 is inactivated
|
||||
if ( fState.GetIsActivation() && ( ! activation ) ) continue;
|
||||
tools::histo::h1d* h1 = h1Vector[i];
|
||||
G4String fileName = fFileManager->GetHnFileName("h1", name);
|
||||
std::ofstream hnFile(fileName);
|
||||
|
||||
G4bool result
|
||||
= tools::wcsv::hto(hnFile, h1->s_cls(), *h1);
|
||||
if ( ! result ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "saving histogram " << name << " failed";
|
||||
G4Exception("G4CsvAnalysisManager::Write()",
|
||||
"Analysis_W022", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
hnFile.close();
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL1() )
|
||||
fState.GetVerboseL1()->Message("write", "file", fileName);
|
||||
#endif
|
||||
fFileManager->LockHistoDirectoryName();
|
||||
}
|
||||
result = WriteT(h1Vector, hnVector, "h1");
|
||||
}
|
||||
else {
|
||||
// The worker manager just adds its histograms to the master
|
||||
@@ -200,47 +156,21 @@ G4bool G4CsvAnalysisManager::WriteH1()
|
||||
lH1.unlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvAnalysisManager::WriteH2()
|
||||
{
|
||||
const std::vector<tools::histo::h2d*>& h2Vector
|
||||
= fH2Manager->GetH2Vector();
|
||||
const std::vector<G4HnInformation*>& hnVector
|
||||
= fH2Manager->GetHnVector();
|
||||
auto h2Vector = fH2Manager->GetH2Vector();
|
||||
auto hnVector = fH2Manager->GetHnVector();
|
||||
|
||||
if ( ! h2Vector.size() ) return true;
|
||||
|
||||
auto result = true;
|
||||
|
||||
if ( ! G4Threading::IsWorkerThread() ) {
|
||||
|
||||
// h2 histograms
|
||||
for ( G4int i=0; i<G4int(h2Vector.size()); ++i ) {
|
||||
G4HnInformation* info = hnVector[i];
|
||||
G4bool activation = info->GetActivation();
|
||||
G4String name = info->GetName();
|
||||
// skip writing if inactivated
|
||||
if ( fState.GetIsActivation() && ( ! activation ) ) continue;
|
||||
tools::histo::h2d* h2 = h2Vector[i];
|
||||
G4String fileName = fFileManager->GetHnFileName("h2", name);
|
||||
std::ofstream hnFile(fileName);
|
||||
G4bool result
|
||||
= tools::wcsv::hto(hnFile, h2->s_cls(), *h2);
|
||||
if ( ! result ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "saving histogram " << name << " failed";
|
||||
G4Exception("G4CsvAnalysisManager::Write()",
|
||||
"Analysis_W022", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
hnFile.close();
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL1() )
|
||||
fState.GetVerboseL1()->Message("write", "file", fileName);
|
||||
#endif
|
||||
fFileManager->LockHistoDirectoryName();
|
||||
}
|
||||
result = WriteT(h2Vector, hnVector, "h2");
|
||||
}
|
||||
else {
|
||||
// The worker manager just adds its histograms to the master
|
||||
@@ -250,47 +180,21 @@ G4bool G4CsvAnalysisManager::WriteH2()
|
||||
lH2.unlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvAnalysisManager::WriteH3()
|
||||
{
|
||||
const std::vector<tools::histo::h3d*>& h3Vector
|
||||
= fH3Manager->GetH3Vector();
|
||||
const std::vector<G4HnInformation*>& hnVector
|
||||
= fH3Manager->GetHnVector();
|
||||
auto h3Vector = fH3Manager->GetH3Vector();
|
||||
auto hnVector = fH3Manager->GetHnVector();
|
||||
|
||||
if ( ! h3Vector.size() ) return true;
|
||||
|
||||
auto result = true;
|
||||
|
||||
if ( ! G4Threading::IsWorkerThread() ) {
|
||||
|
||||
// h3 histograms
|
||||
for ( G4int i=0; i<G4int(h3Vector.size()); ++i ) {
|
||||
G4HnInformation* info = hnVector[i];
|
||||
G4bool activation = info->GetActivation();
|
||||
G4String name = info->GetName();
|
||||
// skip writing if inactivated
|
||||
if ( fState.GetIsActivation() && ( ! activation ) ) continue;
|
||||
tools::histo::h3d* h3 = h3Vector[i];
|
||||
G4String fileName = fFileManager->GetHnFileName("h3", name);
|
||||
std::ofstream hnFile(fileName);
|
||||
G4bool result
|
||||
= tools::wcsv::hto(hnFile, h3->s_cls(), *h3);
|
||||
if ( ! result ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "saving histogram " << name << " failed";
|
||||
G4Exception("G4CsvAnalysisManager::Write()",
|
||||
"Analysis_W022", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
hnFile.close();
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL1() )
|
||||
fState.GetVerboseL1()->Message("write", "file", fileName);
|
||||
#endif
|
||||
fFileManager->LockHistoDirectoryName();
|
||||
}
|
||||
result = WriteT(h3Vector, hnVector, "h3");
|
||||
}
|
||||
else {
|
||||
// The worker manager just adds its histograms to the master
|
||||
@@ -300,47 +204,22 @@ G4bool G4CsvAnalysisManager::WriteH3()
|
||||
lH3.unlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvAnalysisManager::WriteP1()
|
||||
{
|
||||
const std::vector<tools::histo::p1d*>& p1Vector
|
||||
= fP1Manager->GetP1Vector();
|
||||
const std::vector<G4HnInformation*>& hnVector
|
||||
= fP1Manager->GetHnVector();
|
||||
auto p1Vector = fP1Manager->GetP1Vector();
|
||||
auto hnVector = fP1Manager->GetHnVector();
|
||||
|
||||
if ( ! p1Vector.size() ) return true;
|
||||
|
||||
if ( ! G4Threading::IsWorkerThread() ) {
|
||||
auto result = true;
|
||||
|
||||
for ( G4int i=0; i<G4int(p1Vector.size()); ++i ) {
|
||||
G4HnInformation* info = hnVector[i];
|
||||
G4bool activation = info->GetActivation();
|
||||
G4String name = info->GetName();
|
||||
// skip writing if activation is enabled and P1 is inactivated
|
||||
if ( fState.GetIsActivation() && ( ! activation ) ) continue;
|
||||
tools::histo::p1d* p1 = p1Vector[i];
|
||||
G4String fileName = fFileManager->GetHnFileName("p1", name);
|
||||
std::ofstream hnFile(fileName);
|
||||
G4bool result
|
||||
= tools::wcsv::pto(hnFile, p1->s_cls(), *p1);
|
||||
if ( ! result ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "saving profile " << name << " failed";
|
||||
G4Exception("G4CsvAnalysisManager::Write()",
|
||||
"Analysis_W022", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
hnFile.close();
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL1() )
|
||||
fState.GetVerboseL1()->Message("write", "file", fileName);
|
||||
#endif
|
||||
fFileManager->LockProfileDirectoryName();
|
||||
}
|
||||
}
|
||||
if ( ! G4Threading::IsWorkerThread() ) {
|
||||
result = WriteT(p1Vector, hnVector, "p1");
|
||||
}
|
||||
else {
|
||||
// The worker manager just adds its profiles to the master
|
||||
// This operation needs a lock
|
||||
@@ -349,47 +228,22 @@ G4bool G4CsvAnalysisManager::WriteP1()
|
||||
lP1.unlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvAnalysisManager::WriteP2()
|
||||
{
|
||||
const std::vector<tools::histo::p2d*>& p2Vector
|
||||
= fP2Manager->GetP2Vector();
|
||||
const std::vector<G4HnInformation*>& hnVector
|
||||
= fP2Manager->GetHnVector();
|
||||
auto p2Vector = fP2Manager->GetP2Vector();
|
||||
auto hnVector = fP2Manager->GetHnVector();
|
||||
|
||||
if ( ! p2Vector.size() ) return true;
|
||||
|
||||
if ( ! G4Threading::IsWorkerThread() ) {
|
||||
auto result = true;
|
||||
|
||||
for ( G4int i=0; i<G4int(p2Vector.size()); ++i ) {
|
||||
G4HnInformation* info = hnVector[i];
|
||||
G4bool activation = info->GetActivation();
|
||||
G4String name = info->GetName();
|
||||
// skip writing if activation is enabled and P2 is inactivated
|
||||
if ( fState.GetIsActivation() && ( ! activation ) ) continue;
|
||||
tools::histo::p2d* p2 = p2Vector[i];
|
||||
G4String fileName = fFileManager->GetHnFileName("p2", name);
|
||||
std::ofstream hnFile(fileName);
|
||||
G4bool result
|
||||
= tools::wcsv::pto(hnFile, p2->s_cls(), *p2);
|
||||
if ( ! result ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "saving profile " << name << " failed";
|
||||
G4Exception("G4CsvAnalysisManager::Write()",
|
||||
"Analysis_W022", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
hnFile.close();
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL1() )
|
||||
fState.GetVerboseL1()->Message("write", "file", fileName);
|
||||
#endif
|
||||
fFileManager->LockProfileDirectoryName();
|
||||
}
|
||||
}
|
||||
if ( ! G4Threading::IsWorkerThread() ) {
|
||||
result = WriteT(p2Vector, hnVector, "p2");
|
||||
}
|
||||
else {
|
||||
// The worker manager just adds its profiles to the master
|
||||
// This operation needs a lock
|
||||
@@ -398,7 +252,7 @@ G4bool G4CsvAnalysisManager::WriteP2()
|
||||
lP2.unlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
@@ -406,24 +260,12 @@ G4bool G4CsvAnalysisManager::Reset()
|
||||
{
|
||||
// Reset histograms and ntuple
|
||||
|
||||
G4bool finalResult = true;
|
||||
auto finalResult = true;
|
||||
|
||||
G4bool result = fH1Manager->Reset();
|
||||
auto result = G4ToolsAnalysisManager::Reset();
|
||||
finalResult = finalResult && result;
|
||||
|
||||
result = fH2Manager->Reset();
|
||||
finalResult = finalResult && result;
|
||||
|
||||
result = fH3Manager->Reset();
|
||||
finalResult = finalResult && result;
|
||||
|
||||
result = fP1Manager->Reset();
|
||||
finalResult = finalResult && result;
|
||||
|
||||
result = fP2Manager->Reset();
|
||||
finalResult = finalResult && result;
|
||||
|
||||
result = fNtupleManager->Reset();
|
||||
result = fNtupleManager->Reset(true);
|
||||
finalResult = finalResult && result;
|
||||
|
||||
return finalResult;
|
||||
@@ -432,8 +274,8 @@ G4bool G4CsvAnalysisManager::Reset()
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvAnalysisManager::OpenFileImpl(const G4String& fileName)
|
||||
{
|
||||
G4bool finalResult = true;
|
||||
G4bool result = fFileManager->SetFileName(fileName);
|
||||
auto finalResult = true;
|
||||
auto result = fFileManager->SetFileName(fileName);
|
||||
finalResult = finalResult && result;
|
||||
|
||||
// Only lock file name in file manager
|
||||
@@ -454,7 +296,7 @@ G4bool G4CsvAnalysisManager::OpenFileImpl(const G4String& fileName)
|
||||
G4bool G4CsvAnalysisManager::WriteImpl()
|
||||
{
|
||||
// nothing to be done for Csv file
|
||||
G4bool finalResult = true;
|
||||
auto finalResult = true;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() )
|
||||
@@ -477,7 +319,7 @@ G4bool G4CsvAnalysisManager::WriteImpl()
|
||||
}
|
||||
|
||||
// H1
|
||||
G4bool result = WriteH1();
|
||||
auto result = WriteH1();
|
||||
finalResult = finalResult && result;
|
||||
|
||||
// H2
|
||||
@@ -506,8 +348,8 @@ G4bool G4CsvAnalysisManager::WriteImpl()
|
||||
//}
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() )
|
||||
fState.GetVerboseL4()
|
||||
if ( fState.GetVerboseL1() )
|
||||
fState.GetVerboseL1()
|
||||
->Message("write", "files", "", finalResult);
|
||||
#endif
|
||||
|
||||
@@ -517,22 +359,17 @@ G4bool G4CsvAnalysisManager::WriteImpl()
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvAnalysisManager::CloseFileImpl()
|
||||
{
|
||||
G4bool finalResult = true;
|
||||
auto finalResult = true;
|
||||
|
||||
// Unlock file name only
|
||||
G4bool result = fFileManager->CloseFile();
|
||||
auto result = fFileManager->CloseFile();
|
||||
finalResult = finalResult && result;
|
||||
|
||||
// Histogram and profile files are created/closed indivudually for each
|
||||
// object in WriteHn{Pn] function
|
||||
|
||||
// Close ntuple files
|
||||
if ( ( ! G4Threading::IsMultithreadedApplication() ) ||
|
||||
( ! fState.GetIsMaster() ) ) {
|
||||
// In sequential mode or in MT mode only on workers
|
||||
result = CloseNtupleFiles();
|
||||
finalResult = finalResult && result;
|
||||
}
|
||||
// In sequential mode or in MT mode only on workers
|
||||
result = CloseNtupleFiles();
|
||||
finalResult = finalResult && result;
|
||||
|
||||
// reset data
|
||||
result = Reset();
|
||||
|
||||
@@ -29,11 +29,6 @@
|
||||
|
||||
#include "G4CsvAnalysisReader.hh"
|
||||
#include "G4CsvRFileManager.hh"
|
||||
#include "G4H1ToolsManager.hh"
|
||||
#include "G4H2ToolsManager.hh"
|
||||
#include "G4H3ToolsManager.hh"
|
||||
#include "G4P1ToolsManager.hh"
|
||||
#include "G4P2ToolsManager.hh"
|
||||
#include "G4CsvRNtupleManager.hh"
|
||||
#include "G4CsvRNtupleDescription.hh"
|
||||
#include "G4AnalysisVerbose.hh"
|
||||
@@ -48,8 +43,8 @@
|
||||
|
||||
using namespace G4Analysis;
|
||||
|
||||
G4CsvAnalysisReader* G4CsvAnalysisReader::fgMasterInstance = 0;
|
||||
G4ThreadLocal G4CsvAnalysisReader* G4CsvAnalysisReader::fgInstance = 0;
|
||||
G4CsvAnalysisReader* G4CsvAnalysisReader::fgMasterInstance = nullptr;
|
||||
G4ThreadLocal G4CsvAnalysisReader* G4CsvAnalysisReader::fgInstance = nullptr;
|
||||
|
||||
//
|
||||
// utility functions
|
||||
@@ -66,7 +61,7 @@ void* ReadObject(std::istream& hnFile,
|
||||
tools::rcsv::histo handler(hnFile);
|
||||
std::string objectTypeInFile;
|
||||
void* object;
|
||||
G4bool verbose = false;
|
||||
auto verbose = false;
|
||||
if ( ! handler.read(G4cout, objectTypeInFile, object, verbose) ) {
|
||||
G4ExceptionDescription description;
|
||||
description
|
||||
@@ -74,8 +69,8 @@ void* ReadObject(std::istream& hnFile,
|
||||
<< "Cannot get "<< objectType << " in file " << fileName;
|
||||
G4String inFunctionFull = "G4CsvAnalysisReader::";
|
||||
inFunctionFull.append(inFunction);
|
||||
G4Exception(inFunctionFull, "Analysis_WR011", JustWarning, description);
|
||||
return 0;
|
||||
G4Exception(inFunctionFull, "Analysis_WRnullptr11", JustWarning, description);
|
||||
return nullptr;
|
||||
}
|
||||
if ( objectTypeInFile != objectType ) {
|
||||
G4ExceptionDescription description;
|
||||
@@ -86,7 +81,7 @@ void* ReadObject(std::istream& hnFile,
|
||||
G4String inFunctionFull = "G4CsvAnalysisReader::";
|
||||
inFunctionFull.append(inFunction);
|
||||
G4Exception(inFunctionFull, "Analysis_WR011", JustWarning, description);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return object;
|
||||
@@ -97,7 +92,7 @@ void* ReadObject(std::istream& hnFile,
|
||||
//_____________________________________________________________________________
|
||||
G4CsvAnalysisReader* G4CsvAnalysisReader::Instance()
|
||||
{
|
||||
if ( fgInstance == 0 ) {
|
||||
if ( fgInstance == nullptr ) {
|
||||
G4bool isMaster = ! G4Threading::IsWorkerThread();
|
||||
fgInstance = new G4CsvAnalysisReader(isMaster);
|
||||
}
|
||||
@@ -107,14 +102,9 @@ G4CsvAnalysisReader* G4CsvAnalysisReader::Instance()
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4CsvAnalysisReader::G4CsvAnalysisReader(G4bool isMaster)
|
||||
: G4VAnalysisReader("Csv", isMaster),
|
||||
fH1Manager(0),
|
||||
fH2Manager(0),
|
||||
fH3Manager(0),
|
||||
fP1Manager(0),
|
||||
fP2Manager(0),
|
||||
fNtupleManager(0),
|
||||
fFileManager(0)
|
||||
: G4ToolsAnalysisReader("Csv", isMaster),
|
||||
fNtupleManager(nullptr),
|
||||
fFileManager(nullptr)
|
||||
{
|
||||
if ( ( isMaster && fgMasterInstance ) || ( fgInstance ) ) {
|
||||
G4ExceptionDescription description;
|
||||
@@ -129,21 +119,11 @@ G4CsvAnalysisReader::G4CsvAnalysisReader(G4bool isMaster)
|
||||
fgInstance = this;
|
||||
|
||||
// Create managers
|
||||
fH1Manager = new G4H1ToolsManager(fState);
|
||||
fH2Manager = new G4H2ToolsManager(fState);
|
||||
fH3Manager = new G4H3ToolsManager(fState);
|
||||
fP1Manager = new G4P1ToolsManager(fState);
|
||||
fP2Manager = new G4P2ToolsManager(fState);
|
||||
fNtupleManager = new G4CsvRNtupleManager(fState);
|
||||
fFileManager = new G4CsvRFileManager(fState);
|
||||
// The managers will be deleted by the base class
|
||||
|
||||
// Set managers to base class
|
||||
SetH1Manager(fH1Manager);
|
||||
SetH2Manager(fH2Manager);
|
||||
SetH3Manager(fH3Manager);
|
||||
SetP1Manager(fP1Manager);
|
||||
SetP2Manager(fP2Manager);
|
||||
SetNtupleManager(fNtupleManager);
|
||||
SetFileManager(fFileManager);
|
||||
}
|
||||
@@ -151,8 +131,8 @@ G4CsvAnalysisReader::G4CsvAnalysisReader(G4bool isMaster)
|
||||
//_____________________________________________________________________________
|
||||
G4CsvAnalysisReader::~G4CsvAnalysisReader()
|
||||
{
|
||||
if ( fState.GetIsMaster() ) fgMasterInstance = 0;
|
||||
fgInstance = 0;
|
||||
if ( fState.GetIsMaster() ) fgMasterInstance = nullptr;
|
||||
fgInstance = nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -179,12 +159,9 @@ G4bool G4CsvAnalysisReader::Reset()
|
||||
{
|
||||
// Reset histograms and ntuple
|
||||
|
||||
G4bool finalResult = true;
|
||||
auto finalResult = true;
|
||||
|
||||
G4bool result = fH1Manager->Reset();
|
||||
finalResult = finalResult && result;
|
||||
|
||||
result = fH2Manager->Reset();
|
||||
auto result = G4ToolsAnalysisReader::Reset();
|
||||
finalResult = finalResult && result;
|
||||
|
||||
result = fNtupleManager->Reset();
|
||||
@@ -208,7 +185,7 @@ G4int G4CsvAnalysisReader::ReadH1Impl(const G4String& h1Name,
|
||||
#endif
|
||||
|
||||
// open file
|
||||
G4String h1FileName = GetHnFileName("h1", h1Name, fileName, isUserFileName);
|
||||
auto h1FileName = GetHnFileName("h1", h1Name, fileName, isUserFileName);
|
||||
std::ifstream hnFile(h1FileName);
|
||||
if ( ! hnFile.is_open() ) {
|
||||
G4ExceptionDescription description;
|
||||
@@ -227,9 +204,8 @@ G4int G4CsvAnalysisReader::ReadH1Impl(const G4String& h1Name,
|
||||
= ReadObject(hnFile, tools::histo::h1d::s_class(), h1FileName, "ReadH1Impl");
|
||||
if ( ! object ) return kInvalidId;
|
||||
|
||||
tools::histo::h1d* h1
|
||||
= static_cast<tools::histo::h1d*>(object);
|
||||
G4int id = fH1Manager->AddH1(h1Name, h1);
|
||||
auto h1 = static_cast<tools::histo::h1d*>(object);
|
||||
auto id = fH1Manager->AddH1(h1Name, h1);
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL2() )
|
||||
@@ -250,7 +226,7 @@ G4int G4CsvAnalysisReader::ReadH2Impl(const G4String& h2Name,
|
||||
#endif
|
||||
|
||||
// open file
|
||||
G4String h2FileName = GetHnFileName("h2", h2Name, fileName, isUserFileName);
|
||||
auto h2FileName = GetHnFileName("h2", h2Name, fileName, isUserFileName);
|
||||
std::ifstream hnFile(h2FileName);
|
||||
if ( ! hnFile.is_open() ) {
|
||||
G4ExceptionDescription description;
|
||||
@@ -269,9 +245,8 @@ G4int G4CsvAnalysisReader::ReadH2Impl(const G4String& h2Name,
|
||||
= ReadObject(hnFile, tools::histo::h2d::s_class(), h2FileName, "ReadH2Impl");
|
||||
if ( ! object ) return kInvalidId;
|
||||
|
||||
tools::histo::h2d* h2
|
||||
= static_cast<tools::histo::h2d*>(object);
|
||||
G4int id = fH2Manager->AddH2(h2Name, h2);
|
||||
auto h2 = static_cast<tools::histo::h2d*>(object);
|
||||
auto id = fH2Manager->AddH2(h2Name, h2);
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL2() )
|
||||
@@ -292,7 +267,7 @@ G4int G4CsvAnalysisReader::ReadH3Impl(const G4String& h3Name,
|
||||
#endif
|
||||
|
||||
// open file
|
||||
G4String h3FileName = GetHnFileName("h3", h3Name, fileName, isUserFileName);
|
||||
auto h3FileName = GetHnFileName("h3", h3Name, fileName, isUserFileName);
|
||||
std::ifstream hnFile(h3FileName);
|
||||
if ( ! hnFile.is_open() ) {
|
||||
G4ExceptionDescription description;
|
||||
@@ -311,9 +286,8 @@ G4int G4CsvAnalysisReader::ReadH3Impl(const G4String& h3Name,
|
||||
= ReadObject(hnFile, tools::histo::h3d::s_class(), h3FileName, "ReadH3Impl");
|
||||
if ( ! object ) return kInvalidId;
|
||||
|
||||
tools::histo::h3d* h3
|
||||
= static_cast<tools::histo::h3d*>(object);
|
||||
G4int id = fH3Manager->AddH3(h3Name, h3);
|
||||
auto h3 = static_cast<tools::histo::h3d*>(object);
|
||||
auto id = fH3Manager->AddH3(h3Name, h3);
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL2() )
|
||||
@@ -353,9 +327,8 @@ G4int G4CsvAnalysisReader::ReadP1Impl(const G4String& p1Name,
|
||||
= ReadObject(hnFile, tools::histo::p1d::s_class(), fileName, "ReadP1Impl");
|
||||
if ( ! object ) return kInvalidId;
|
||||
|
||||
tools::histo::p1d* p1
|
||||
= static_cast<tools::histo::p1d*>(object);
|
||||
G4int id = fP1Manager->AddP1(p1Name, p1);
|
||||
auto p1 = static_cast<tools::histo::p1d*>(object);
|
||||
auto id = fP1Manager->AddP1(p1Name, p1);
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL2() )
|
||||
@@ -395,9 +368,8 @@ G4int G4CsvAnalysisReader::ReadP2Impl(const G4String& p2Name,
|
||||
= ReadObject(hnFile, tools::histo::p2d::s_class(), p2FileName, "ReadP2Impl");
|
||||
if ( ! object ) return kInvalidId;
|
||||
|
||||
tools::histo::p2d* p2
|
||||
= static_cast<tools::histo::p2d*>(object);
|
||||
G4int id = fP2Manager->AddP2(p2Name, p2);
|
||||
auto p2 = static_cast<tools::histo::p2d*>(object);
|
||||
auto id = fP2Manager->AddP2(p2Name, p2);
|
||||
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
@@ -428,13 +400,11 @@ G4int G4CsvAnalysisReader::ReadNtupleImpl(const G4String& ntupleName,
|
||||
|
||||
// Open file
|
||||
if ( ! fFileManager->OpenRFile(fullFileName) ) return kInvalidId;
|
||||
std::ifstream* ntupleFile
|
||||
= fFileManager->GetRFile(fullFileName);
|
||||
auto ntupleFile = fFileManager->GetRFile(fullFileName);
|
||||
|
||||
// Create ntuple
|
||||
tools::rcsv::ntuple* rntuple = new tools::rcsv::ntuple(*ntupleFile);
|
||||
G4int id
|
||||
= fNtupleManager->SetNtuple(new G4CsvRNtupleDescription(rntuple));
|
||||
auto rntuple = new tools::rcsv::ntuple(*ntupleFile);
|
||||
auto id = fNtupleManager->SetNtuple(new G4CsvRNtupleDescription(rntuple));
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL2() )
|
||||
|
||||
@@ -33,13 +33,11 @@
|
||||
//_____________________________________________________________________________
|
||||
G4CsvFileManager::G4CsvFileManager(const G4AnalysisManagerState& state)
|
||||
: G4VFileManager(state)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4CsvFileManager::~G4CsvFileManager()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
//
|
||||
// public methods
|
||||
@@ -53,6 +51,7 @@ G4bool G4CsvFileManager::OpenFile(const G4String& fileName)
|
||||
|
||||
fLockFileName = true;
|
||||
fLockNtupleDirectoryName = true;
|
||||
fIsOpenFile = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -68,14 +67,15 @@ G4bool G4CsvFileManager::WriteFile()
|
||||
G4bool G4CsvFileManager::CloseFile()
|
||||
{
|
||||
fLockFileName = false;
|
||||
fIsOpenFile = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvFileManager::CreateNtupleFile(
|
||||
G4CsvNtupleDescription* ntupleDescription)
|
||||
G4TNtupleDescription<tools::wcsv::ntuple>* ntupleDescription)
|
||||
{
|
||||
G4String ntupleName = ntupleDescription->fNtupleBooking->name();
|
||||
G4String ntupleName = ntupleDescription->fNtupleBooking.name();
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() )
|
||||
@@ -83,8 +83,7 @@ G4bool G4CsvFileManager::CreateNtupleFile(
|
||||
->Message("create", "file", GetNtupleFileName(ntupleName));
|
||||
#endif
|
||||
|
||||
std::ofstream* ntupleFile
|
||||
= new std::ofstream(GetNtupleFileName(ntupleName));
|
||||
auto ntupleFile = new std::ofstream(GetNtupleFileName(ntupleName));
|
||||
if ( ntupleFile->fail() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "Cannot open file "
|
||||
@@ -106,9 +105,9 @@ G4bool G4CsvFileManager::CreateNtupleFile(
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvFileManager::CloseNtupleFile(
|
||||
G4CsvNtupleDescription* ntupleDescription)
|
||||
G4TNtupleDescription<tools::wcsv::ntuple>* ntupleDescription)
|
||||
{
|
||||
G4String ntupleName = ntupleDescription->fNtupleBooking->name();
|
||||
G4String ntupleName = ntupleDescription->fNtupleBooking.name();
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() )
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
// Author: Ivana Hrivnacova, 18/06/2013 (ivana@ipno.in2p3.fr)
|
||||
|
||||
#include "G4CsvNtupleManager.hh"
|
||||
#include "G4CsvNtupleDescription.hh"
|
||||
#include "G4CsvFileManager.hh"
|
||||
#include "G4AnalysisManagerState.hh"
|
||||
#include "G4AnalysisUtilities.hh"
|
||||
@@ -39,147 +38,81 @@
|
||||
|
||||
using namespace G4Analysis;
|
||||
|
||||
//
|
||||
// utility methods
|
||||
//
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4CsvNtupleManager::G4CsvNtupleManager(const G4AnalysisManagerState& state)
|
||||
: G4VNtupleManager(state),
|
||||
fFileManager(0),
|
||||
fNtupleDescriptionVector(),
|
||||
fNtupleVector(),
|
||||
: G4TNtupleManager<tools::wcsv::ntuple>(state),
|
||||
fFileManager(nullptr),
|
||||
fIsCommentedHeader(true),
|
||||
fIsHippoHeader(false)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4CsvNtupleManager::~G4CsvNtupleManager()
|
||||
{
|
||||
std::vector<G4CsvNtupleDescription*>::iterator it;
|
||||
for (it = fNtupleDescriptionVector.begin(); it != fNtupleDescriptionVector.end(); it++ ) {
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
{}
|
||||
|
||||
//
|
||||
// private methods
|
||||
//
|
||||
|
||||
//_____________________________________________________________________________
|
||||
tools::wcsv::ntuple::column<int>*
|
||||
G4CsvNtupleManager::GetNtupleIColumn(G4int ntupleId, G4int columnId) const
|
||||
void G4CsvNtupleManager::CreateTNtuple(
|
||||
G4TNtupleDescription<tools::wcsv::ntuple>* ntupleDescription,
|
||||
const G4String& /*name*/, const G4String& title)
|
||||
{
|
||||
G4CsvNtupleDescription* ntupleDecription
|
||||
= GetNtupleInFunction(ntupleId, "GetNtupleIColumn");
|
||||
if ( ! ntupleDecription ) return 0;
|
||||
|
||||
std::map<G4int, tools::wcsv::ntuple::column<int>* >& ntupleIColumnMap
|
||||
= ntupleDecription->fNtupleIColumnMap;
|
||||
std::map<G4int, tools::wcsv::ntuple::column<int>* >::const_iterator it
|
||||
= ntupleIColumnMap.find(columnId);
|
||||
if ( it == ntupleIColumnMap.end() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " does not exist.";
|
||||
G4Exception("G4CsvNtupleManager::GetNtupleIColumn()",
|
||||
"Analysis_W011", JustWarning, description);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
tools::wcsv::ntuple::column<float>*
|
||||
G4CsvNtupleManager::GetNtupleFColumn(G4int ntupleId, G4int columnId) const
|
||||
{
|
||||
G4CsvNtupleDescription* ntupleDecription
|
||||
= GetNtupleInFunction(ntupleId, "GetNtupleFColumn");
|
||||
if ( ! ntupleDecription ) return 0;
|
||||
|
||||
std::map<G4int, tools::wcsv::ntuple::column<float>* >& ntupleFColumnMap
|
||||
= ntupleDecription->fNtupleFColumnMap;
|
||||
std::map<G4int, tools::wcsv::ntuple::column<float>* >::const_iterator it
|
||||
= ntupleFColumnMap.find(columnId);
|
||||
if ( it == ntupleFColumnMap.end() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " does not exist.";
|
||||
G4Exception("G4CsvNtupleManager::GetNtupleFColumn()",
|
||||
"Analysis_W011", JustWarning, description);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
||||
//_____________________________________________________________________________
|
||||
tools::wcsv::ntuple::column<double>*
|
||||
G4CsvNtupleManager::GetNtupleDColumn(G4int ntupleId, G4int columnId) const
|
||||
{
|
||||
G4CsvNtupleDescription* ntupleDecription
|
||||
= GetNtupleInFunction(ntupleId, "GetNtupleDColumn");
|
||||
if ( ! ntupleDecription ) return 0;
|
||||
|
||||
std::map<G4int, tools::wcsv::ntuple::column<double>* >& ntupleDColumnMap
|
||||
= ntupleDecription->fNtupleDColumnMap;
|
||||
std::map<G4int, tools::wcsv::ntuple::column<double>* >::const_iterator it
|
||||
= ntupleDColumnMap.find(columnId);
|
||||
if ( it == ntupleDColumnMap.end() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " does not exist.";
|
||||
G4Exception("G4CsvNtupleManager::GetNtupleDColumn()",
|
||||
"Analysis_W011", JustWarning, description);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
tools::wcsv::ntuple::column<std::string>*
|
||||
G4CsvNtupleManager::GetNtupleSColumn(G4int ntupleId, G4int columnId) const
|
||||
{
|
||||
G4CsvNtupleDescription* ntupleDecription
|
||||
= GetNtupleInFunction(ntupleId, "GetNtupleSColumn");
|
||||
if ( ! ntupleDecription ) return 0;
|
||||
|
||||
std::map<G4int, tools::wcsv::ntuple::column<std::string>* >& ntupleSColumnMap
|
||||
= ntupleDecription->fNtupleSColumnMap;
|
||||
std::map<G4int, tools::wcsv::ntuple::column<std::string>* >::const_iterator it
|
||||
= ntupleSColumnMap.find(columnId);
|
||||
if ( it == ntupleSColumnMap.end() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " does not exist.";
|
||||
G4Exception("G4CsvNtupleManager::GetNtupleSColumn()",
|
||||
"Analysis_W011", JustWarning, description);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4CsvNtupleDescription* G4CsvNtupleManager::GetNtupleInFunction(G4int id,
|
||||
G4String functionName, G4bool warn,
|
||||
G4bool /*onlyIfActive*/) const
|
||||
{
|
||||
G4int index = id - fFirstId;
|
||||
if ( index < 0 || index >= G4int(fNtupleDescriptionVector.size()) ) {
|
||||
if ( warn) {
|
||||
G4String inFunction = "G4CsvNtupleManager::";
|
||||
inFunction += functionName;
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "ntuple " << id << " does not exist.";
|
||||
G4Exception(inFunction, "Analysis_W011", JustWarning, description);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fNtupleDescriptionVector[index];
|
||||
// Create ntuple if the file is open (what means here that
|
||||
// a filename was already set)
|
||||
if ( fFileManager->GetFileName().size() ) {
|
||||
if ( fFileManager->CreateNtupleFile(ntupleDescription) ) {
|
||||
ntupleDescription->fNtuple
|
||||
= new tools::wcsv::ntuple(*(ntupleDescription->fFile));
|
||||
// ntuple object is deleted when closing a file
|
||||
(ntupleDescription->fNtuple)->set_title(title);
|
||||
fNtupleVector.push_back(ntupleDescription->fNtuple);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
void G4CsvNtupleManager::CreateTNtupleFromBooking(
|
||||
G4TNtupleDescription<tools::wcsv::ntuple>* ntupleDescription)
|
||||
{
|
||||
// create a file for this ntuple
|
||||
if ( ! fFileManager->CreateNtupleFile(ntupleDescription) ) return;
|
||||
|
||||
// create ntuple
|
||||
ntupleDescription->fNtuple
|
||||
= new tools::wcsv::ntuple(
|
||||
*(ntupleDescription->fFile), G4cerr, ntupleDescription->fNtupleBooking);
|
||||
fNtupleVector.push_back(ntupleDescription->fNtuple);
|
||||
|
||||
// write header (if activated)
|
||||
if ( ! WriteHeader(ntupleDescription->fNtuple) ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Writing ntuple header has failed. ";
|
||||
G4Exception("G4CsvNtupleManager::CreateNtupleFromBooking()",
|
||||
"Analysis_W021", JustWarning, description);
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
void G4CsvNtupleManager::FinishTNtuple(
|
||||
G4TNtupleDescription<tools::wcsv::ntuple>* ntupleDescription)
|
||||
{
|
||||
// Write header if ntuple already exists
|
||||
if ( ! WriteHeader(ntupleDescription->fNtuple) ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Writing ntuple header has failed. ";
|
||||
G4Exception("G4CsvNtupleManager::FinishTNtuple()",
|
||||
"Analysis_W022", JustWarning, description);
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::WriteHeader(tools::wcsv::ntuple* ntuple) const
|
||||
{
|
||||
@@ -200,648 +133,3 @@ G4bool G4CsvNtupleManager::WriteHeader(tools::wcsv::ntuple* ntuple) const
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// protected methods
|
||||
//
|
||||
|
||||
//_____________________________________________________________________________
|
||||
void G4CsvNtupleManager::CreateNtuplesFromBooking()
|
||||
{
|
||||
// Create ntuple from ntuple_booking.
|
||||
|
||||
// Do not create ntuples on master thread
|
||||
if ( G4Threading::IsMultithreadedApplication() &&
|
||||
fState.GetIsMaster() ) return;
|
||||
|
||||
std::vector<G4CsvNtupleDescription*>::iterator itn;
|
||||
for (itn = fNtupleDescriptionVector.begin(); itn != fNtupleDescriptionVector.end(); itn++ ) {
|
||||
|
||||
tools::ntuple_booking* ntupleBooking = (*itn)->fNtupleBooking;
|
||||
if ( ! ntupleBooking ) continue;
|
||||
|
||||
// Do not create ntuple if it already exists
|
||||
if ( (*itn)->fNtuple ) continue;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() )
|
||||
fState.GetVerboseL4()
|
||||
->Message("create from booking", "ntuple", ntupleBooking->name());
|
||||
#endif
|
||||
|
||||
// create a file for this ntuple
|
||||
if ( ! fFileManager->CreateNtupleFile((*itn)) ) continue;
|
||||
|
||||
// create ntuple
|
||||
(*itn)->fNtuple
|
||||
= new tools::wcsv::ntuple(*((*itn)->fFile), G4cerr, *ntupleBooking);
|
||||
fNtupleVector.push_back((*itn)->fNtuple);
|
||||
|
||||
// write header (if activated)
|
||||
if ( ! WriteHeader((*itn)->fNtuple) ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Writing ntuple header has failed. ";
|
||||
G4Exception("G4CsvNtupleManager::CreateNtupleFromBooking()",
|
||||
"Analysis_W021", JustWarning, description);
|
||||
}
|
||||
|
||||
if ( ntupleBooking->columns().size() ) {
|
||||
// store ntuple columns in local maps
|
||||
const std::vector<tools::column_booking>& columns
|
||||
= ntupleBooking->columns();
|
||||
std::vector<tools::column_booking>::const_iterator it;
|
||||
G4int index = 0;
|
||||
for ( it = columns.begin(); it!=columns.end(); ++it) {
|
||||
if ( it->cls_id() == tools::_cid(int(0) ) ) {
|
||||
(*itn)->fNtupleIColumnMap[index++]
|
||||
= (*itn)->fNtuple->find_column<int>(it->name());
|
||||
}
|
||||
else if ( it->cls_id() == tools::_cid(float(0) ) ) {
|
||||
(*itn)->fNtupleFColumnMap[index++]
|
||||
= (*itn)->fNtuple->find_column<float>(it->name());
|
||||
}
|
||||
else if ( it->cls_id() == tools::_cid(double(0))) {
|
||||
(*itn)->fNtupleDColumnMap[index++]
|
||||
= (*itn)->fNtuple->find_column<double>(it->name());
|
||||
}
|
||||
else if ( it->cls_id() == tools::_cid(std::string(""))) {
|
||||
(*itn)->fNtupleSColumnMap[index++]
|
||||
= (*itn)->fNtuple->find_column<std::string>(it->name());
|
||||
}
|
||||
else {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Unsupported column type " << it->cls_id();
|
||||
G4Exception("G4CsvNtupleManager::CreateNtupleFromBooking()",
|
||||
"Analysis_W002", JustWarning, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL3() )
|
||||
fState.GetVerboseL3()
|
||||
->Message("create from booking", "ntuple", ntupleBooking->name());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::IsEmpty() const
|
||||
{
|
||||
return ! fNtupleDescriptionVector.size();
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::Reset()
|
||||
{
|
||||
std::vector<G4CsvNtupleDescription*>::iterator it;
|
||||
for (it = fNtupleDescriptionVector.begin(); it != fNtupleDescriptionVector.end(); it++ ) {
|
||||
delete (*it)->fNtuple;
|
||||
(*it)->fNtuple = 0;
|
||||
}
|
||||
fNtupleVector.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
tools::wcsv::ntuple* G4CsvNtupleManager::GetNtuple() const
|
||||
{
|
||||
return GetNtuple(fFirstId);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
tools::wcsv::ntuple* G4CsvNtupleManager::GetNtuple(G4int ntupleId) const
|
||||
{
|
||||
G4CsvNtupleDescription* ntupleDescription
|
||||
= GetNtupleInFunction(ntupleId, "GetNtuple");
|
||||
|
||||
if ( ! ntupleDescription ) return 0;
|
||||
|
||||
return ntupleDescription->fNtuple;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4int G4CsvNtupleManager::CreateNtuple(const G4String& name,
|
||||
const G4String& title)
|
||||
{
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() )
|
||||
fState.GetVerboseL4()->Message("create", "ntuple", name);
|
||||
#endif
|
||||
|
||||
// Create ntuple description
|
||||
G4int index = fNtupleDescriptionVector.size();
|
||||
G4CsvNtupleDescription* ntupleDescription
|
||||
= new G4CsvNtupleDescription();
|
||||
fNtupleDescriptionVector.push_back(ntupleDescription);
|
||||
|
||||
// Create ntuple booking
|
||||
ntupleDescription->fNtupleBooking
|
||||
= new tools::ntuple_booking(name, title);
|
||||
// ntuple booking object is deleted in destructor
|
||||
|
||||
// Create ntuple if the file is open (what means here that
|
||||
// a filename was already set)
|
||||
if ( fFileManager->GetFileName().size() ) {
|
||||
if ( fFileManager->CreateNtupleFile(ntupleDescription) ) {
|
||||
ntupleDescription->fNtuple
|
||||
= new tools::wcsv::ntuple(*(ntupleDescription->fFile));
|
||||
// ntuple object is deleted when closing a file
|
||||
(ntupleDescription->fNtuple)->set_title(title);
|
||||
fNtupleVector.push_back(ntupleDescription->fNtuple);
|
||||
}
|
||||
}
|
||||
|
||||
fLockFirstId = true;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL2() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << name << " ntupleId " << index + fFirstId;
|
||||
fState.GetVerboseL2()->Message("create", "ntuple", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
return index + fFirstId;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4int G4CsvNtupleManager::CreateNtupleIColumn(const G4String& name,
|
||||
std::vector<int>* vector)
|
||||
{
|
||||
G4int ntupleId = fNtupleDescriptionVector.size() + fFirstId - 1;
|
||||
return CreateNtupleIColumn(ntupleId, name, vector);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4int G4CsvNtupleManager::CreateNtupleFColumn(const G4String& name,
|
||||
std::vector<float>* vector)
|
||||
{
|
||||
G4int ntupleId = fNtupleDescriptionVector.size() + fFirstId - 1;
|
||||
return CreateNtupleFColumn(ntupleId, name, vector);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4int G4CsvNtupleManager::CreateNtupleDColumn(const G4String& name,
|
||||
std::vector<double>* vector)
|
||||
{
|
||||
G4int ntupleId = fNtupleDescriptionVector.size() + fFirstId - 1;
|
||||
return CreateNtupleDColumn(ntupleId, name, vector);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4int G4CsvNtupleManager::CreateNtupleSColumn(const G4String& name)
|
||||
{
|
||||
G4int ntupleId = fNtupleDescriptionVector.size() + fFirstId - 1;
|
||||
return CreateNtupleSColumn(ntupleId, name);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
void G4CsvNtupleManager::FinishNtuple()
|
||||
{
|
||||
G4int ntupleId = fNtupleDescriptionVector.size() + fFirstId - 1;
|
||||
FinishNtuple(ntupleId);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4int G4CsvNtupleManager::CreateNtupleIColumn(G4int ntupleId,
|
||||
const G4String& name,
|
||||
std::vector<int>* vector)
|
||||
{
|
||||
if ( vector ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Ntuple columns of vector are not supported." ;
|
||||
G4Exception("G4CsvAnalysisManager::CreateNtupleIColumn",
|
||||
"Analysis_W002", JustWarning, description);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << name << " ntupleId " << ntupleId;
|
||||
fState.GetVerboseL4()->Message("create", "ntuple I column", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
G4CsvNtupleDescription* ntupleDescription
|
||||
= GetNtupleInFunction(ntupleId, "CreateNtupleIColumn");
|
||||
if ( ! ntupleDescription ) return kInvalidId;
|
||||
|
||||
tools::ntuple_booking* ntupleBooking
|
||||
= ntupleDescription->fNtupleBooking;
|
||||
|
||||
if ( ! ntupleBooking ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Ntuple " << ntupleId << " has to be created first. ";
|
||||
G4Exception("G4CsvNtupleManager::CreateNtupleIColumn()",
|
||||
"Analysis_W002", JustWarning, description);
|
||||
return kInvalidId;
|
||||
}
|
||||
|
||||
// Save column info in booking
|
||||
G4int index = ntupleBooking->columns().size();
|
||||
ntupleBooking->add_column<int>(name);
|
||||
|
||||
// Create column if ntuple already exists
|
||||
if ( ntupleDescription->fNtuple ) {
|
||||
tools::wcsv::ntuple::column<int>* column
|
||||
= ntupleDescription->fNtuple->create_column<int>(name);
|
||||
ntupleDescription->fNtupleIColumnMap[index] = column;
|
||||
}
|
||||
|
||||
fLockFirstNtupleColumnId = true;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL2() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << name << " ntupleId " << ntupleId;
|
||||
fState.GetVerboseL2()->Message("create", "ntuple I column", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
return index + fFirstNtupleColumnId;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4int G4CsvNtupleManager::CreateNtupleFColumn(G4int ntupleId,
|
||||
const G4String& name,
|
||||
std::vector<float>* vector)
|
||||
{
|
||||
if ( vector ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Ntuple columns of vector are not supported." ;
|
||||
G4Exception("G4CsvAnalysisManager::CreateNtupleFColumn",
|
||||
"Analysis_W002", JustWarning, description);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << name << " ntupleId " << ntupleId;
|
||||
fState.GetVerboseL4()->Message("create", "ntuple F column", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
G4CsvNtupleDescription* ntupleDescription
|
||||
= GetNtupleInFunction(ntupleId, "CreateNtupleFColumn");
|
||||
if ( ! ntupleDescription ) return kInvalidId;
|
||||
|
||||
tools::ntuple_booking* ntupleBooking
|
||||
= ntupleDescription->fNtupleBooking;
|
||||
|
||||
if ( ! ntupleBooking ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Ntuple " << ntupleId << " has to be created first. ";
|
||||
G4Exception("G4CsvNtupleManager::CreateNtupleFColumn()",
|
||||
"Analysis_W002", JustWarning, description);
|
||||
return kInvalidId;
|
||||
}
|
||||
|
||||
// Save column info in booking
|
||||
G4int index = ntupleBooking->columns().size();
|
||||
ntupleBooking->add_column<float>(name);
|
||||
|
||||
// Create column if ntuple already exists
|
||||
if ( ntupleDescription->fNtuple ) {
|
||||
tools::wcsv::ntuple::column<float>* column
|
||||
= ntupleDescription->fNtuple->create_column<float>(name);
|
||||
ntupleDescription->fNtupleFColumnMap[index] = column;
|
||||
}
|
||||
|
||||
fLockFirstNtupleColumnId = true;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL2() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << name << " ntupleId " << ntupleId;
|
||||
fState.GetVerboseL2()->Message("create", "ntuple F column", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
return index + fFirstNtupleColumnId;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4int G4CsvNtupleManager::CreateNtupleDColumn(G4int ntupleId,
|
||||
const G4String& name,
|
||||
std::vector<double>* vector)
|
||||
{
|
||||
if ( vector ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Ntuple columns of vector are not supported." ;
|
||||
G4Exception("G4CsvAnalysisManager::CreateNtupleDColumn",
|
||||
"Analysis_W002", JustWarning, description);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << name << " ntupleId " << ntupleId;
|
||||
fState.GetVerboseL4()->Message("create", "ntuple D column", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
G4CsvNtupleDescription* ntupleDescription
|
||||
= GetNtupleInFunction(ntupleId, "CreateNtupleDColumn");
|
||||
if ( ! ntupleDescription ) return kInvalidId;
|
||||
|
||||
tools::ntuple_booking* ntupleBooking
|
||||
= ntupleDescription->fNtupleBooking;
|
||||
|
||||
if ( ! ntupleBooking ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Ntuple " << ntupleId << " has to be created first. ";
|
||||
G4Exception("G4CsvNtupleManager::CreateNtupleDColumn()",
|
||||
"Analysis_W002", JustWarning, description);
|
||||
return kInvalidId;
|
||||
}
|
||||
|
||||
// Save column info in booking
|
||||
G4int index = ntupleBooking->columns().size();
|
||||
ntupleBooking->add_column<double>(name);
|
||||
|
||||
// Create column if ntuple already exists
|
||||
if ( ntupleDescription->fNtuple ) {
|
||||
tools::wcsv::ntuple::column<double>* column
|
||||
= ntupleDescription->fNtuple->create_column<double>(name);
|
||||
ntupleDescription->fNtupleDColumnMap[index] = column;
|
||||
}
|
||||
|
||||
fLockFirstNtupleColumnId = true;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL2() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << name << " ntupleId " << ntupleId;
|
||||
fState.GetVerboseL2()->Message("create", "ntuple D column", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
return index + fFirstNtupleColumnId;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4int G4CsvNtupleManager::CreateNtupleSColumn(G4int ntupleId,
|
||||
const G4String& name)
|
||||
{
|
||||
/*
|
||||
if ( vector ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Ntuple columns of vector are not supported." ;
|
||||
G4Exception("G4CsvAnalysisManager::CreateNtupleSColumn",
|
||||
"Analysis_W002", JustWarning, description);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << name << " ntupleId " << ntupleId;
|
||||
fState.GetVerboseL4()->Message("create", "ntuple S column", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
G4CsvNtupleDescription* ntupleDescription
|
||||
= GetNtupleInFunction(ntupleId, "CreateNtupleSColumn");
|
||||
if ( ! ntupleDescription ) return kInvalidId;
|
||||
|
||||
tools::ntuple_booking* ntupleBooking
|
||||
= ntupleDescription->fNtupleBooking;
|
||||
|
||||
if ( ! ntupleBooking ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Ntuple " << ntupleId << " has to be created first. ";
|
||||
G4Exception("G4CsvNtupleManager::CreateNtupleSColumn()",
|
||||
"Analysis_W002", JustWarning, description);
|
||||
return kInvalidId;
|
||||
}
|
||||
|
||||
// Save column info in booking
|
||||
G4int index = ntupleBooking->columns().size();
|
||||
ntupleBooking->add_column<std::string>(name);
|
||||
|
||||
// Create column if ntuple already exists
|
||||
if ( ntupleDescription->fNtuple ) {
|
||||
tools::wcsv::ntuple::column<std::string>* column
|
||||
= ntupleDescription->fNtuple->create_column<std::string>(name);
|
||||
ntupleDescription->fNtupleSColumnMap[index] = column;
|
||||
}
|
||||
|
||||
fLockFirstNtupleColumnId = true;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL2() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << name << " ntupleId " << ntupleId;
|
||||
fState.GetVerboseL2()->Message("create", "ntuple S column", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
return index + fFirstNtupleColumnId;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
void G4CsvNtupleManager::FinishNtuple(G4int ntupleId)
|
||||
{
|
||||
// nothing to be done if hippo header is inactivated
|
||||
G4CsvNtupleDescription* ntupleDescription
|
||||
= GetNtupleInFunction(ntupleId, "FinishNtuple");
|
||||
if ( ! ntupleDescription ) return;
|
||||
|
||||
// Write hippo header if ntuple already exists
|
||||
if ( ntupleDescription->fNtuple ) {
|
||||
if ( ! WriteHeader(ntupleDescription->fNtuple) ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " "
|
||||
<< "Writing ntuple header has failed. ";
|
||||
G4Exception("G4CsvNtupleManager::Finish()",
|
||||
"Analysis_W022", JustWarning, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::FillNtupleIColumn(G4int columnId, G4int value)
|
||||
{
|
||||
return FillNtupleIColumn(fFirstId, columnId, value);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::FillNtupleFColumn(G4int columnId, G4float value)
|
||||
{
|
||||
return FillNtupleFColumn(fFirstId, columnId, value);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::FillNtupleDColumn(G4int columnId, G4double value)
|
||||
{
|
||||
return FillNtupleDColumn(fFirstId, columnId, value);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::FillNtupleSColumn(G4int columnId,
|
||||
const G4String& value)
|
||||
{
|
||||
return FillNtupleSColumn(fFirstId, columnId, value);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::AddNtupleRow()
|
||||
{
|
||||
return AddNtupleRow(fFirstId);
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::FillNtupleIColumn(G4int ntupleId, G4int columnId,
|
||||
G4int value)
|
||||
{
|
||||
tools::wcsv::ntuple::column<int>* column
|
||||
= GetNtupleIColumn(ntupleId, columnId);
|
||||
if ( ! column ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " does not exist.";
|
||||
G4Exception("G4CsvNtupleManager::FillNtupleIColumn()",
|
||||
"Analysis_W011", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
|
||||
column->fill(value);
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " value " << value;
|
||||
fState.GetVerboseL4()->Message("fill", "ntuple I column", description);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::FillNtupleFColumn(G4int ntupleId, G4int columnId,
|
||||
G4float value)
|
||||
{
|
||||
tools::wcsv::ntuple::column<float>* column
|
||||
= GetNtupleFColumn(ntupleId, columnId);
|
||||
if ( ! column ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " does not exist.";
|
||||
G4Exception("G4CsvNtupleManager::FillNtupleFColumn()",
|
||||
"Analysis_W011", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
|
||||
column->fill(value);
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " value " << value;
|
||||
fState.GetVerboseL4()->Message("fill", "ntuple F column", description);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::FillNtupleDColumn(G4int ntupleId, G4int columnId,
|
||||
G4double value)
|
||||
{
|
||||
tools::wcsv::ntuple::column<double>* column
|
||||
= GetNtupleDColumn(ntupleId, columnId);
|
||||
if ( ! column ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " does not exist.";
|
||||
G4Exception("G4CsvNtupleManager::FillNtupleDColumn()",
|
||||
"Analysis_W011", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
|
||||
column->fill(value);
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " value " << value;
|
||||
fState.GetVerboseL4()->Message("fill", "ntuple D column", description);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::FillNtupleSColumn(G4int ntupleId, G4int columnId,
|
||||
const G4String& value)
|
||||
{
|
||||
tools::wcsv::ntuple::column<std::string>* column
|
||||
= GetNtupleSColumn(ntupleId, columnId);
|
||||
if ( ! column ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " does not exist.";
|
||||
G4Exception("G4CsvNtupleManager::FillNtupleSColumn()",
|
||||
"Analysis_W011", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
|
||||
column->fill(value);
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " ntupleId " << ntupleId
|
||||
<< " columnId " << columnId << " value " << value;
|
||||
fState.GetVerboseL4()->Message("fill", "ntuple S column", description);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
G4bool G4CsvNtupleManager::AddNtupleRow(G4int ntupleId)
|
||||
{
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " ntupleId " << ntupleId;
|
||||
fState.GetVerboseL4()->Message("add", "ntuple row", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
G4CsvNtupleDescription* ntupleDescription
|
||||
= GetNtupleInFunction(ntupleId, "AddNtupleRow");
|
||||
if ( ! ntupleDescription ) return false;
|
||||
|
||||
if ( ! ntupleDescription->fNtuple ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " " << "ntuple does not exist. ";
|
||||
G4Exception("G4CsvNtupleManager::AddNtupleRow()",
|
||||
"Analysis_W022", JustWarning, description);
|
||||
return false;
|
||||
}
|
||||
|
||||
ntupleDescription->fNtuple->add_row();
|
||||
#ifdef G4VERBOSE
|
||||
if ( fState.GetVerboseL4() ) {
|
||||
G4ExceptionDescription description;
|
||||
description << " ntupleId " << ntupleId;
|
||||
fState.GetVerboseL4()->Message("add", "ntuple row", description);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -95,6 +95,6 @@ std::ifstream* G4CsvRFileManager::GetRFile(const G4String& fileName) const
|
||||
if ( it != fRFiles.end() )
|
||||
return it->second;
|
||||
else {
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ G4CsvRNtupleDescription* G4CsvRNtupleManager::GetNtupleInFunction(G4int id,
|
||||
description << " " << "ntuple " << id << " does not exist.";
|
||||
G4Exception(inFunction, "Analysis_WR011", JustWarning, description);
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return fNtupleVector[index];
|
||||
@@ -107,7 +107,7 @@ tools::rcsv::ntuple* G4CsvRNtupleManager::GetNtuple(G4int ntupleId) const
|
||||
G4CsvRNtupleDescription* rntupleDescription
|
||||
= GetNtupleInFunction(ntupleId, "GetNtuple");
|
||||
|
||||
if ( ! rntupleDescription ) return 0;
|
||||
if ( ! rntupleDescription ) return nullptr;
|
||||
|
||||
return rntupleDescription->fNtuple;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$Id: exception_classification.txt 85317 2014-10-27 15:58:15Z gcosmo $
|
||||
$Id: exception_classification.txt 92099 2015-08-18 09:04:30Z gcosmo $
|
||||
|
||||
Analysis_F001: Fatal exception when trying to create a singleton manager twice
|
||||
|
||||
@@ -20,6 +20,8 @@ Analysis_W022: Writing an object on file has failed
|
||||
|
||||
Analysis_W031: Merging data has failed
|
||||
|
||||
Analysis_W041: Requested feature is not available with selected output.
|
||||
|
||||
Analysis_WR001: Cannot open a file for reading
|
||||
|
||||
Analysis_WR011: Cannot access an object in a file
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_HEADER
|
||||
#define tools_HEADER
|
||||
|
||||
#include "S_STRING"
|
||||
#include "scast"
|
||||
|
||||
#define TOOLS_HEADER(a__class,a__sclass,a__parent)\
|
||||
private:\
|
||||
typedef a__parent parent;\
|
||||
public:\
|
||||
TOOLS_SCLASS(a__sclass)\
|
||||
public:\
|
||||
virtual void* cast(const std::string& a_class) const {\
|
||||
if(void* p = tools::cmp_cast<a__class>(this,a_class)) return p;\
|
||||
return parent::cast(a_class);\
|
||||
}\
|
||||
virtual const std::string& s_cls() const {return s_class();}
|
||||
|
||||
#define TOOLS_HEADER_COPY(a__class,a__sclass,a__parent,a__to)\
|
||||
TOOLS_HEADER(a__class,a__sclass,a__parent)\
|
||||
virtual a__to* copy() const {return new a__class(*this);}
|
||||
|
||||
#define TOOLS_T_HEADER(a__T,a__class,a__sclass,a__parent)\
|
||||
private:\
|
||||
typedef a__parent parent;\
|
||||
public:\
|
||||
TOOLS_T_SCLASS(a__T,a__sclass)\
|
||||
public:\
|
||||
virtual void* cast(const std::string& a_class) const {\
|
||||
if(void* p = tools::cmp_cast<a__class>(this,a_class)) return p;\
|
||||
return parent::cast(a_class);\
|
||||
}\
|
||||
virtual const std::string& s_cls() const {return s_class();}
|
||||
|
||||
#endif
|
||||
@@ -46,4 +46,18 @@ static const std::string& s_class() {\
|
||||
}\
|
||||
static void check_class_name() {a_name<a_T>::s_class();}
|
||||
|
||||
#define TOOLS_T2_SCLASS(a_T1,a_T2,a_name)\
|
||||
static const std::string& s_class() {\
|
||||
static const std::string s_v(#a_name);\
|
||||
return s_v;\
|
||||
}\
|
||||
static void check_class_name() {a_name<a_T1,a_T2>::s_class();}
|
||||
|
||||
#define TOOLS_T3_SCLASS(a_T1,a_T2,a_T3,a_name)\
|
||||
static const std::string& s_class() {\
|
||||
static const std::string s_v(#a_name);\
|
||||
return s_v;\
|
||||
}\
|
||||
static void check_class_name() {a_name<a_T1,a_T2,a_T3>::s_class();}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -72,7 +72,6 @@ protected:
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
std::string name() {return m_name;}
|
||||
const std::string& name() const {return m_name;}
|
||||
|
||||
void set_index(uint64 a_index){m_index = a_index;}
|
||||
@@ -149,10 +148,9 @@ protected:
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
std::ostream& out() {return m_out;}
|
||||
std::ostream& out() const {return m_out;}
|
||||
const std::vector<base_col*>& cols() const {return m_cols;}
|
||||
|
||||
std::string title() {return m_title;}
|
||||
const std::string& title() const {return m_title;}
|
||||
void set_title(const std::string& a_title) {m_title = a_title;}
|
||||
|
||||
@@ -272,11 +270,12 @@ inline const std::string& s_aida_type(int64) {
|
||||
static const std::string s_v("long");
|
||||
return s_v;
|
||||
}
|
||||
/*
|
||||
inline const std::string& s_aida_type(const std::vector<double>&) {
|
||||
static const std::string s_v("double[]");
|
||||
return s_v;
|
||||
}
|
||||
|
||||
*/
|
||||
inline const std::string& s_aida_type_ituple() {
|
||||
static const std::string s_v("ITuple");
|
||||
return s_v;
|
||||
@@ -309,7 +308,7 @@ public:
|
||||
return base_col::cast(a_class);
|
||||
}
|
||||
public:
|
||||
virtual std::string aida_type() const = 0;
|
||||
virtual const std::string& aida_type() const = 0;
|
||||
virtual bool s_default_value(std::string&) const = 0;
|
||||
virtual bool s_value(std::string&) const = 0;
|
||||
virtual bool s_fill(const std::string&) = 0;
|
||||
@@ -394,7 +393,7 @@ public:
|
||||
}
|
||||
virtual uint64 num_elems() const {return m_data.size();}
|
||||
public:
|
||||
virtual std::string aida_type() const {return s_aida_type(T());}
|
||||
virtual const std::string& aida_type() const {return s_aida_type(T());}
|
||||
virtual bool s_default_value(std::string& a_s) const {
|
||||
a_s = tos(m_default);
|
||||
return true;
|
||||
@@ -704,23 +703,18 @@ inline bool create_cols_from_vals(ntuple& a_ntu,
|
||||
col = a_ntu.create_col<double>((*it).label(),(*it).get_double());
|
||||
|
||||
//} else if((*it).type()==value::UNSIGNED_CHAR) {
|
||||
// col = a_ntu.create_col<unsigned char>
|
||||
// ((*it).label(),(*it).get_unsigned_char());
|
||||
// col = a_ntu.create_col<unsigned char>((*it).label(),(*it).get_unsigned_char());
|
||||
} else if((*it).type()==value::UNSIGNED_SHORT) {
|
||||
col = a_ntu.create_col<unsigned short>
|
||||
((*it).label(),(*it).get_unsigned_short());
|
||||
col = a_ntu.create_col<unsigned short>((*it).label(),(*it).get_unsigned_short());
|
||||
} else if((*it).type()==value::UNSIGNED_INT) {
|
||||
col = a_ntu.create_col<unsigned int>
|
||||
((*it).label(),(*it).get_unsigned_int());
|
||||
col = a_ntu.create_col<unsigned int>((*it).label(),(*it).get_unsigned_int());
|
||||
} else if((*it).type()==value::UNSIGNED_INT64) {
|
||||
col = a_ntu.create_col<uint64>
|
||||
((*it).label(),(*it).get_unsigned_int64());
|
||||
col = a_ntu.create_col<uint64>((*it).label(),(*it).get_unsigned_int64());
|
||||
|
||||
} else if((*it).type()==value::BOOL) {
|
||||
col = a_ntu.create_col<bool>((*it).label(),(*it).get_bool());
|
||||
} else if((*it).type()==value::STRING) {
|
||||
col = a_ntu.create_col<std::string>
|
||||
((*it).label(),(*it).get_string());
|
||||
col = a_ntu.create_col<std::string>((*it).label(),(*it).get_string());
|
||||
} else if((*it).type()==value::INT64) {
|
||||
col = a_ntu.create_col<int64>((*it).label(),(*it).get_int64());
|
||||
}
|
||||
@@ -1043,8 +1037,7 @@ inline bool create_cols_from_string(ntuple& a_ntu,
|
||||
return true;
|
||||
}
|
||||
|
||||
inline aida_col_ntu* find_col_ntu(ntuple& a_ntu,
|
||||
const std::string& a_name){
|
||||
inline aida_col_ntu* find_col_ntu(ntuple& a_ntu,const std::string& a_name){
|
||||
base_col* col = find_named<base_col>(a_ntu.cols(),a_name);
|
||||
if(!col) return 0;
|
||||
return safe_cast<base_col, aida_col_ntu >(*col);
|
||||
@@ -1218,7 +1211,7 @@ protected:
|
||||
}
|
||||
public:
|
||||
stat_looper(base_ntu& a_ntu,const base_col& a_col)
|
||||
: base_looper<T>(a_ntu,a_col)
|
||||
:base_looper<T>(a_ntu,a_col)
|
||||
,m_first(true)
|
||||
,m_mn(T())
|
||||
,m_mx(T())
|
||||
@@ -1229,7 +1222,7 @@ public:
|
||||
virtual ~stat_looper(){}
|
||||
public:
|
||||
stat_looper(const stat_looper& a_from)
|
||||
: base_looper<T>(a_from)
|
||||
:base_looper<T>(a_from)
|
||||
,m_first(true)
|
||||
,m_mn(T())
|
||||
,m_mx(T())
|
||||
@@ -1308,6 +1301,27 @@ inline base_col* find_leaf_column(const base_ntu& a_ntu,const std::string& a_nam
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool to_vector(base_ntu& a_ntu,std::vector<double>& a_vec,unsigned int a_col = 0) {
|
||||
a_vec.clear();
|
||||
const std::vector<base_col*>& cols = a_ntu.cols();
|
||||
if(cols.empty()) return false;
|
||||
if(a_col>=cols.size()) return false;
|
||||
base_col* _base_col = cols[a_col];
|
||||
aida_col<T>* _col = safe_cast<base_col, aida_col<T> >(*_base_col);
|
||||
if(!_col) return false;
|
||||
a_ntu.start();
|
||||
uint64 _rows = a_ntu.rows();
|
||||
a_vec.resize(_rows);
|
||||
T v;
|
||||
{for(uint64 row=0;row<_rows;row++) {
|
||||
if(!a_ntu.next()) {a_vec.clear();return false;}
|
||||
if(!_col->get_entry(v)) {}
|
||||
a_vec[row] = v;
|
||||
}}
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -106,9 +106,7 @@ public:
|
||||
return vec;
|
||||
}
|
||||
|
||||
bool add(const std::string& a_key,
|
||||
const std::string& a_value = "",
|
||||
bool a_override = true){
|
||||
bool add(const std::string& a_key,const std::string& a_value = "",bool a_override = true){
|
||||
if(a_override) {
|
||||
tools_vforit(arg,m_args,it) {
|
||||
if((*it).first==a_key) {
|
||||
@@ -118,7 +116,7 @@ public:
|
||||
}
|
||||
}
|
||||
if(a_key.empty()) return false;
|
||||
m_args.push_back(arg(a_key,a_value));
|
||||
m_args.push_back(arg(a_key,a_value));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -127,17 +125,14 @@ public:
|
||||
std::vector<std::string> ws;
|
||||
words((*it),"=",false,ws);
|
||||
if(ws.size()==1) {
|
||||
if(a_strip) {
|
||||
m_args.push_back(arg(strp(ws[0]),""));
|
||||
} else {
|
||||
m_args.push_back(arg(ws[0],""));
|
||||
}
|
||||
if(a_strip) strip(ws[0],both,' ');
|
||||
m_args.push_back(arg(ws[0],""));
|
||||
} else if(ws.size()>=2) {
|
||||
if(a_strip) {
|
||||
m_args.push_back(arg(strp(ws[0]),strp(ws[1])));
|
||||
} else {
|
||||
m_args.push_back(arg(ws[0],ws[1]));
|
||||
strip(ws[0],both,' ');
|
||||
strip(ws[1],both,' ');
|
||||
}
|
||||
m_args.push_back(arg(ws[0],ws[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,10 +141,13 @@ public:
|
||||
//a_args must contain an even number of strings.
|
||||
unsigned int sz_half = a_args.size()/2;
|
||||
if((2*sz_half)!=a_args.size()) return;
|
||||
for(std::vector<std::string>::const_iterator it = a_args.begin();
|
||||
it!=a_args.end();it+=2) {
|
||||
for(std::vector<std::string>::const_iterator it = a_args.begin();it!=a_args.end();it+=2) {
|
||||
if(a_strip) {
|
||||
m_args.push_back(arg(strp(*it),strp(*(it+1))));
|
||||
std::string key = *it;
|
||||
strip(key,both,' ');
|
||||
std::string val = *(it+1);
|
||||
strip(val,both,' ');
|
||||
m_args.push_back(arg(key,val));
|
||||
} else {
|
||||
m_args.push_back(arg(*it,*(it+1)));
|
||||
}
|
||||
@@ -183,7 +181,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool prog_name(std::string& a_value){
|
||||
bool prog_name(std::string& a_value) const {
|
||||
if(m_args.empty()) {a_value.clear();return false;}
|
||||
if(m_args[0].second.size()) {a_value.clear();return false;}
|
||||
a_value = m_args[0].first;
|
||||
@@ -229,22 +227,17 @@ public:
|
||||
// char** argv;
|
||||
// args.argcv(argc,argv);
|
||||
// you can delete with :
|
||||
// args.delete_argcv(argc,argv);
|
||||
// args::delete_argcv(argc,argv);
|
||||
if(m_args.empty()) {a_argc = 0;a_argv = 0;return true;}
|
||||
typedef char* _cstr_t;
|
||||
_cstr_t* av = new _cstr_t[m_args.size()];
|
||||
_cstr_t* av = new _cstr_t[m_args.size()+1];
|
||||
if(!av) {a_argc = 0;a_argv = 0;return false;}
|
||||
a_argv = av;
|
||||
for(std::vector<arg>::const_iterator it = m_args.begin();
|
||||
it!=m_args.end();++it,av++) {
|
||||
for(std::vector<arg>::const_iterator it = m_args.begin();it!=m_args.end();++it,av++) {
|
||||
std::string::size_type lf = (*it).first.length();
|
||||
std::string::size_type ls = (*it).second.length();
|
||||
std::string::size_type sz = 0;
|
||||
if(ls) {
|
||||
sz = lf + 1 + ls;
|
||||
} else {
|
||||
sz = lf;
|
||||
}
|
||||
std::string::size_type sz = lf;
|
||||
if(ls) sz += 1 + ls;
|
||||
char* p = new char[sz+1];
|
||||
if(!p) {a_argc = 0;a_argv = 0;return false;} //some delete are lacking.
|
||||
*av = p;
|
||||
@@ -256,6 +249,7 @@ public:
|
||||
for(std::string::size_type i=0;i<ls;i++,p++,ps++) {*p = *ps;}
|
||||
*p = 0;}
|
||||
}
|
||||
*(a_argv+m_args.size()) = 0;
|
||||
a_argc = (int)m_args.size();
|
||||
return true;
|
||||
}
|
||||
@@ -307,11 +301,10 @@ public:
|
||||
}
|
||||
|
||||
//NOTE : print is a Python keyword.
|
||||
void dump(std::ostream& a_out) const {
|
||||
void dump(std::ostream& a_out,const std::string& a_comment = "",const std::string& a_prefix = "") const {
|
||||
if(a_comment.size()) a_out << a_comment << std::endl;
|
||||
tools_vforcit(arg,m_args,it) {
|
||||
a_out << "key = " << sout((*it).first)
|
||||
<< " value = " << sout((*it).second)
|
||||
<< std::endl;
|
||||
a_out << a_prefix << "key = " << sout((*it).first) << ", value = " << sout((*it).second) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,27 +367,6 @@ inline bool check_or_args(const std::vector<std::string>& aArgs,unsigned int a_1
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool to(std::ostream& a_out,const std::string& a_string,T& a_value){
|
||||
if(!to<T>(a_string,a_value)) {
|
||||
a_out << "Passed value " << sout(a_string)
|
||||
<< " is of bad type."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool to(std::ostream& a_out,const std::string& a_string,bool& a_value){
|
||||
if(!to(a_string,a_value)) {
|
||||
a_out << "Passed value " << sout(a_string)
|
||||
<< " is not a boolean."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::string gui_toolkit(args& a_args,bool a_rm_in_args){
|
||||
std::string driver;
|
||||
a_args.find("-toolkit",driver);
|
||||
@@ -461,6 +433,11 @@ inline std::string gui_toolkit(args& a_args,bool a_rm_in_args){
|
||||
a_args.remove("-Net");
|
||||
a_args.remove("-net");
|
||||
}
|
||||
} else if(a_args.is_arg("-inex")) {
|
||||
driver = "inex";
|
||||
if(a_rm_in_args) {
|
||||
a_args.remove("-inex");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,12 +122,14 @@ public:
|
||||
//}
|
||||
_size *= m_orders[index];
|
||||
}
|
||||
m_vector.resize(_size,zero());
|
||||
m_vector.resize(_size);
|
||||
m_vector.assign(_size,zero());
|
||||
m_offsets.resize(dim,0);
|
||||
m_offsets[0] = 1;
|
||||
for(unsigned int iaxis=1;iaxis<dim;iaxis++)
|
||||
m_offsets[iaxis] = m_offsets[iaxis-1] * m_orders[iaxis-1];
|
||||
m_is.resize(dim,0);
|
||||
m_is.resize(dim);
|
||||
m_is.assign(dim,0);
|
||||
return true;
|
||||
}
|
||||
unsigned int dimension() const { return m_orders.size();}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_axis
|
||||
#define tools_axis
|
||||
|
||||
#include "mathf"
|
||||
|
||||
namespace tools {
|
||||
|
||||
class axis {
|
||||
public:
|
||||
axis()
|
||||
:m_min_value(0)
|
||||
,m_max_value(0)
|
||||
,m_steps(0)
|
||||
,m_is_log(false)
|
||||
{}
|
||||
virtual ~axis(){}
|
||||
public:
|
||||
axis(const axis& a_from)
|
||||
:m_min_value(a_from.m_min_value)
|
||||
,m_max_value(a_from.m_max_value)
|
||||
,m_steps(a_from.m_steps)
|
||||
,m_is_log(a_from.m_is_log)
|
||||
{}
|
||||
axis& operator=(const axis& a_from){
|
||||
m_min_value = a_from.m_min_value;
|
||||
m_max_value = a_from.m_max_value;
|
||||
m_steps = a_from.m_steps;
|
||||
m_is_log = a_from.m_is_log;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
bool is_log(bool a_v){
|
||||
if(m_is_log==a_v) return false;
|
||||
m_is_log = a_v;
|
||||
return true;
|
||||
}
|
||||
bool min_value(float a_v) {
|
||||
if(m_min_value==a_v) return false;
|
||||
m_min_value = a_v;
|
||||
return true;
|
||||
}
|
||||
bool max_value(float a_v) {
|
||||
if(m_max_value==a_v) return false;
|
||||
m_max_value = a_v;
|
||||
return true;
|
||||
}
|
||||
float min_value() const {return m_min_value;}
|
||||
float max_value() const {return m_max_value;}
|
||||
bool is_log() const {return m_is_log;}
|
||||
|
||||
void adjust_axis() { //from hippodraw.
|
||||
int _axis = 0;
|
||||
float step;
|
||||
float mylow, myhigh;
|
||||
int N_NICE = 4;
|
||||
static const float nice[/*N_NICE*/4] = { 1.0,2.0,2.5,5.0 };
|
||||
|
||||
if (m_min_value > m_max_value) {
|
||||
float low = m_min_value;
|
||||
m_min_value = m_max_value;
|
||||
m_max_value = low;
|
||||
} else if (m_min_value == m_max_value) {
|
||||
float value = m_min_value;
|
||||
m_min_value = value - 1;
|
||||
m_max_value = value + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_steps <= 0) {
|
||||
_axis = 1;
|
||||
m_steps = 10;
|
||||
}
|
||||
|
||||
// Round the "bin width" to a nice number.
|
||||
// If this is being done for an axis (ie m_steps was 0 , then
|
||||
// we don't have to go > *m_max_value.
|
||||
//
|
||||
float w = (m_max_value - m_min_value)/((float)m_steps);
|
||||
float mag = ffloor(flog10(w));
|
||||
int i = 0;
|
||||
do {
|
||||
step = nice[i] * fpow(10.0,mag);
|
||||
|
||||
mylow = ffloor(m_min_value/step) * step;
|
||||
myhigh = _axis==1 ? fceil(m_max_value/step) * step :
|
||||
mylow + step * m_steps;
|
||||
|
||||
i++;
|
||||
if (i>=N_NICE) {
|
||||
i = 0;
|
||||
mag++;
|
||||
}
|
||||
}
|
||||
while ( ( (_axis==1) && myhigh < m_max_value) ||
|
||||
( (_axis==0) && myhigh <= m_max_value) );
|
||||
|
||||
float range = myhigh - mylow;
|
||||
|
||||
// we now have decided on a range. Try to move
|
||||
// m_min_value/m_max_value a little
|
||||
// to end up on a nice number.
|
||||
//
|
||||
// first check if either end is near 0.0
|
||||
if ( !m_is_log && (m_min_value >= 0.0) &&
|
||||
(( (_axis==1) && (range>=m_max_value) ) ||
|
||||
( (_axis==0) && (range>m_max_value) )) ) {
|
||||
m_min_value = 0.0;
|
||||
m_max_value = range;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (( (_axis==1) && (m_max_value<=0.0) ) ||
|
||||
( (_axis==0) && (m_max_value<0.0) ))
|
||||
&& (-range<=m_min_value)) {
|
||||
m_max_value = 0.0;
|
||||
m_min_value = -range;
|
||||
return;
|
||||
}
|
||||
|
||||
// try to round *m_min_value.
|
||||
// correction
|
||||
if( m_is_log && (m_min_value<=0.0)) {
|
||||
m_min_value = 1.0;
|
||||
}
|
||||
|
||||
i = N_NICE-1;
|
||||
mag = myhigh != 0.0 ? fceil(flog10(ffabs(myhigh))) :
|
||||
fceil(flog10(ffabs(mylow)));
|
||||
|
||||
do {
|
||||
step = nice[i] * fpow(10.0,mag);
|
||||
mylow = ffloor(m_min_value/step) * step;
|
||||
myhigh = mylow + range;
|
||||
i--;
|
||||
if (i<0) {
|
||||
i = N_NICE-1;
|
||||
mag--;
|
||||
}
|
||||
}
|
||||
while (( m_is_log && (mylow <= 0.0) ) ||
|
||||
( (_axis==1) && (myhigh < m_max_value) ) ||
|
||||
( (_axis==0) && (myhigh <= m_max_value) ) );
|
||||
|
||||
m_min_value = mylow;
|
||||
m_max_value = myhigh;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
float m_min_value;
|
||||
float m_max_value;
|
||||
int m_steps;
|
||||
bool m_is_log;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_b2s
|
||||
#define tools_b2s
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace tools {
|
||||
|
||||
inline void b2s(bool a_value,std::string& a_s){
|
||||
a_s = a_value?"true":"false";
|
||||
}
|
||||
|
||||
inline void bas(bool a_value,std::string& a_s){
|
||||
a_s += (a_value?"true":"false");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace tools {
|
||||
|
||||
inline void b2s(const std::vector<bool>& a_vals,std::string& a_s,const std::string& a_sep = "\n",bool a_sep_at_end = false) {
|
||||
a_s.clear();
|
||||
unsigned int number = a_vals.size();
|
||||
if(number<=0) return;
|
||||
number--;
|
||||
std::string stmp;
|
||||
for(unsigned int index=0;index<number;index++) {
|
||||
b2s(a_vals[index],stmp);
|
||||
a_s += stmp;
|
||||
a_s += a_sep;
|
||||
}
|
||||
b2s(a_vals[number],stmp);
|
||||
a_s += stmp;
|
||||
if(a_sep_at_end) a_s += a_sep;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_charp_out
|
||||
#define tools_charp_out
|
||||
|
||||
#include "snpf"
|
||||
#include <string>
|
||||
|
||||
namespace tools {
|
||||
|
||||
class charp_out : public std::string {
|
||||
typedef std::string parent;
|
||||
public:
|
||||
charp_out(const char* a_value) {
|
||||
char s[512];
|
||||
if(sizeof(unsigned long)==sizeof(char*)) { //majority of cases.
|
||||
snpf(s,sizeof(s),"%lu",a_value);
|
||||
parent::operator+=(s);
|
||||
} else if(sizeof(unsigned long long)==sizeof(char*)) { //majority of cases.
|
||||
snpf(s,sizeof(s),"%llu",a_value);
|
||||
parent::operator+=(s);
|
||||
} else {
|
||||
parent::operator+=("charp_out_failed");
|
||||
}
|
||||
}
|
||||
public:
|
||||
charp_out(const charp_out& a_from):parent(a_from){}
|
||||
charp_out& operator=(const charp_out& a_from){parent::operator=(a_from);return *this;}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -63,20 +63,34 @@ namespace tools {
|
||||
inline bool cid2s(cid a_id,std::string& a_s) {
|
||||
// NOTE : the returned string must not contain space.
|
||||
|
||||
if(a_id==_cid(char(0))) {a_s = "char";return true;}
|
||||
else if(a_id==_cid(short(0))) {a_s = "short";return true;}
|
||||
else if(a_id==_cid(int(0))) {a_s = "int";return true;}
|
||||
else if(a_id==_cid(float(0))) {a_s = "float";return true;}
|
||||
else if(a_id==_cid(double(0))) {a_s = "double";return true;}
|
||||
if(a_id==_cid(char(0))) {a_s = "char";return true;}
|
||||
else if(a_id==_cid(short(0))) {a_s = "short";return true;}
|
||||
else if(a_id==_cid(int(0))) {a_s = "int";return true;}
|
||||
else if(a_id==_cid(float(0))) {a_s = "float";return true;}
|
||||
else if(a_id==_cid(double(0))) {a_s = "double";return true;}
|
||||
else if(a_id==_cid(std::string())) {a_s = "string";return true;}
|
||||
|
||||
// NOTE : the below do not follow the AIDA convention.
|
||||
else if(a_id==_cid((unsigned char)0)) {a_s = "uchar";return true;} //AIDA=byte
|
||||
else if(a_id==_cid((unsigned char)0)) {a_s = "uchar";return true;} //AIDA=byte
|
||||
else if(a_id==_cid((unsigned short)0)) {a_s = "ushort";return true;} //AIDA not defined
|
||||
else if(a_id==_cid((unsigned int)0)) {a_s = "uint";return true;} //AIDA not defined
|
||||
else if(a_id==_cid(bool(true))) {a_s = "bool";return true;} //AIDA=boolean
|
||||
else if(a_id==_cid(int64(0))) {a_s = "int64";return true;} //AIDA=long
|
||||
else if(a_id==_cid(uint64(0))) {a_s = "uint64";return true;} //AIDA=not defined
|
||||
else if(a_id==_cid((unsigned int)0)) {a_s = "uint";return true;} //AIDA not defined
|
||||
else if(a_id==_cid(bool(true))) {a_s = "bool";return true;} //AIDA=boolean
|
||||
else if(a_id==_cid(int64(0))) {a_s = "int64";return true;} //AIDA=long
|
||||
else if(a_id==_cid(uint64(0))) {a_s = "uint64";return true;} //AIDA=not defined
|
||||
|
||||
else if(a_id==_cid_std_vector<char>()) {a_s = "char[]";return true;}
|
||||
else if(a_id==_cid_std_vector<short>()) {a_s = "short[]";return true;}
|
||||
else if(a_id==_cid_std_vector<int>()) {a_s = "int[]";return true;}
|
||||
else if(a_id==_cid_std_vector<float>()) {a_s = "float[]";return true;}
|
||||
else if(a_id==_cid_std_vector<double>()) {a_s = "double[]";return true;}
|
||||
else if(a_id==_cid_std_vector<std::string>()) {a_s = "string[]";return true;}
|
||||
|
||||
else if(a_id==_cid_std_vector<unsigned char>()) {a_s = "uchar[]";return true;}
|
||||
else if(a_id==_cid_std_vector<unsigned short>()) {a_s = "ushort[]";return true;}
|
||||
else if(a_id==_cid_std_vector<unsigned int>()) {a_s = "uint[]";return true;}
|
||||
else if(a_id==_cid_std_vector<bool>()) {a_s = "bool[]";return true;}
|
||||
else if(a_id==_cid_std_vector<int64>()) {a_s = "int64[]";return true;}
|
||||
else if(a_id==_cid_std_vector<uint64>()) {a_s = "uint64[]";return true;}
|
||||
|
||||
a_s.clear();
|
||||
return false;
|
||||
|
||||
@@ -21,7 +21,7 @@ inline float _fabs(const float& a_x) {return ::fabsf(a_x);}
|
||||
inline float _tan(const float& a_x) {return ::tanf(a_x);}
|
||||
inline void _half_pi(float& a_v) {a_v = float(1.5707963267948965580E0);}
|
||||
inline void _pi(float& a_v) {a_v = float(3.1415926535897931160E0);}
|
||||
|
||||
inline float _conj(const float& a_x) {return a_x;}
|
||||
|
||||
//double
|
||||
inline double _pow(const double& a_x,const double& a_y) {return ::pow(a_x,a_y);}
|
||||
@@ -34,6 +34,7 @@ inline double _fabs(const double& a_x) {return ::fabs(a_x);}
|
||||
inline double _tan(const double& a_x) {return ::tan(a_x);}
|
||||
inline void _half_pi(double& a_v) {a_v = 1.5707963267948965580E0;}
|
||||
inline void _pi(double& a_v) {a_v = 3.1415926535897931160E0;}
|
||||
inline double _conj(const double& a_x) {return a_x;}
|
||||
|
||||
//long double
|
||||
#ifndef ANDROID
|
||||
@@ -47,6 +48,7 @@ inline long double _fabs(const long double& a_x) {return ::fabsl(a_x);}
|
||||
inline long double _tan(const long double& a_x) {return ::tanl(a_x);}
|
||||
inline void _half_pi(long double& a_v) {a_v = 1.5707963267948965580E0;}
|
||||
inline void _pi(long double& a_v) {a_v = 3.1415926535897931160E0;}
|
||||
inline long double _conj(const long double& a_x) {return a_x;}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_cmemT
|
||||
#define tools_cmemT
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include "mem"
|
||||
#endif
|
||||
|
||||
namespace tools {
|
||||
|
||||
template <class T>
|
||||
inline void cmem_free(T*& a_p){
|
||||
if(!a_p) return;
|
||||
::free(a_p);
|
||||
a_p = NULL;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::decrement("cmem");
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T* cmem_alloc(unsigned int a_num){
|
||||
if(a_num<=0) return 0;
|
||||
T* p = (T*)::malloc(a_num*sizeof(T));
|
||||
if(!p) return 0;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment("cmem");
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T* cmem_alloc_copy(const T* a_from,unsigned int a_num){
|
||||
if(a_num<=0) return 0;
|
||||
T* p = (T*)::malloc(a_num*sizeof(T));
|
||||
if(!p) return 0;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment("cmem");
|
||||
#endif
|
||||
//::memcpy(p,a_from,a_num*sizeof(T));
|
||||
for(unsigned int i=0;i<a_num;i++) p[i] = a_from[i];
|
||||
return p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,141 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_colorf
|
||||
#define tools_colorf
|
||||
|
||||
#include "lina/vec4f"
|
||||
|
||||
namespace tools {
|
||||
|
||||
class colorf : public vec4f {
|
||||
public: //for swig
|
||||
typedef unsigned char uchar;
|
||||
public:
|
||||
TOOLS_SCLASS(tools::colorf) //for stype()
|
||||
public:
|
||||
colorf():vec4f(0,0,0,1){}
|
||||
colorf(float a_r,float a_g,float a_b,float a_a = 1):vec4f(a_r,a_g,a_b,a_a){}
|
||||
virtual ~colorf() {}
|
||||
public:
|
||||
colorf(const colorf& a_from):vec4f(a_from){}
|
||||
colorf& operator=(const colorf& a_from){
|
||||
vec4f::operator=(a_from);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
float r() const {return v0();}
|
||||
float g() const {return v1();}
|
||||
float b() const {return v2();}
|
||||
float a() const {return v3();}
|
||||
|
||||
void set_r(float a_v) {m_data[0] = a_v;}
|
||||
void set_g(float a_v) {m_data[1] = a_v;}
|
||||
void set_b(float a_v) {m_data[2] = a_v;}
|
||||
void set_a(float a_v) {m_data[3] = a_v;}
|
||||
|
||||
uchar rchar() const {return uchar(255.0f*m_data[0]);}
|
||||
uchar gchar() const {return uchar(255.0f*m_data[1]);}
|
||||
uchar bchar() const {return uchar(255.0f*m_data[2]);}
|
||||
|
||||
public:
|
||||
// our forever 65 named colors taken long time ago from X11.
|
||||
|
||||
//NOTE : don't handle a static object because of mem balance.
|
||||
//0-9
|
||||
static colorf aquamarine() {return colorf(0.496101F,0.996109F,0.828138F);}
|
||||
static colorf mediumaquamarine() {return colorf(0.398444F,0.800793F,0.664073F);}
|
||||
static colorf black() {return colorf(0,0,0);}
|
||||
static colorf blue() {return colorf(0,0,1);}
|
||||
static colorf cadetblue() {return colorf(0.371099F,0.617197F,0.62501F);}
|
||||
static colorf cornflowerblue() {return colorf(0.390631F,0.58204F,0.925795F);}
|
||||
static colorf darkslateblue() {return colorf(0.281254F,0.238285F,0.542977F);}
|
||||
static colorf lightblue() {return colorf(0.675792F,0.843763F,0.898451F);}
|
||||
static colorf lightsteelblue() {return colorf(0.68751F,0.765637F,0.867201F);}
|
||||
static colorf mediumblue() {return colorf(0,0,0.800793F);}
|
||||
|
||||
//10-19
|
||||
static colorf mediumslateblue() {return colorf(0.480476F,0.406256F,0.929702F);}
|
||||
static colorf midnightblue() {return colorf(0.0976577F,0.0976577F,0.437507F);}
|
||||
static colorf navyblue() {return colorf(0,0,0.500008F);}
|
||||
static colorf navy() {return colorf(0,0,0.500008F);}
|
||||
static colorf skyblue() {return colorf(0.527352F,0.8047F,0.917983F);}
|
||||
static colorf slateblue() {return colorf(0.414069F,0.351568F,0.800793F);}
|
||||
static colorf steelblue() {return colorf(0.273442F,0.50782F,0.703136F);}
|
||||
static colorf coral() {return colorf(0.996109F,0.496101F,0.312505F);}
|
||||
static colorf cyan() {return colorf(0,1,1);}
|
||||
static colorf firebrick() {return colorf(0.695323F,0.132815F,0.132815F);}
|
||||
|
||||
//20-29
|
||||
static colorf brown() {return colorf(0.644541F,0.164065F,0.164065F);}
|
||||
static colorf gold() {return colorf(0.996109F,0.839857F,0);}
|
||||
static colorf goldenrod() {return colorf(0.851575F,0.644541F,0.125002F);}
|
||||
static colorf green() {return colorf(0,1,0);}
|
||||
static colorf darkgreen() {return colorf(0,0.390631F,0);}
|
||||
static colorf darkolivegreen() {return colorf(0.332036F,0.417975F,0.183597F);}
|
||||
static colorf forestgreen() {return colorf(0.132815F,0.542977F,0.132815F);}
|
||||
static colorf limegreen() {return colorf(0.195315F,0.800793F,0.195315F);}
|
||||
static colorf mediumseagreen() {return colorf(0.234379F,0.699229F,0.441413F);}
|
||||
static colorf mediumspringgreen() {return colorf(0,0.976577F,0.601572F);}
|
||||
|
||||
//30-39
|
||||
static colorf palegreen() {return colorf(0.593759F,0.980484F,0.593759F);}
|
||||
static colorf seagreen() {return colorf(0.17969F,0.542977F,0.339849F);}
|
||||
static colorf springgreen() {return colorf(0,0.996109F,0.496101F);}
|
||||
static colorf yellowgreen() {return colorf(0.601572F,0.800793F,0.195315F);}
|
||||
static colorf darkslategrey() {return colorf(0.183597F,0.308598F,0.308598F);}
|
||||
static colorf dimgrey() {return colorf(0.410163F,0.410163F,0.410163F);}
|
||||
static colorf lightgrey() {return colorf(0.824231F,0.824231F,0.824231F);}
|
||||
static colorf grey() {return colorf(0.750011F,0.750011F,0.750011F);}
|
||||
static colorf khaki() {return colorf(0.937514F,0.898451F,0.546883F);}
|
||||
static colorf magenta() {return colorf(1,0,1);}
|
||||
|
||||
//40-49
|
||||
static colorf maroon() {return colorf(0.68751F,0.187503F,0.375006F);}
|
||||
static colorf orange() {return colorf(0.996109F,0.644541F,0);}
|
||||
static colorf orchid() {return colorf(0.851575F,0.437507F,0.83595F);}
|
||||
static colorf darkorchid() {return colorf(0.597665F,0.195315F,0.796887F);}
|
||||
static colorf mediumorchid() {return colorf(0.726574F,0.332036F,0.824231F);}
|
||||
static colorf pink() {return colorf(0.996109F,0.750011F,0.792981F);}
|
||||
static colorf plum() {return colorf(0.863294F,0.62501F,0.863294F);}
|
||||
static colorf red() {return colorf(1,0,0);}
|
||||
static colorf indianred() {return colorf(0.800793F,0.35938F,0.35938F);}
|
||||
static colorf mediumvioletred() {return colorf(0.777356F,0.0820325F,0.519539F);}
|
||||
|
||||
//50-59
|
||||
static colorf orangered() {return colorf(0.996109F,0.269535F,0);}
|
||||
static colorf violetred() {return colorf(0.812512F,0.125002F,0.562509F);}
|
||||
static colorf salmon() {return colorf(0.976577F,0.500008F,0.445319F);}
|
||||
static colorf sienna() {return colorf(0.62501F,0.320317F,0.175784F);}
|
||||
static colorf tan() {return colorf(0.820325F,0.703136F,0.546883F);}
|
||||
static colorf thistle() {return colorf(0.843763F,0.746105F,0.843763F);}
|
||||
static colorf turquoise() {return colorf(0.250004F,0.875013F,0.812512F);}
|
||||
static colorf darkturquoise() {return colorf(0,0.8047F,0.816419F);}
|
||||
static colorf mediumturquoise() {return colorf(0.281254F,0.816419F,0.796887F);}
|
||||
static colorf violet() {return colorf(0.929702F,0.50782F,0.929702F);}
|
||||
|
||||
//60-64
|
||||
static colorf blueviolet() {return colorf(0.539071F,0.167971F,0.882826F);}
|
||||
static colorf wheat() {return colorf(0.957046F,0.867201F,0.699229F);}
|
||||
static colorf white() {return colorf(1,1,1);}
|
||||
static colorf yellow() {return colorf(1,1,0);}
|
||||
static colorf greenyellow() {return colorf(0.675792F,0.996109F,0.18359F);}
|
||||
};
|
||||
|
||||
struct cmp_colorf {
|
||||
bool operator()(const colorf& a_a,const colorf& a_b) const {
|
||||
// x :
|
||||
if(a_a.v0()<a_b.v0()) return true;
|
||||
if(a_a.v0()>a_b.v0()) return false;
|
||||
// y :
|
||||
if(a_a.v1()<a_b.v1()) return true;
|
||||
if(a_a.v1()>a_b.v1()) return false;
|
||||
// z :
|
||||
if(a_a.v2()<a_b.v2()) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <ostream>
|
||||
|
||||
#include "forit"
|
||||
#include "sout"
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include "mem"
|
||||
@@ -55,18 +56,9 @@ public:
|
||||
tools_vforit(tree,m_sub,it) (*it).clear();
|
||||
}
|
||||
void dump_tree(std::ostream& a_out,const std::string& a_margin) {
|
||||
#ifdef WIN32
|
||||
if(m_dcl.size()) a_out << a_margin.c_str() << m_dcl.c_str() << std::endl;
|
||||
#else
|
||||
if(m_dcl.size()) a_out << a_margin << m_dcl << std::endl;
|
||||
#endif
|
||||
{tools_vforit(tree,m_sub,it) {
|
||||
#ifdef WIN32
|
||||
std::string s = a_margin;s += " ";
|
||||
(*it).dump_tree(a_out,s);
|
||||
#else
|
||||
(*it).dump_tree(a_out,a_margin+" ");
|
||||
#endif
|
||||
}}
|
||||
}
|
||||
public:
|
||||
@@ -194,8 +186,7 @@ inline void dump_columns(std::ostream& a_out,
|
||||
a_out << a_margin
|
||||
<< "ITuple : " << (*it).label() << " : begin "
|
||||
<< std::endl;
|
||||
std::vector<value>* vars =
|
||||
(std::vector<value>*)(*it).get_void_star();
|
||||
std::vector<value>* vars = (std::vector<value>*)(*it).get_void_star();
|
||||
dump_columns(a_out,*vars,a_margin+" ");
|
||||
//a_out << a_margin
|
||||
// << "ITuple : " << (*it).label() << " : end "
|
||||
@@ -253,7 +244,6 @@ public:
|
||||
}
|
||||
/*
|
||||
const std::string& script() const { return m_script;}
|
||||
std::string script() { return m_script;}
|
||||
//bool isSuccess() const { return fSuccess;}
|
||||
std::ostream& out() const {return m_out;}
|
||||
*/
|
||||
@@ -433,8 +423,7 @@ protected:
|
||||
}
|
||||
}
|
||||
protected:
|
||||
static bool s2type(const std::string& a_s,
|
||||
value::e_type& a_type){
|
||||
static bool s2type(const std::string& a_s,value::e_type& a_type){
|
||||
if(a_s=="float") {
|
||||
a_type = value::FLOAT;
|
||||
} else if(a_s=="double") {
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_cstr
|
||||
#define tools_cstr
|
||||
|
||||
#include <cstring> // strcpy
|
||||
#include <cstdlib> // malloc,free
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include "mem"
|
||||
#endif
|
||||
|
||||
namespace tools {
|
||||
|
||||
// NOTE : have str_ to avoid clashes with various strxxx cpp macro
|
||||
// that may come from C or system headers.
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
inline const std::string& s_cstr() {
|
||||
static const std::string s_v("tools::cstr");
|
||||
return s_v;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline char* str_dup(const char* a_cstr,bool a_inc = true) {
|
||||
#ifdef TOOLS_MEM
|
||||
if(a_inc) mem::increment(s_cstr().c_str());
|
||||
#else
|
||||
(void)a_inc;
|
||||
#endif
|
||||
return ::strcpy((char*)::malloc(::strlen(a_cstr)+1),a_cstr);
|
||||
}
|
||||
|
||||
inline void str_del(char*& a_cstr) {
|
||||
if(a_cstr==NULL) return;
|
||||
::free(a_cstr);
|
||||
#ifdef TOOLS_MEM
|
||||
mem::decrement(s_cstr().c_str());
|
||||
#endif
|
||||
a_cstr = NULL;
|
||||
}
|
||||
|
||||
inline char* str_new(size_t a_l = 0,char a_char = ' ') {
|
||||
char* s = (char*)::malloc((a_l+1)*sizeof(char));
|
||||
if(s==NULL) return NULL;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_cstr().c_str());
|
||||
#endif
|
||||
char* pos = s;
|
||||
for(size_t c=0;c<a_l;c++,pos++) *pos = a_char;
|
||||
*(s+a_l) = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
inline bool str_cat(char*& a_1,const char a_c) {
|
||||
size_t l1 = ::strlen(a_1);
|
||||
char* s = (char*)::malloc(l1+1+1);
|
||||
if(!s) return false;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_cstr().c_str());
|
||||
#endif
|
||||
::memcpy(s,a_1,l1);
|
||||
::memcpy(s+l1,&a_c,1);
|
||||
*(s+l1+1) = 0;
|
||||
::free(a_1);
|
||||
#ifdef TOOLS_MEM
|
||||
mem::decrement(s_cstr().c_str());
|
||||
#endif
|
||||
a_1 = s;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool str_cat(char*& a_1,const char* a_2) {
|
||||
size_t l1 = ::strlen(a_1);
|
||||
size_t l2 = ::strlen(a_2);
|
||||
char* s = (char*)::malloc(l1+l2+1);
|
||||
if(!s) return false;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_cstr().c_str());
|
||||
#endif
|
||||
::memcpy(s,a_1,l1);
|
||||
::memcpy(s+l1,a_2,l2);
|
||||
*(s+l1+l2) = 0;
|
||||
::free(a_1);
|
||||
#ifdef TOOLS_MEM
|
||||
mem::decrement(s_cstr().c_str());
|
||||
#endif
|
||||
a_1 = s;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void str_rev(char* a_s) {
|
||||
size_t l = ::strlen(a_s);
|
||||
size_t hl = l/2;
|
||||
char* beg = a_s;
|
||||
char* end = a_s+l-1;
|
||||
for(size_t i=0;i<hl;i++) {
|
||||
char c = *end;
|
||||
*end = *beg;
|
||||
*beg = c;
|
||||
beg++;end--;
|
||||
}
|
||||
}
|
||||
|
||||
inline char* str_sub(const char* a_s,
|
||||
unsigned int a_pos,
|
||||
unsigned int a_sz = 0) { //0 = take up end.
|
||||
size_t l = ::strlen(a_s);
|
||||
if(a_pos>=l) return 0; //throw std::out_of_range
|
||||
size_t ls;
|
||||
if(a_sz) {
|
||||
ls = (a_sz<(l-a_pos)?a_sz:(l-a_pos)); //min(a_sz,l-a_pos)
|
||||
} else {
|
||||
ls = l-a_pos;
|
||||
}
|
||||
char* s = (char*)::malloc(ls+1);
|
||||
if(!s) return 0;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_cstr().c_str());
|
||||
#endif
|
||||
//abcdefgh l=8
|
||||
//0123456789
|
||||
::memcpy(s,a_s+a_pos,ls);
|
||||
*(s+ls) = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
inline char* str_rep(const char* a_s,unsigned int a_pos,unsigned int a_sz,const char* a_new) {
|
||||
//not tested yet.
|
||||
size_t las = ::strlen(a_s);
|
||||
if(a_pos>=las) return 0; //throw std::out_of_range
|
||||
if(a_pos+a_sz>las) return 0;
|
||||
size_t lan = ::strlen(a_new);
|
||||
unsigned int num = a_sz<lan?a_sz:(unsigned int)lan;
|
||||
//abcdefghij : l = 10
|
||||
//0123456789
|
||||
// p
|
||||
size_t le = las-(a_pos+a_sz);
|
||||
size_t ls = a_pos+num+le;
|
||||
char* s = (char*)::malloc(ls+1);
|
||||
if(!s) return 0;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_cstr().c_str());
|
||||
#endif
|
||||
::memcpy(s,a_s,a_pos);
|
||||
::memcpy(s+a_pos,a_new,num);
|
||||
if(le) ::memcpy(s+a_pos+num,a_s+a_pos+a_sz,le);
|
||||
*(s+ls) = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
inline void str_skip(char*& a_cstr,char a_c) {
|
||||
while(true) {
|
||||
if(*a_cstr!=a_c) break;
|
||||
a_cstr++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include <clocale>
|
||||
|
||||
namespace tools {
|
||||
|
||||
inline char* beg_LC_NUMERIC() {
|
||||
char* _sl = ::setlocale(LC_NUMERIC,0);
|
||||
char* old = _sl?str_dup(_sl):0;
|
||||
::setlocale(LC_NUMERIC,"C");
|
||||
return old;
|
||||
}
|
||||
inline void end_LC_NUMERIC(char*& a_s) {
|
||||
if(a_s) {
|
||||
::setlocale(LC_NUMERIC,a_s);
|
||||
str_del(a_s);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool str_2d(const char* a_s,double& a_v) {
|
||||
char* olcn = beg_LC_NUMERIC();
|
||||
|
||||
char* end;
|
||||
a_v = ::strtod(a_s,&end);
|
||||
if(end==a_s) {
|
||||
a_v = 0;
|
||||
end_LC_NUMERIC(olcn);
|
||||
return false;
|
||||
}
|
||||
|
||||
end_LC_NUMERIC(olcn);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
inline bool str_2d(const char* a_s,double& a_v) {
|
||||
char* _sl = ::setlocale(LC_NUMERIC,0);
|
||||
char* old = _sl?str_dup(_sl):0;
|
||||
::setlocale(LC_NUMERIC,"C");
|
||||
|
||||
char* end;
|
||||
a_v = ::strtod(a_s,&end);
|
||||
bool status = true;
|
||||
if(end==a_s) {
|
||||
status = false;
|
||||
a_v = 0;
|
||||
}
|
||||
|
||||
if(old) {
|
||||
::setlocale(LC_NUMERIC,old);
|
||||
str_del(old);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -6,14 +6,13 @@
|
||||
|
||||
#include "gzip"
|
||||
#include "forit"
|
||||
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "words" //is_hippo
|
||||
#include "path" //suffix
|
||||
#include "S_STRING"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include "mem"
|
||||
#endif
|
||||
@@ -138,8 +137,7 @@ inline bool read_num(const std::string& a_file,std::vector<std::string>::size_ty
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool read_bytes(const std::string& a_file,
|
||||
char*& a_buffer,long& a_length){
|
||||
inline bool read_bytes(const std::string& a_file,char*& a_buffer,long& a_length){
|
||||
// Returned buffer should be deleted with delete [].
|
||||
FILE* file = ::fopen(a_file.c_str(),"rb");
|
||||
if(!file) {
|
||||
@@ -214,8 +212,87 @@ inline bool is_aida(const std::string& a_file,bool& a_is){
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE : take care of the open in exlib/app/Wt/main_cpp which can't work
|
||||
// by using suffix.
|
||||
inline bool num_csv_doubles(const std::string& a_string,char& a_sep,unsigned int& a_number){
|
||||
if(a_string.empty()) {a_sep=0;a_number=0;return true;} //it is ok.
|
||||
|
||||
//guess sep :
|
||||
char sep = 0;
|
||||
{const char* buffer = a_string.c_str();
|
||||
//::printf("debug : |%s|\n",buffer);
|
||||
const char* pos = buffer;
|
||||
const char* mx = buffer+a_string.size();
|
||||
char* end;
|
||||
{double d = ::strtod(pos,&end);(void)d;}
|
||||
//::printf("debug : d first %g\n",d);
|
||||
if(end==pos) {a_sep=0;a_number=0;return false;} //not starting with a number.
|
||||
if(end==mx) {a_sep=0;a_number=1;return true;} //is ok, one number only.
|
||||
sep = *end;}
|
||||
|
||||
//::printf("debug : %d\n",sep);
|
||||
|
||||
unsigned int number = 0;
|
||||
|
||||
const char* buffer = a_string.c_str();
|
||||
//::printf("debug : |%s|\n",buffer);
|
||||
const char* pos = buffer;
|
||||
const char* mx = buffer+a_string.size();
|
||||
while(true) {
|
||||
char* end;
|
||||
{double d = ::strtod(pos,&end);(void)d;}
|
||||
if(end==pos) {
|
||||
if(end>=mx) break;
|
||||
a_sep = sep;
|
||||
a_number = number;
|
||||
return false; //since a number expected.
|
||||
}
|
||||
//::printf("debug : d %g\n",d);
|
||||
number++;
|
||||
if(*end!=sep) {
|
||||
if(end>=mx) break;
|
||||
a_sep = sep;
|
||||
a_number = number;
|
||||
return false; //since a sep is expected.
|
||||
}
|
||||
pos = end+1;
|
||||
if(pos>mx) break;
|
||||
}
|
||||
|
||||
a_sep = sep;
|
||||
a_number = number;
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE : take care of the open in exlib/app/tntnet/main_cpp which can't work by using suffix.
|
||||
|
||||
inline bool is_hippo(const std::string& a_file,bool& a_is){
|
||||
//if((suffix(a_file)=="hiptxt")||(suffix(a_file)=="tnt")) {
|
||||
// a_is = true;
|
||||
// return true;
|
||||
//}
|
||||
// An hippo file as :
|
||||
// one line for title.
|
||||
// one line with n labels separated by \t
|
||||
// data lines with n numbers separated by a char sep (not necessary \t) (at least one data line expected).
|
||||
std::vector<std::string> txt;
|
||||
if(!file::read_num(a_file,3,txt)) {a_is=false;return false;}
|
||||
if(txt.size()<3) {a_is=false;return true;}
|
||||
char csep;
|
||||
unsigned int number;
|
||||
if(!num_csv_doubles(txt[2],csep,number)) {a_is=false;return true;}
|
||||
std::vector<std::string> words;
|
||||
tools::words(txt[1],"\t",false,words);
|
||||
if(words.size()!=number) {a_is=false;return true;}
|
||||
bool all_doubles = true;
|
||||
tools_vforcit(std::string,words,it) {
|
||||
const char* pos = (*it).c_str();
|
||||
char* end;
|
||||
double d = ::strtod(pos,&end);(void)d;
|
||||
if(end==pos) {all_doubles=false;break;}
|
||||
}
|
||||
a_is = all_doubles?false:true; //all_double=false then we assume the second line is labels of columns.
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE : the below is_csv() does not take into account a column with strings.
|
||||
|
||||
inline bool is_csv(const std::vector<std::string>& a_txt,bool& a_is){
|
||||
@@ -277,19 +354,6 @@ inline bool is_csv(const std::string& a_file,bool& a_is){
|
||||
return is_csv(txt,a_is);
|
||||
}
|
||||
|
||||
inline bool is_hippo(const std::string& a_file,bool& a_is){
|
||||
//if((suffix(a_file)=="hiptxt")||(suffix(a_file)=="tnt")) {
|
||||
// a_is = true;
|
||||
// return true;
|
||||
//}
|
||||
std::vector<std::string> txt;
|
||||
if(!file::read_num(a_file,5,txt)) return false;
|
||||
//skip two first lines (title and labels).
|
||||
std::vector<std::string> htxt;
|
||||
for(unsigned int i=2;i<txt.size();i++) htxt.push_back(txt[i]);
|
||||
return is_csv(htxt,a_is);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#include "fileis"
|
||||
@@ -313,6 +377,12 @@ inline bool mime_type(const std::string& a_file,std::string& a_mime){
|
||||
return true;
|
||||
}}
|
||||
|
||||
{bool is;
|
||||
if(is_ico(a_file,is)&&is) {
|
||||
a_mime = "image/vnd.microsoft.icon";
|
||||
return true;
|
||||
}}
|
||||
|
||||
{bool is;
|
||||
if(is_fits(a_file,is)&&is) {
|
||||
a_mime = "image/fits";
|
||||
@@ -452,64 +522,19 @@ inline bool std_rename(const std::string& a_from,const std::string& a_to) {
|
||||
return (::rename(a_from.c_str(),a_to.c_str()) == 0 ? true : false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// by using C system ////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::string quote(const std::string& a_path) {
|
||||
if(a_path.find(' ')==std::string::npos) return a_path;
|
||||
// path with spaces :
|
||||
if(a_path[0]=='"') return a_path; //Already in double quote.
|
||||
return std::string("\"")+a_path+"\"";
|
||||
}
|
||||
|
||||
// used in OnX/BaseUI.
|
||||
inline bool mv(const std::string& a_from,const std::string& a_to){
|
||||
inline bool copy_bytes(const std::string& a_from,const std::string& a_to) {
|
||||
if(a_to==a_from) return true;
|
||||
#ifdef WIN32
|
||||
std::string cmd = "MOVE /Y";
|
||||
#else
|
||||
std::string cmd = "/bin/mv";
|
||||
char* buffer;
|
||||
long length;
|
||||
if(!read_bytes(a_from,buffer,length)) return false;
|
||||
bool status = write_bytes(a_to,buffer,(size_t)length);
|
||||
delete [] buffer;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::decrement(s_new().c_str());
|
||||
#endif
|
||||
cmd += " ";
|
||||
cmd += quote(a_from);
|
||||
cmd += " ";
|
||||
cmd += quote(a_to);
|
||||
int ret = ::system(cmd.c_str());
|
||||
return (ret==(-1)?false:true);
|
||||
return status;
|
||||
}
|
||||
|
||||
inline bool cp(const std::string& a_from,const std::string& a_to) {
|
||||
if(a_to==a_from) return true;
|
||||
#ifdef WIN32
|
||||
std::string cmd = "COPY /Y";
|
||||
#else
|
||||
std::string cmd = "/bin/cp";
|
||||
#endif
|
||||
cmd += " ";
|
||||
cmd += quote(a_from);
|
||||
cmd += " ";
|
||||
cmd += quote(a_to);
|
||||
int ret = ::system(cmd.c_str());
|
||||
return (ret==(-1)?false:true);
|
||||
}
|
||||
|
||||
inline bool rm(const std::string& a_file){
|
||||
// WARNING : do not confuse with file::std_remove which is
|
||||
// an encapsulation of the remove of stdio.h that
|
||||
// does not support wildcards.
|
||||
#ifdef WIN32
|
||||
std::string cmd = "DEL /Q";
|
||||
#else
|
||||
std::string cmd = "/bin/rm -f";
|
||||
#endif
|
||||
cmd += " ";
|
||||
cmd += quote(a_file);
|
||||
int ret = ::system(cmd.c_str());
|
||||
return (ret==(-1)?false:true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
class holder {
|
||||
public:
|
||||
|
||||
@@ -19,6 +19,7 @@ TOOLS_GLOBAL_STRING(format_fog)
|
||||
TOOLS_GLOBAL_STRING(format_dot)
|
||||
TOOLS_GLOBAL_STRING(format_dcm)
|
||||
TOOLS_GLOBAL_STRING(format_iv)
|
||||
TOOLS_GLOBAL_STRING(format_wrl)
|
||||
TOOLS_GLOBAL_STRING(format_jpeg)
|
||||
TOOLS_GLOBAL_STRING(format_png)
|
||||
TOOLS_GLOBAL_STRING(format_root)
|
||||
@@ -47,6 +48,7 @@ TOOLS_GLOBAL_EXT(dot)
|
||||
TOOLS_GLOBAL_EXT(dcm)
|
||||
TOOLS_GLOBAL_EXT(iv)
|
||||
TOOLS_GLOBAL_EXT(hiv)
|
||||
TOOLS_GLOBAL_EXT(wrl)
|
||||
TOOLS_GLOBAL_EXT(jpg)
|
||||
TOOLS_GLOBAL_EXT(png)
|
||||
TOOLS_GLOBAL_EXT(root)
|
||||
@@ -74,6 +76,7 @@ inline void formats(std::vector<std::string>& a_v) {
|
||||
a_v.push_back(s_format_dot());
|
||||
a_v.push_back(s_format_dcm());
|
||||
a_v.push_back(s_format_iv());
|
||||
a_v.push_back(s_format_wrl());
|
||||
a_v.push_back(s_format_jpeg());
|
||||
a_v.push_back(s_format_png());
|
||||
a_v.push_back(s_format_root());
|
||||
@@ -105,6 +108,7 @@ inline std::string ext_fmt(const std::string& a_ext) {
|
||||
if(a_ext==s_ext_dcm()) return s_format_dcm();
|
||||
if(a_ext==s_ext_iv()) return s_format_iv();
|
||||
if(a_ext==s_ext_hiv()) return s_format_iv();
|
||||
if(a_ext==s_ext_wrl()) return s_format_wrl();
|
||||
if(a_ext==s_ext_exsg()) return s_format_exsg();
|
||||
if(a_ext==s_ext_bsg()) return s_format_bsg();
|
||||
if(a_ext==s_ext_scenarios()) return s_format_scenarios();
|
||||
|
||||
@@ -36,6 +36,19 @@ inline bool is_jpeg(const std::string& a_file,bool& a_is){
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool is_ico(const std::string& a_file,bool& a_is){
|
||||
unsigned char head[4];
|
||||
{unsigned int num = 4;
|
||||
if(!signature(a_file,head,num)) {a_is = false;return false;}
|
||||
if(num!=4) {a_is = false;return true;}}
|
||||
if(head[0]!=0) {a_is = false;return true;}
|
||||
if(head[1]!=0) {a_is = false;return true;}
|
||||
if(head[2]!=1) {a_is = false;return true;}
|
||||
if(head[3]!=0) {a_is = false;return true;}
|
||||
a_is = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool is_png(const std::string& a_file,bool& a_is){
|
||||
unsigned char head[4];
|
||||
{unsigned int num = 4;
|
||||
@@ -81,6 +94,20 @@ inline bool is_iv(const std::string& a_file,bool& a_is){
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool is_wrl(const std::string& a_file,bool& a_is){
|
||||
unsigned char head[5];
|
||||
{unsigned int num = 5;
|
||||
if(!signature(a_file,head,num)) {a_is = false;return false;}
|
||||
if(num!=5) {a_is = false;return true;}}
|
||||
if(head[0]!='#') {a_is = false;return true;}
|
||||
if(head[1]!='V') {a_is = false;return true;}
|
||||
if(head[2]!='R') {a_is = false;return true;}
|
||||
if(head[3]!='M') {a_is = false;return true;}
|
||||
if(head[4]!='L') {a_is = false;return true;}
|
||||
a_is = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool is_fog(const std::string& a_file,bool& a_is){
|
||||
unsigned char head[256];
|
||||
{unsigned int num = 256;
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_fmanip
|
||||
#define tools_fmanip
|
||||
|
||||
#include "file"
|
||||
#include "sep"
|
||||
#include "sout"
|
||||
#include <ostream>
|
||||
|
||||
namespace tools {
|
||||
|
||||
inline bool find_with_dirs(std::ostream& a_out,
|
||||
const std::vector<std::string>& a_dirs,
|
||||
const std::string& a_file,
|
||||
std::string& a_path,
|
||||
bool a_verbose = false ) {
|
||||
std::vector<std::string>::const_iterator it;
|
||||
for(it=a_dirs.begin();it!=a_dirs.end();++it) {
|
||||
if((*it).empty()) {
|
||||
// with a "" in dirs, this case could solve :
|
||||
// - a_file in the current directory.
|
||||
// - a_file with an absolute path name.
|
||||
a_path = a_file; //may be an absolute file name.
|
||||
} else {
|
||||
a_path = *it;
|
||||
a_path += sep();
|
||||
a_path += a_file;
|
||||
}
|
||||
|
||||
if(a_verbose) {
|
||||
a_out << "find_with_dirs :"
|
||||
<< " look for " << tools::sout(a_path) << " ..."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if(tools::file::exists(a_path)) {
|
||||
if(a_verbose) {
|
||||
a_out << "find_with_dirs :"
|
||||
<< " found " << tools::sout(a_path) << "."
|
||||
<< std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
a_path.clear();
|
||||
|
||||
if(a_verbose) {
|
||||
a_out << "find_with_dirs :"
|
||||
<< " " << tools::sout(a_file) << " not found."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "system"
|
||||
|
||||
namespace tools {
|
||||
|
||||
inline bool find_with_path(std::ostream& a_out,
|
||||
const std::string& a_env,
|
||||
const std::string& a_file,
|
||||
std::string& a_path,
|
||||
bool a_verbose = false ) {
|
||||
std::string PATH;
|
||||
if(!tools::getenv(a_env,PATH)) {
|
||||
//look for a a_file in current directory.
|
||||
a_path = a_file;
|
||||
if(tools::file::exists(a_path)) return true;
|
||||
a_out << "tools::find_with_path :"
|
||||
<< " env variable " << sout(a_env) << " not defined."
|
||||
<< std::endl;
|
||||
a_path.clear();
|
||||
return false;
|
||||
}
|
||||
if(a_verbose) {
|
||||
a_out << "find_with_path :"
|
||||
<< " PATH is " << tools::sout(PATH)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
std::vector<std::string> dirs;
|
||||
tools::words(PATH,psep(),false,dirs); //or true ?
|
||||
|
||||
return find_with_dirs(a_out,dirs,a_file,a_path,a_verbose);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,48 +5,43 @@
|
||||
#define tools_forit
|
||||
|
||||
#define tools_vforcit(a__T,a__v,a__it) \
|
||||
for(std::vector< a__T >::const_iterator (a__it) = (a__v).begin();\
|
||||
(a__it)!=(a__v).end();++(a__it))
|
||||
for(std::vector< a__T >::const_iterator (a__it) = (a__v).begin();(a__it)!=(a__v).end();++(a__it))
|
||||
|
||||
#define tools_vforit(a__T,a__v,a__it) \
|
||||
for(std::vector< a__T >::iterator (a__it) = (a__v).begin();\
|
||||
(a__it)!=(a__v).end();++(a__it))
|
||||
for(std::vector< a__T >::iterator (a__it) = (a__v).begin();(a__it)!=(a__v).end();++(a__it))
|
||||
|
||||
#define tools_typename_vforcit(a__T,a__v,a__it_t,a__it) \
|
||||
typedef typename std::vector< a__T >::const_iterator a__it_t;\
|
||||
for(a__it_t (a__it) = (a__v).begin();(a__it)!=(a__v).end();++(a__it))
|
||||
#define tools_vforit_npp(a__T,a__v,a__it) \
|
||||
for(std::vector< a__T >::iterator (a__it) = (a__v).begin();(a__it)!=(a__v).end();)
|
||||
|
||||
#define tools_typename_vforcit(a__T,a__v,a__it) \
|
||||
for(typename std::vector< a__T >::const_iterator (a__it) = (a__v).begin();(a__it)!=(a__v).end();++(a__it))
|
||||
|
||||
#define tools_typename_vforit(a__T,a__v,a__it) \
|
||||
for(typename std::vector< a__T >::iterator (a__it) = (a__v).begin();(a__it)!=(a__v).end();++(a__it))
|
||||
|
||||
#define tools_sforcit(a__s,a__it) \
|
||||
for(std::string::const_iterator (a__it) = (a__s).begin();\
|
||||
(a__it)!=(a__s).end();++(a__it))
|
||||
for(std::string::const_iterator (a__it) = (a__s).begin();(a__it)!=(a__s).end();++(a__it))
|
||||
|
||||
#define tools_sforit(a__s,a__it) \
|
||||
for(std::string::iterator (a__it) = (a__s).begin();\
|
||||
(a__it)!=(a__s).end();++(a__it))
|
||||
for(std::string::iterator (a__it) = (a__s).begin();(a__it)!=(a__s).end();++(a__it))
|
||||
|
||||
#define tools_lforcit(a__T,a__l,a__it) \
|
||||
for(std::list< a__T >::const_iterator (a__it) = (a__l).begin();\
|
||||
(a__it)!=(a__l).end();++(a__it))
|
||||
for(std::list< a__T >::const_iterator (a__it) = (a__l).begin();(a__it)!=(a__l).end();++(a__it))
|
||||
|
||||
#define tools_lforit(a__T,a__l,a__it) \
|
||||
for(std::list< a__T >::iterator (a__it) = (a__l).begin();\
|
||||
(a__it)!=(a__l).end();++(a__it))
|
||||
for(std::list< a__T >::iterator (a__it) = (a__l).begin();(a__it)!=(a__l).end();++(a__it))
|
||||
|
||||
#define tools_mforcit(a__K,a__V,a__m,a__it) \
|
||||
for(std::map< a__K , a__V >::const_iterator (a__it) = (a__m).begin();\
|
||||
(a__it)!=(a__m).end();++(a__it))
|
||||
for(std::map< a__K , a__V >::const_iterator (a__it) = (a__m).begin();(a__it)!=(a__m).end();++(a__it))
|
||||
|
||||
#define tools_mforit(a__K,a__V,a__m,a__it) \
|
||||
for(std::map< a__K , a__V >::iterator (a__it) = (a__m).begin();\
|
||||
(a__it)!=(a__m).end();++(a__it))
|
||||
for(std::map< a__K , a__V >::iterator (a__it) = (a__m).begin();(a__it)!=(a__m).end();++(a__it))
|
||||
|
||||
#define tools_typename_mforcit(a__K,a__V,a__m,a__it_t,a__it) \
|
||||
typedef typename std::map< a__K, a__V >::const_iterator a__it_t;\
|
||||
for(a__it_t (a__it) = (a__m).begin();(a__it)!=(a__m).end();++(a__it))
|
||||
#define tools_typename_mforcit(a__K,a__V,a__m,a__it) \
|
||||
for(typename std::map< a__K, a__V >::const_iterator (a__it) = (a__m).begin();(a__it)!=(a__m).end();++(a__it))
|
||||
|
||||
#define tools_typename_mforit(a__K,a__V,a__m,a__it_t,a__it) \
|
||||
typedef typename std::map< a__K, a__V >::iterator a__it_t;\
|
||||
for(a__it_t (a__it) = (a__m).begin();(a__it)!=(a__m).end();++(a__it))
|
||||
#define tools_typename_mforit(a__K,a__V,a__m,a__it) \
|
||||
for(typename std::map< a__K, a__V >::iterator (a__it) = (a__m).begin();(a__it)!=(a__m).end();++(a__it))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_glprims
|
||||
#define tools_glprims
|
||||
|
||||
//same as OpenGL GL_[POINTS,etc...], but for the case we don't have OpenGL.
|
||||
|
||||
namespace tools {
|
||||
namespace gl {
|
||||
|
||||
typedef unsigned char mode_t;
|
||||
|
||||
inline mode_t points() {return 0x0000;}
|
||||
inline mode_t lines() {return 0x0001;} //segments
|
||||
inline mode_t line_loop() {return 0x0002;}
|
||||
inline mode_t line_strip() {return 0x0003;} //polyline
|
||||
inline mode_t triangles() {return 0x0004;}
|
||||
inline mode_t triangle_strip() {return 0x0005;}
|
||||
inline mode_t triangle_fan() {return 0x0006;}
|
||||
//inline mode_t quads() {return 0x0007;}
|
||||
//inline mode_t quad_strip() {return 0x0008;}
|
||||
//inline mode_t polygon() {return 0x0009;}
|
||||
|
||||
inline bool is_mode(mode_t a_mode) {
|
||||
return a_mode<=0x006?true:false;
|
||||
}
|
||||
|
||||
inline bool is_line(mode_t a_mode) {
|
||||
if(a_mode==points()) return true; //0 sz line !
|
||||
if(a_mode==lines()) return true;
|
||||
if(a_mode==line_loop()) return true;
|
||||
if(a_mode==line_strip()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void cvt_2to3(unsigned int a_npt,const float* a_xys,float*& a_xyzs) {
|
||||
const float* vpos = a_xys;
|
||||
float x,y;
|
||||
for(unsigned int i=0;i<a_npt;i++) {
|
||||
x = *vpos;vpos++;
|
||||
y = *vpos;vpos++;
|
||||
*a_xyzs = x;a_xyzs++;
|
||||
*a_xyzs = y;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void triangle_fan_to_triangles(unsigned int a_npt,
|
||||
const float* a_fxyzs,
|
||||
const float* a_fnms,
|
||||
float*& a_xyzs,
|
||||
float*& a_nms) {
|
||||
|
||||
{const float* vpos = a_fxyzs;
|
||||
|
||||
float x1 = *vpos;vpos++;
|
||||
float y1 = *vpos;vpos++;
|
||||
float z1 = *vpos;vpos++;
|
||||
|
||||
float x2 = *vpos;vpos++;
|
||||
float y2 = *vpos;vpos++;
|
||||
float z2 = *vpos;vpos++;
|
||||
|
||||
float x3,y3,z3;
|
||||
for(unsigned int i=2;i<a_npt;i++) {
|
||||
x3 = *vpos;vpos++;
|
||||
y3 = *vpos;vpos++;
|
||||
z3 = *vpos;vpos++;
|
||||
*a_xyzs = x1;a_xyzs++;
|
||||
*a_xyzs = y1;a_xyzs++;
|
||||
*a_xyzs = z1;a_xyzs++;
|
||||
|
||||
*a_xyzs = x2;a_xyzs++;
|
||||
*a_xyzs = y2;a_xyzs++;
|
||||
*a_xyzs = z2;a_xyzs++;
|
||||
|
||||
*a_xyzs = x3;a_xyzs++;
|
||||
*a_xyzs = y3;a_xyzs++;
|
||||
*a_xyzs = z3;a_xyzs++;
|
||||
|
||||
x2 = x3;
|
||||
y2 = y3;
|
||||
z2 = z3;
|
||||
}}
|
||||
|
||||
{const float* vpos = a_fnms;
|
||||
|
||||
float x1 = *vpos;vpos++;
|
||||
float y1 = *vpos;vpos++;
|
||||
float z1 = *vpos;vpos++;
|
||||
|
||||
float x2 = *vpos;vpos++;
|
||||
float y2 = *vpos;vpos++;
|
||||
float z2 = *vpos;vpos++;
|
||||
|
||||
float x3,y3,z3;
|
||||
for(unsigned int i=2;i<a_npt;i++) {
|
||||
x3 = *vpos;vpos++;
|
||||
y3 = *vpos;vpos++;
|
||||
z3 = *vpos;vpos++;
|
||||
*a_nms = x1;a_nms++;
|
||||
*a_nms = y1;a_nms++;
|
||||
*a_nms = z1;a_nms++;
|
||||
|
||||
*a_nms = x2;a_nms++;
|
||||
*a_nms = y2;a_nms++;
|
||||
*a_nms = z2;a_nms++;
|
||||
|
||||
*a_nms = x3;a_nms++;
|
||||
*a_nms = y3;a_nms++;
|
||||
*a_nms = z3;a_nms++;
|
||||
|
||||
x2 = x3;
|
||||
y2 = y3;
|
||||
z2 = z3;
|
||||
}}
|
||||
}
|
||||
|
||||
inline void triangle_strip_to_triangles(unsigned int a_npt,
|
||||
const float* a_fxyzs,
|
||||
const float* a_fnms,
|
||||
float*& a_xyzs,
|
||||
float*& a_nms) {
|
||||
|
||||
{const float* vpos = a_fxyzs;
|
||||
|
||||
float x1 = *vpos;vpos++;
|
||||
float y1 = *vpos;vpos++;
|
||||
float z1 = *vpos;vpos++;
|
||||
|
||||
float x2 = *vpos;vpos++;
|
||||
float y2 = *vpos;vpos++;
|
||||
float z2 = *vpos;vpos++;
|
||||
|
||||
float x3,y3,z3;
|
||||
bool flip = false;
|
||||
for(unsigned int i=2;i<a_npt;i++) {
|
||||
x3 = *vpos;vpos++;
|
||||
y3 = *vpos;vpos++;
|
||||
z3 = *vpos;vpos++;
|
||||
|
||||
if(flip) {
|
||||
*a_xyzs = x1;a_xyzs++;
|
||||
*a_xyzs = y1;a_xyzs++;
|
||||
*a_xyzs = z1;a_xyzs++;
|
||||
|
||||
*a_xyzs = x3;a_xyzs++;
|
||||
*a_xyzs = y3;a_xyzs++;
|
||||
*a_xyzs = z3;a_xyzs++;
|
||||
|
||||
*a_xyzs = x2;a_xyzs++;
|
||||
*a_xyzs = y2;a_xyzs++;
|
||||
*a_xyzs = z2;a_xyzs++;
|
||||
} else {
|
||||
*a_xyzs = x1;a_xyzs++;
|
||||
*a_xyzs = y1;a_xyzs++;
|
||||
*a_xyzs = z1;a_xyzs++;
|
||||
|
||||
*a_xyzs = x2;a_xyzs++;
|
||||
*a_xyzs = y2;a_xyzs++;
|
||||
*a_xyzs = z2;a_xyzs++;
|
||||
|
||||
*a_xyzs = x3;a_xyzs++;
|
||||
*a_xyzs = y3;a_xyzs++;
|
||||
*a_xyzs = z3;a_xyzs++;
|
||||
}
|
||||
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
z1 = z2;
|
||||
|
||||
x2 = x3;
|
||||
y2 = y3;
|
||||
z2 = z3;
|
||||
|
||||
flip = flip?false:true;
|
||||
}}
|
||||
|
||||
{const float* vpos = a_fnms;
|
||||
|
||||
float x1 = *vpos;vpos++;
|
||||
float y1 = *vpos;vpos++;
|
||||
float z1 = *vpos;vpos++;
|
||||
|
||||
float x2 = *vpos;vpos++;
|
||||
float y2 = *vpos;vpos++;
|
||||
float z2 = *vpos;vpos++;
|
||||
|
||||
float x3,y3,z3;
|
||||
bool flip = false;
|
||||
for(unsigned int i=2;i<a_npt;i++) {
|
||||
x3 = *vpos;vpos++;
|
||||
y3 = *vpos;vpos++;
|
||||
z3 = *vpos;vpos++;
|
||||
|
||||
if(flip) {
|
||||
*a_nms = x1;a_nms++;
|
||||
*a_nms = y1;a_nms++;
|
||||
*a_nms = z1;a_nms++;
|
||||
|
||||
*a_nms = x3;a_nms++;
|
||||
*a_nms = y3;a_nms++;
|
||||
*a_nms = z3;a_nms++;
|
||||
|
||||
*a_nms = x2;a_nms++;
|
||||
*a_nms = y2;a_nms++;
|
||||
*a_nms = z2;a_nms++;
|
||||
} else {
|
||||
*a_nms = x1;a_nms++;
|
||||
*a_nms = y1;a_nms++;
|
||||
*a_nms = z1;a_nms++;
|
||||
|
||||
*a_nms = x2;a_nms++;
|
||||
*a_nms = y2;a_nms++;
|
||||
*a_nms = z2;a_nms++;
|
||||
|
||||
*a_nms = x3;a_nms++;
|
||||
*a_nms = y3;a_nms++;
|
||||
*a_nms = z3;a_nms++;
|
||||
}
|
||||
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
z1 = z2;
|
||||
|
||||
x2 = x3;
|
||||
y2 = y3;
|
||||
z2 = z3;
|
||||
flip = flip?false:true;
|
||||
}}
|
||||
}
|
||||
|
||||
inline void triangle_fan_to_triangles_2to3(unsigned int a_npt,
|
||||
const float* a_xys,
|
||||
float*& a_xyzs) {
|
||||
|
||||
const float* vpos = a_xys;
|
||||
|
||||
float x1 = *vpos;vpos++;
|
||||
float y1 = *vpos;vpos++;
|
||||
|
||||
float x2 = *vpos;vpos++;
|
||||
float y2 = *vpos;vpos++;
|
||||
|
||||
float x3,y3;
|
||||
for(unsigned int i=2;i<a_npt;i++) {
|
||||
x3 = *vpos;vpos++;
|
||||
y3 = *vpos;vpos++;
|
||||
|
||||
*a_xyzs = x1;a_xyzs++;
|
||||
*a_xyzs = y1;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
|
||||
*a_xyzs = x2;a_xyzs++;
|
||||
*a_xyzs = y2;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
|
||||
*a_xyzs = x3;a_xyzs++;
|
||||
*a_xyzs = y3;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
|
||||
x2 = x3;
|
||||
y2 = y3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline void triangle_strip_to_triangles_2to3(unsigned int a_npt,
|
||||
const float* a_xys,
|
||||
float*& a_xyzs) {
|
||||
|
||||
const float* vpos = a_xys;
|
||||
|
||||
float x1 = *vpos;vpos++;
|
||||
float y1 = *vpos;vpos++;
|
||||
|
||||
float x2 = *vpos;vpos++;
|
||||
float y2 = *vpos;vpos++;
|
||||
|
||||
float x3,y3;
|
||||
bool flip = false;
|
||||
for(unsigned int i=2;i<a_npt;i++) {
|
||||
x3 = *vpos;vpos++;
|
||||
y3 = *vpos;vpos++;
|
||||
|
||||
if(flip) {
|
||||
*a_xyzs = x1;a_xyzs++;
|
||||
*a_xyzs = y1;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
|
||||
*a_xyzs = x3;a_xyzs++;
|
||||
*a_xyzs = y3;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
|
||||
*a_xyzs = x2;a_xyzs++;
|
||||
*a_xyzs = y2;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
} else {
|
||||
*a_xyzs = x1;a_xyzs++;
|
||||
*a_xyzs = y1;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
|
||||
*a_xyzs = x2;a_xyzs++;
|
||||
*a_xyzs = y2;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
|
||||
*a_xyzs = x3;a_xyzs++;
|
||||
*a_xyzs = y3;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
}
|
||||
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
|
||||
x2 = x3;
|
||||
y2 = y3;
|
||||
|
||||
flip = flip?false:true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline void line_strip_to_lines_2to3(unsigned int a_npt,
|
||||
const float* a_xys,
|
||||
float*& a_xyzs) {
|
||||
|
||||
const float* vpos = a_xys;
|
||||
|
||||
float x1 = *vpos;vpos++;
|
||||
float y1 = *vpos;vpos++;
|
||||
|
||||
float x2,y2;
|
||||
for(unsigned int i=1;i<a_npt;i++) {
|
||||
x2 = *vpos;vpos++;
|
||||
y2 = *vpos;vpos++;
|
||||
|
||||
*a_xyzs = x1;a_xyzs++;
|
||||
*a_xyzs = y1;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
|
||||
*a_xyzs = x2;a_xyzs++;
|
||||
*a_xyzs = y2;a_xyzs++;
|
||||
*a_xyzs = 0;a_xyzs++;
|
||||
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
G.Barrand : glu.h of Mesa-7.8.1 but containing only tess related material.
|
||||
We bring also the needed material from gl.h.
|
||||
*/
|
||||
|
||||
#ifndef tools_glutess__glu
|
||||
#define tools_glutess__glu
|
||||
|
||||
#include "rename"
|
||||
|
||||
/* //////////////////////////////////////////////////////////////// */
|
||||
/* //////////////////////////////////////////////////////////////// */
|
||||
|
||||
typedef unsigned int GLUenum;
|
||||
typedef void GLUvoid;
|
||||
typedef double GLUdouble;
|
||||
|
||||
typedef unsigned char GLUboolean;
|
||||
typedef float GLUfloat; /* single precision float */
|
||||
typedef double GLUclampd; /* double precision float in [0,1] */
|
||||
|
||||
/* //////////////////////////////////////////////////////////////// */
|
||||
/* //////////////////////////////////////////////////////////////// */
|
||||
/* //////////////////////////////////////////////////////////////// */
|
||||
|
||||
/* TessCallback */
|
||||
#define GLU_TESS_BEGIN_DATA 100106
|
||||
#define GLU_TESS_VERTEX_DATA 100107
|
||||
#define GLU_TESS_END_DATA 100108
|
||||
#define GLU_TESS_ERROR_DATA 100109
|
||||
#define GLU_TESS_COMBINE_DATA 100111
|
||||
|
||||
/* TessProperty */
|
||||
#define GLU_TESS_WINDING_RULE 100140
|
||||
//#define GLU_TESS_TOLERANCE 100142
|
||||
|
||||
/* TessWinding */
|
||||
#define GLU_TESS_WINDING_ODD 100130
|
||||
#define GLU_TESS_WINDING_POSITIVE 100132
|
||||
#define GLU_TESS_WINDING_NEGATIVE 100133
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
// mesa glu has the below for Windows.
|
||||
//#define GLUAPIENTRY __stdcall
|
||||
//typedef void (__stdcall* _GLUfuncptr)();
|
||||
|
||||
#define GLUAPIENTRY
|
||||
typedef void (* _GLUfuncptr)();
|
||||
|
||||
#define GLUAPI
|
||||
|
||||
typedef struct GLUtesselator GLUtesselator;
|
||||
|
||||
typedef GLUtesselator GLUtesselatorObj;
|
||||
typedef GLUtesselator GLUtriangulatorObj;
|
||||
|
||||
/*
|
||||
GLUAPI GLUtesselator* GLUAPIENTRY gluNewTess (void);
|
||||
GLUAPI void GLUAPIENTRY gluDeleteTess (GLUtesselator* tess);
|
||||
|
||||
GLUAPI void GLUAPIENTRY gluTessBeginContour (GLUtesselator* tess);
|
||||
GLUAPI void GLUAPIENTRY gluTessBeginPolygon (GLUtesselator* tess, GLUvoid* data);
|
||||
GLUAPI void GLUAPIENTRY gluTessCallback (GLUtesselator* tess, GLUenum which, _GLUfuncptr CallBackFunc);
|
||||
GLUAPI void GLUAPIENTRY gluTessEndContour (GLUtesselator* tess);
|
||||
GLUAPI void GLUAPIENTRY gluTessEndPolygon (GLUtesselator* tess);
|
||||
GLUAPI void GLUAPIENTRY gluTessNormal (GLUtesselator* tess, GLUdouble valueX, GLUdouble valueY, GLUdouble valueZ);
|
||||
GLUAPI void GLUAPIENTRY gluTessProperty (GLUtesselator* tess, GLUenum which, GLUdouble data);
|
||||
GLUAPI void GLUAPIENTRY gluTessVertex (GLUtesselator* tess, GLUdouble *location, GLUvoid* data);
|
||||
*/
|
||||
|
||||
#define GLU_MIN(x,y) ((x) <= (y) ? (x) : (y))
|
||||
#define GLU_MAX(x,y) ((x) >= (y) ? (x) : (y))
|
||||
#define GLU_ABS(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
/* //////////////////////////////////////////////////////////////// */
|
||||
/* //////////////////////////////////////////////////////////////// */
|
||||
/* //////////////////////////////////////////////////////////////// */
|
||||
|
||||
/* Boolean values */
|
||||
#define GLU_FALSE 0x0
|
||||
#define GLU_TRUE 0x1
|
||||
|
||||
/* Primitives */
|
||||
#define GLU_LINE_LOOP 0x0002
|
||||
#define GLU_TRIANGLES 0x0004
|
||||
#define GLU_TRIANGLE_STRIP 0x0005
|
||||
#define GLU_TRIANGLE_FAN 0x0006
|
||||
|
||||
#define GLU_TESS_MAX_COORD 1.0e150
|
||||
|
||||
/* ErrorCode */
|
||||
#define GLU_INVALID_ENUM 100900
|
||||
#define GLU_INVALID_VALUE 100901
|
||||
#define GLU_OUT_OF_MEMORY 100902
|
||||
#define GLU_INCOMPATIBLE_GL_VERSION 100903
|
||||
#define GLU_INVALID_OPERATION 100904
|
||||
|
||||
/* TessCallback */
|
||||
#define GLU_TESS_BEGIN 100100
|
||||
#define GLU_TESS_VERTEX 100101
|
||||
#define GLU_TESS_END 100102
|
||||
#define GLU_TESS_ERROR 100103
|
||||
#define GLU_TESS_EDGE_FLAG 100104
|
||||
#define GLU_EDGE_FLAG 100104
|
||||
#define GLU_TESS_COMBINE 100105
|
||||
#define GLU_TESS_EDGE_FLAG_DATA 100110
|
||||
|
||||
/* TessContour */
|
||||
#define GLU_CW 100120
|
||||
#define GLU_CCW 100121
|
||||
#define GLU_INTERIOR 100122
|
||||
#define GLU_EXTERIOR 100123
|
||||
#define GLU_UNKNOWN 100124
|
||||
|
||||
/* TessProperty */
|
||||
#define GLU_TESS_BOUNDARY_ONLY 100141
|
||||
#define GLU_TESS_TOLERANCE 100142
|
||||
|
||||
/* TessError */
|
||||
#define GLU_TESS_ERROR1 100151
|
||||
#define GLU_TESS_ERROR2 100152
|
||||
#define GLU_TESS_ERROR3 100153
|
||||
#define GLU_TESS_ERROR4 100154
|
||||
#define GLU_TESS_ERROR5 100155
|
||||
#define GLU_TESS_ERROR6 100156
|
||||
#define GLU_TESS_ERROR7 100157
|
||||
#define GLU_TESS_ERROR8 100158
|
||||
#define GLU_TESS_MISSING_BEGIN_POLYGON 100151
|
||||
#define GLU_TESS_MISSING_BEGIN_CONTOUR 100152
|
||||
#define GLU_TESS_MISSING_END_POLYGON 100153
|
||||
#define GLU_TESS_MISSING_END_CONTOUR 100154
|
||||
#define GLU_TESS_COORD_TOO_LARGE 100155
|
||||
#define GLU_TESS_NEED_COMBINE_CALLBACK 100156
|
||||
|
||||
/* TessWinding */
|
||||
#define GLU_TESS_WINDING_NONZERO 100131
|
||||
#define GLU_TESS_WINDING_ABS_GEQ_TWO 100134
|
||||
|
||||
#endif /* __glu_h__ */
|
||||
@@ -0,0 +1,133 @@
|
||||
// see license file for original license.
|
||||
|
||||
#ifndef tools_glutess__tess
|
||||
#define tools_glutess__tess
|
||||
|
||||
#include "mesh"
|
||||
#include "dict"
|
||||
#include "priorityq"
|
||||
|
||||
#include <csetjmp>
|
||||
|
||||
/* The begin/end calls must be properly nested. We keep track of
|
||||
* the current state to enforce the ordering.
|
||||
*/
|
||||
enum TessState { T_DORMANT, T_IN_POLYGON, T_IN_CONTOUR };
|
||||
|
||||
/* We cache vertex data for single-contour polygons so that we can
|
||||
* try a quick-and-dirty decomposition first.
|
||||
*/
|
||||
#define GLU_TESS_MAX_CACHE 100
|
||||
|
||||
typedef struct CachedVertex {
|
||||
GLUdouble coords[3];
|
||||
void *data;
|
||||
} CachedVertex;
|
||||
|
||||
struct GLUtesselator {
|
||||
|
||||
/*** state needed for collecting the input data ***/
|
||||
|
||||
enum TessState state; /* what begin/end calls have we seen? */
|
||||
|
||||
GLUhalfEdge *lastEdge; /* lastEdge->Org is the most recent vertex */
|
||||
GLUmesh *mesh; /* stores the input contours, and eventually
|
||||
the tessellation itself */
|
||||
|
||||
void (GLUAPIENTRY *callError)( GLUenum errnum );
|
||||
|
||||
/*** state needed for projecting onto the sweep plane ***/
|
||||
|
||||
GLUdouble normal[3]; /* user-specified normal (if provided) */
|
||||
GLUdouble sUnit[3]; /* unit vector in s-direction (debugging) */
|
||||
GLUdouble tUnit[3]; /* unit vector in t-direction (debugging) */
|
||||
|
||||
/*** state needed for the line sweep ***/
|
||||
|
||||
GLUdouble relTolerance; /* tolerance for merging features */
|
||||
GLUenum windingRule; /* rule for determining polygon interior */
|
||||
GLUboolean fatalError; /* fatal error: needed combine callback */
|
||||
|
||||
Dict *dict; /* edge dictionary for sweep line */
|
||||
PriorityQ *pq; /* priority queue of vertex events */
|
||||
GLUvertex *event; /* current sweep event being processed */
|
||||
|
||||
void (GLUAPIENTRY *callCombine)( GLUdouble coords[3], void *data[4],
|
||||
GLUfloat weight[4], void **outData );
|
||||
|
||||
/*** state needed for rendering callbacks (see render.c) ***/
|
||||
|
||||
GLUboolean flagBoundary; /* mark boundary edges (use EdgeFlag) */
|
||||
GLUboolean boundaryOnly; /* Extract contours, not triangles */
|
||||
GLUface *lonelyTriList;
|
||||
/* list of triangles which could not be rendered as strips or fans */
|
||||
|
||||
void (GLUAPIENTRY *callBegin)( GLUenum type );
|
||||
void (GLUAPIENTRY *callEdgeFlag)( GLUboolean boundaryEdge );
|
||||
void (GLUAPIENTRY *callVertex)( void *data );
|
||||
void (GLUAPIENTRY *callEnd)( void );
|
||||
void (GLUAPIENTRY *callMesh)( GLUmesh *mesh );
|
||||
|
||||
|
||||
/*** state needed to cache single-contour polygons for renderCache() */
|
||||
|
||||
GLUboolean emptyCache; /* empty cache on next vertex() call */
|
||||
int cacheCount; /* number of cached vertices */
|
||||
CachedVertex cache[GLU_TESS_MAX_CACHE]; /* the vertex data */
|
||||
|
||||
/*** rendering callbacks that also pass polygon data ***/
|
||||
void (GLUAPIENTRY *callBeginData)( GLUenum type, void *polygonData );
|
||||
void (GLUAPIENTRY *callEdgeFlagData)( GLUboolean boundaryEdge,
|
||||
void *polygonData );
|
||||
void (GLUAPIENTRY *callVertexData)( void *data, void *polygonData );
|
||||
void (GLUAPIENTRY *callEndData)( void *polygonData );
|
||||
void (GLUAPIENTRY *callErrorData)( GLUenum errnum, void *polygonData );
|
||||
void (GLUAPIENTRY *callCombineData)( GLUdouble coords[3], void *data[4],
|
||||
GLUfloat weight[4], void **outData,
|
||||
void *polygonData );
|
||||
|
||||
jmp_buf env; /* place to jump to when memAllocs fail */
|
||||
|
||||
void *polygonData; /* client data for current polygon */
|
||||
};
|
||||
|
||||
void GLUAPIENTRY __gl_noBeginData( GLUenum type, void *polygonData );
|
||||
void GLUAPIENTRY __gl_noEdgeFlagData( GLUboolean boundaryEdge, void *polygonData );
|
||||
void GLUAPIENTRY __gl_noVertexData( void *data, void *polygonData );
|
||||
void GLUAPIENTRY __gl_noEndData( void *polygonData );
|
||||
void GLUAPIENTRY __gl_noErrorData( GLUenum errnum, void *polygonData );
|
||||
void GLUAPIENTRY __gl_noCombineData( GLUdouble coords[3], void *data[4],
|
||||
GLUfloat weight[4], void **outData,
|
||||
void *polygonData );
|
||||
|
||||
#define CALL_BEGIN_OR_BEGIN_DATA(a) \
|
||||
if (tess->callBeginData != &__gl_noBeginData) \
|
||||
(*tess->callBeginData)((a),tess->polygonData); \
|
||||
else (*tess->callBegin)((a));
|
||||
|
||||
#define CALL_VERTEX_OR_VERTEX_DATA(a) \
|
||||
if (tess->callVertexData != &__gl_noVertexData) \
|
||||
(*tess->callVertexData)((a),tess->polygonData); \
|
||||
else (*tess->callVertex)((a));
|
||||
|
||||
#define CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA(a) \
|
||||
if (tess->callEdgeFlagData != &__gl_noEdgeFlagData) \
|
||||
(*tess->callEdgeFlagData)((a),tess->polygonData); \
|
||||
else (*tess->callEdgeFlag)((a));
|
||||
|
||||
#define CALL_END_OR_END_DATA() \
|
||||
if (tess->callEndData != &__gl_noEndData) \
|
||||
(*tess->callEndData)(tess->polygonData); \
|
||||
else (*tess->callEnd)();
|
||||
|
||||
#define CALL_COMBINE_OR_COMBINE_DATA(a,b,c,d) \
|
||||
if (tess->callCombineData != &__gl_noCombineData) \
|
||||
(*tess->callCombineData)((a),(b),(c),(d),tess->polygonData); \
|
||||
else (*tess->callCombine)((a),(b),(c),(d));
|
||||
|
||||
#define CALL_ERROR_OR_ERROR_DATA(a) \
|
||||
if (tess->callErrorData != &__gl_noErrorData) \
|
||||
(*tess->callErrorData)((a),tess->polygonData); \
|
||||
else (*tess->callError)((a));
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
// see license file for original license.
|
||||
|
||||
#ifndef tools_glutess_dict_list
|
||||
#define tools_glutess_dict_list
|
||||
|
||||
/* Use #define's so that another heap implementation can use this one */
|
||||
|
||||
#define DictKey DictListKey
|
||||
#define Dict DictList
|
||||
#define DictNode DictListNode
|
||||
|
||||
#define dictNewDict(frame,leq) __gl_dictListNewDict(frame,leq)
|
||||
#define dictDeleteDict(dict) __gl_dictListDeleteDict(dict)
|
||||
|
||||
#define dictSearch(dict,key) __gl_dictListSearch(dict,key)
|
||||
#define dictInsert(dict,key) __gl_dictListInsert(dict,key)
|
||||
#define dictInsertBefore(dict,node,key) __gl_dictListInsertBefore(dict,node,key)
|
||||
#define dictDelete(dict,node) __gl_dictListDelete(dict,node)
|
||||
|
||||
#define dictKey(n) __gl_dictListKey(n)
|
||||
#define dictSucc(n) __gl_dictListSucc(n)
|
||||
#define dictPred(n) __gl_dictListPred(n)
|
||||
#define dictMin(d) __gl_dictListMin(d)
|
||||
#define dictMax(d) __gl_dictListMax(d)
|
||||
|
||||
typedef void *DictKey;
|
||||
typedef struct Dict Dict;
|
||||
typedef struct DictNode DictNode;
|
||||
|
||||
#define __gl_dictListKey(n) ((n)->key)
|
||||
#define __gl_dictListSucc(n) ((n)->next)
|
||||
#define __gl_dictListPred(n) ((n)->prev)
|
||||
#define __gl_dictListMin(d) ((d)->head.next)
|
||||
#define __gl_dictListMax(d) ((d)->head.prev)
|
||||
#define __gl_dictListInsert(d,k) (dictInsertBefore((d),&(d)->head,(k)))
|
||||
|
||||
/*** Private data structures ***/
|
||||
|
||||
struct DictNode {
|
||||
DictKey key;
|
||||
DictNode *next;
|
||||
DictNode *prev;
|
||||
};
|
||||
|
||||
struct Dict {
|
||||
DictNode head;
|
||||
void *frame;
|
||||
int (*leq)(void *frame, DictKey key1, DictKey key2);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
/// inlined C code : ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
#include <cstddef>
|
||||
#include "memalloc"
|
||||
|
||||
inline Dict *dictNewDict( void *frame,int (*leq)(void *frame, DictKey key1, DictKey key2) ) {
|
||||
Dict *dict = (Dict *) memAlloc( sizeof( Dict ));
|
||||
DictNode *head;
|
||||
|
||||
if (dict == NULL) return NULL;
|
||||
|
||||
head = &dict->head;
|
||||
|
||||
head->key = NULL;
|
||||
head->next = head;
|
||||
head->prev = head;
|
||||
|
||||
dict->frame = frame;
|
||||
dict->leq = leq;
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
inline void dictDeleteDict( Dict *dict ) {
|
||||
DictNode *node, *next;
|
||||
|
||||
for( node = dict->head.next; node != &dict->head; node = next ) {
|
||||
next = node->next;
|
||||
memFree( node );
|
||||
}
|
||||
memFree( dict );
|
||||
}
|
||||
|
||||
/* Search returns the node with the smallest key greater than or equal
|
||||
* to the given key. If there is no such key, returns a node whose
|
||||
* key is NULL. Similarly, Succ(Max(d)) has a NULL key, etc.
|
||||
*/
|
||||
|
||||
inline DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key ) {
|
||||
DictNode *newNode;
|
||||
|
||||
do {
|
||||
node = node->prev;
|
||||
} while( node->key != NULL && ! (*dict->leq)(dict->frame, node->key, key));
|
||||
|
||||
newNode = (DictNode *) memAlloc( sizeof( DictNode ));
|
||||
if (newNode == NULL) return NULL;
|
||||
|
||||
newNode->key = key;
|
||||
newNode->next = node->next;
|
||||
node->next->prev = newNode;
|
||||
newNode->prev = node;
|
||||
node->next = newNode;
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
inline void dictDelete( Dict * /*dict*/, DictNode *node ) /*ARGSUSED*/
|
||||
{
|
||||
node->next->prev = node->prev;
|
||||
node->prev->next = node->next;
|
||||
memFree( node );
|
||||
}
|
||||
|
||||
inline DictNode *dictSearch( Dict *dict, DictKey key )
|
||||
{
|
||||
DictNode *node = &dict->head;
|
||||
|
||||
do {
|
||||
node = node->next;
|
||||
} while( node->key != NULL && ! (*dict->leq)(dict->frame, key, node->key));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,241 @@
|
||||
// see license file for original license.
|
||||
|
||||
#ifndef tools_glutess_geom
|
||||
#define tools_glutess_geom
|
||||
|
||||
#include "mesh"
|
||||
|
||||
#define VertEq(u,v) ((u)->s == (v)->s && (u)->t == (v)->t)
|
||||
#define VertLeq(u,v) (((u)->s < (v)->s) || ((u)->s == (v)->s && (u)->t <= (v)->t))
|
||||
|
||||
#define EdgeEval(u,v,w) __gl_edgeEval(u,v,w)
|
||||
#define EdgeSign(u,v,w) __gl_edgeSign(u,v,w)
|
||||
|
||||
/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */
|
||||
|
||||
#define TransLeq(u,v) (((u)->t < (v)->t) || \
|
||||
((u)->t == (v)->t && (u)->s <= (v)->s))
|
||||
#define TransEval(u,v,w) __gl_transEval(u,v,w)
|
||||
#define TransSign(u,v,w) __gl_transSign(u,v,w)
|
||||
|
||||
|
||||
#define EdgeGoesLeft(e) VertLeq( (e)->Dst, (e)->Org )
|
||||
#define EdgeGoesRight(e) VertLeq( (e)->Org, (e)->Dst )
|
||||
|
||||
#define VertL1dist(u,v) (GLU_ABS(u->s - v->s) + GLU_ABS(u->t - v->t))
|
||||
|
||||
#define VertCCW(u,v,w) __gl_vertCCW(u,v,w)
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
/// inlined C code : ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
inline int __gl_vertLeq( GLUvertex *u, GLUvertex *v )
|
||||
{
|
||||
/* Returns GLU_TRUE if u is lexicographically <= v. */
|
||||
|
||||
return VertLeq( u, v );
|
||||
}
|
||||
|
||||
inline GLUdouble __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w )
|
||||
{
|
||||
/* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w),
|
||||
* evaluates the t-coord of the edge uw at the s-coord of the vertex v.
|
||||
* Returns v->t - (uw)(v->s), ie. the signed distance from uw to v.
|
||||
* If uw is vertical (and thus passes thru v), the result is zero.
|
||||
*
|
||||
* The calculation is extremely accurate and stable, even when v
|
||||
* is very close to u or w. In particular if we set v->t = 0 and
|
||||
* let r be the negated result (this evaluates (uw)(v->s)), then
|
||||
* r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t).
|
||||
*/
|
||||
GLUdouble gapL, gapR;
|
||||
|
||||
assert( VertLeq( u, v ) && VertLeq( v, w ));
|
||||
|
||||
gapL = v->s - u->s;
|
||||
gapR = w->s - v->s;
|
||||
|
||||
if( gapL + gapR > 0 ) {
|
||||
if( gapL < gapR ) {
|
||||
return (v->t - u->t) + (u->t - w->t) * (gapL / (gapL + gapR));
|
||||
} else {
|
||||
return (v->t - w->t) + (w->t - u->t) * (gapR / (gapL + gapR));
|
||||
}
|
||||
}
|
||||
/* vertical line */
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline GLUdouble __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w )
|
||||
{
|
||||
/* Returns a number whose sign matches EdgeEval(u,v,w) but which
|
||||
* is cheaper to evaluate. Returns > 0, == 0 , or < 0
|
||||
* as v is above, on, or below the edge uw.
|
||||
*/
|
||||
GLUdouble gapL, gapR;
|
||||
|
||||
/*
|
||||
#define VertLeq(u,v) (((u)->s < (v)->s) || \
|
||||
((u)->s == (v)->s && (u)->t <= (v)->t))
|
||||
*/
|
||||
assert( VertLeq( u, v ) && VertLeq( v, w ));
|
||||
|
||||
gapL = v->s - u->s;
|
||||
gapR = w->s - v->s;
|
||||
|
||||
if( gapL + gapR > 0 ) {
|
||||
return (v->t - w->t) * gapL + (v->t - u->t) * gapR;
|
||||
}
|
||||
/* vertical line */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Define versions of EdgeSign, EdgeEval with s and t transposed.
|
||||
*/
|
||||
|
||||
inline GLUdouble __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w )
|
||||
{
|
||||
/* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w),
|
||||
* evaluates the t-coord of the edge uw at the s-coord of the vertex v.
|
||||
* Returns v->s - (uw)(v->t), ie. the signed distance from uw to v.
|
||||
* If uw is vertical (and thus passes thru v), the result is zero.
|
||||
*
|
||||
* The calculation is extremely accurate and stable, even when v
|
||||
* is very close to u or w. In particular if we set v->s = 0 and
|
||||
* let r be the negated result (this evaluates (uw)(v->t)), then
|
||||
* r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s).
|
||||
*/
|
||||
GLUdouble gapL, gapR;
|
||||
|
||||
assert( TransLeq( u, v ) && TransLeq( v, w ));
|
||||
|
||||
gapL = v->t - u->t;
|
||||
gapR = w->t - v->t;
|
||||
|
||||
if( gapL + gapR > 0 ) {
|
||||
if( gapL < gapR ) {
|
||||
return (v->s - u->s) + (u->s - w->s) * (gapL / (gapL + gapR));
|
||||
} else {
|
||||
return (v->s - w->s) + (w->s - u->s) * (gapR / (gapL + gapR));
|
||||
}
|
||||
}
|
||||
/* vertical line */
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline GLUdouble __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w )
|
||||
{
|
||||
/* Returns a number whose sign matches TransEval(u,v,w) but which
|
||||
* is cheaper to evaluate. Returns > 0, == 0 , or < 0
|
||||
* as v is above, on, or below the edge uw.
|
||||
*/
|
||||
GLUdouble gapL, gapR;
|
||||
|
||||
assert( TransLeq( u, v ) && TransLeq( v, w ));
|
||||
|
||||
gapL = v->t - u->t;
|
||||
gapR = w->t - v->t;
|
||||
|
||||
if( gapL + gapR > 0 ) {
|
||||
return (v->s - w->s) * gapL + (v->s - u->s) * gapR;
|
||||
}
|
||||
/* vertical line */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline int __gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w )
|
||||
{
|
||||
/* For almost-degenerate situations, the results are not reliable.
|
||||
* Unless the floating-point arithmetic can be performed without
|
||||
* rounding errors, *any* implementation will give incorrect results
|
||||
* on some degenerate inputs, so the client must have some way to
|
||||
* handle this situation.
|
||||
*/
|
||||
return (u->s*(v->t - w->t) + v->s*(w->t - u->t) + w->s*(u->t - v->t)) >= 0;
|
||||
}
|
||||
|
||||
/* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b),
|
||||
* or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces
|
||||
* this in the rare case that one argument is slightly negative.
|
||||
* The implementation is extremely stable numerically.
|
||||
* In particular it guarantees that the result r satisfies
|
||||
* MIN(x,y) <= r <= MAX(x,y), and the results are very accurate
|
||||
* even when a and b differ greatly in magnitude.
|
||||
*/
|
||||
#define Interpolate(a,x,b,y) \
|
||||
(a = (a < 0) ? 0 : a, b = (b < 0) ? 0 : b, \
|
||||
((a <= b) ? ((b == 0) ? ((x+y) / 2) \
|
||||
: (x + (y-x) * (a/(a+b)))) \
|
||||
: (y + (x-y) * (b/(a+b)))))
|
||||
|
||||
//#define Swap(a,b) if (1) { GLUvertex *t = a; a = b; b = t; } else
|
||||
#define Swap(a,b) do { GLUvertex *t = a; a = b; b = t; } while(false)
|
||||
|
||||
inline void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1,
|
||||
GLUvertex *o2, GLUvertex *d2,
|
||||
GLUvertex *v )
|
||||
/* Given edges (o1,d1) and (o2,d2), compute their point of intersection.
|
||||
* The computed point is guaranteed to lie in the intersection of the
|
||||
* bounding rectangles defined by each edge.
|
||||
*/
|
||||
{
|
||||
GLUdouble z1, z2;
|
||||
|
||||
/* This is certainly not the most efficient way to find the intersection
|
||||
* of two line segments, but it is very numerically stable.
|
||||
*
|
||||
* Strategy: find the two middle vertices in the VertLeq ordering,
|
||||
* and interpolate the intersection s-value from these. Then repeat
|
||||
* using the TransLeq ordering to find the intersection t-value.
|
||||
*/
|
||||
|
||||
if( ! VertLeq( o1, d1 )) { Swap( o1, d1 ); }
|
||||
if( ! VertLeq( o2, d2 )) { Swap( o2, d2 ); }
|
||||
if( ! VertLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); }
|
||||
|
||||
if( ! VertLeq( o2, d1 )) {
|
||||
/* Technically, no intersection -- do our best */
|
||||
v->s = (o2->s + d1->s) / 2;
|
||||
} else if( VertLeq( d1, d2 )) {
|
||||
/* Interpolate between o2 and d1 */
|
||||
z1 = EdgeEval( o1, o2, d1 );
|
||||
z2 = EdgeEval( o2, d1, d2 );
|
||||
if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
|
||||
v->s = Interpolate( z1, o2->s, z2, d1->s );
|
||||
} else {
|
||||
/* Interpolate between o2 and d2 */
|
||||
z1 = EdgeSign( o1, o2, d1 );
|
||||
z2 = -EdgeSign( o1, d2, d1 );
|
||||
if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
|
||||
v->s = Interpolate( z1, o2->s, z2, d2->s );
|
||||
}
|
||||
|
||||
/* Now repeat the process for t */
|
||||
|
||||
if( ! TransLeq( o1, d1 )) { Swap( o1, d1 ); }
|
||||
if( ! TransLeq( o2, d2 )) { Swap( o2, d2 ); }
|
||||
if( ! TransLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); }
|
||||
|
||||
if( ! TransLeq( o2, d1 )) {
|
||||
/* Technically, no intersection -- do our best */
|
||||
v->t = (o2->t + d1->t) / 2;
|
||||
} else if( TransLeq( d1, d2 )) {
|
||||
/* Interpolate between o2 and d1 */
|
||||
z1 = TransEval( o1, o2, d1 );
|
||||
z2 = TransEval( o2, d1, d2 );
|
||||
if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
|
||||
v->t = Interpolate( z1, o2->t, z2, d1->t );
|
||||
} else {
|
||||
/* Interpolate between o2 and d2 */
|
||||
z1 = TransSign( o1, o2, d1 );
|
||||
z2 = -TransSign( o1, d2, d1 );
|
||||
if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
|
||||
v->t = Interpolate( z1, o2->t, z2, d2->t );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,593 @@
|
||||
// see license file for original license.
|
||||
|
||||
#ifndef tools_glutess_glutess
|
||||
#define tools_glutess_glutess
|
||||
|
||||
#include "_tess"
|
||||
|
||||
GLUAPI GLUtesselator* GLUAPIENTRY gluNewTess (void);
|
||||
GLUAPI void GLUAPIENTRY gluDeleteTess (GLUtesselator* tess);
|
||||
|
||||
GLUAPI void GLUAPIENTRY gluTessBeginContour (GLUtesselator* tess);
|
||||
GLUAPI void GLUAPIENTRY gluTessBeginPolygon (GLUtesselator* tess, GLUvoid* data);
|
||||
GLUAPI void GLUAPIENTRY gluTessCallback (GLUtesselator* tess, GLUenum which, _GLUfuncptr CallBackFunc);
|
||||
GLUAPI void GLUAPIENTRY gluTessEndContour (GLUtesselator* tess);
|
||||
GLUAPI void GLUAPIENTRY gluTessEndPolygon (GLUtesselator* tess);
|
||||
GLUAPI void GLUAPIENTRY gluTessNormal (GLUtesselator* tess, GLUdouble valueX, GLUdouble valueY, GLUdouble valueZ);
|
||||
GLUAPI void GLUAPIENTRY gluTessProperty (GLUtesselator* tess, GLUenum which, GLUdouble data);
|
||||
GLUAPI void GLUAPIENTRY gluTessVertex (GLUtesselator* tess, GLUdouble *location, GLUvoid* data);
|
||||
|
||||
#include "mesh"
|
||||
#include "normal"
|
||||
#include "sweep"
|
||||
#include "tessmono"
|
||||
#include "render"
|
||||
|
||||
#define GLU_TESS_DEFAULT_TOLERANCE 0.0
|
||||
#define GLU_TESS_MESH 100112 /* void (*)(GLUmesh *mesh) */
|
||||
|
||||
/*ARGSUSED*/ inline/*static*/ void GLUAPIENTRY static_noBegin( GLUenum /*type*/ ) {}
|
||||
/*ARGSUSED*/ inline/*static*/ void GLUAPIENTRY static_noEdgeFlag( GLUboolean /*boundaryEdge*/ ) {}
|
||||
/*ARGSUSED*/ inline/*static*/ void GLUAPIENTRY static_noVertex( void * /*data*/ ) {}
|
||||
/*ARGSUSED*/ inline/*static*/ void GLUAPIENTRY static_noEnd( void ) {}
|
||||
/*ARGSUSED*/ inline/*static*/ void GLUAPIENTRY static_noError( GLUenum /*errnum*/ ) {}
|
||||
/*ARGSUSED*/ inline/*static*/ void GLUAPIENTRY static_noCombine( GLUdouble /*coords*/[3], void* /*data*/[4],
|
||||
GLUfloat /*weight*/[4], void** /*dataOut*/ ) {}
|
||||
/*ARGSUSED*/ inline/*static*/ void GLUAPIENTRY static_noMesh( GLUmesh* /*mesh*/ ) {}
|
||||
|
||||
|
||||
inline /*ARGSUSED*/ void GLUAPIENTRY __gl_noBeginData( GLUenum /*type*/, void* /*polygonData*/ ) {}
|
||||
inline /*ARGSUSED*/ void GLUAPIENTRY __gl_noEdgeFlagData( GLUboolean /*boundaryEdge*/, void* /*polygonData*/ ) {}
|
||||
inline /*ARGSUSED*/ void GLUAPIENTRY __gl_noVertexData( void* /*data*/, void* /*polygonData*/ ) {}
|
||||
inline /*ARGSUSED*/ void GLUAPIENTRY __gl_noEndData( void* /*polygonData*/ ) {}
|
||||
inline /*ARGSUSED*/ void GLUAPIENTRY __gl_noErrorData( GLUenum /*errnum*/, void* /*polygonData*/ ) {}
|
||||
inline /*ARGSUSED*/ void GLUAPIENTRY __gl_noCombineData( GLUdouble /*coords*/[3],
|
||||
void* /*data*/[4],
|
||||
GLUfloat /*weight*/[4],
|
||||
void** /*outData*/,
|
||||
void* /*polygonData*/ ) {}
|
||||
|
||||
/* Half-edges are allocated in pairs (see mesh.c) */
|
||||
//typedef struct { GLUhalfEdge e, eSym; } EdgePair;
|
||||
|
||||
inline size_t MAX_FAST_ALLOC() {
|
||||
static const size_t s_value = (GLU_MAX(sizeof(EdgePair),GLU_MAX(sizeof(GLUvertex),sizeof(GLUface))));
|
||||
return s_value;
|
||||
}
|
||||
|
||||
inline GLUtesselator * GLUAPIENTRY
|
||||
gluNewTess( void )
|
||||
{
|
||||
GLUtesselator *tess;
|
||||
|
||||
/* Only initialize fields which can be changed by the api. Other fields
|
||||
* are initialized where they are used.
|
||||
*/
|
||||
|
||||
if (memInit( MAX_FAST_ALLOC() ) == 0) {
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
tess = (GLUtesselator *)memAlloc( sizeof( GLUtesselator ));
|
||||
if (tess == NULL) {
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
|
||||
tess->state = T_DORMANT;
|
||||
|
||||
tess->normal[0] = 0;
|
||||
tess->normal[1] = 0;
|
||||
tess->normal[2] = 0;
|
||||
|
||||
tess->relTolerance = GLU_TESS_DEFAULT_TOLERANCE;
|
||||
tess->windingRule = GLU_TESS_WINDING_ODD;
|
||||
tess->flagBoundary = GLU_FALSE;
|
||||
tess->boundaryOnly = GLU_FALSE;
|
||||
|
||||
tess->callBegin = &static_noBegin;
|
||||
tess->callEdgeFlag = &static_noEdgeFlag;
|
||||
tess->callVertex = &static_noVertex;
|
||||
tess->callEnd = &static_noEnd;
|
||||
|
||||
tess->callError = &static_noError;
|
||||
tess->callCombine = &static_noCombine;
|
||||
tess->callMesh = &static_noMesh;
|
||||
|
||||
tess->callBeginData= &__gl_noBeginData;
|
||||
tess->callEdgeFlagData= &__gl_noEdgeFlagData;
|
||||
tess->callVertexData= &__gl_noVertexData;
|
||||
tess->callEndData= &__gl_noEndData;
|
||||
tess->callErrorData= &__gl_noErrorData;
|
||||
tess->callCombineData= &__gl_noCombineData;
|
||||
|
||||
tess->polygonData= NULL;
|
||||
|
||||
return tess;
|
||||
}
|
||||
|
||||
inline/*static*/ void static_MakeDormant( GLUtesselator *tess )
|
||||
{
|
||||
/* Return the tessellator to its original dormant state. */
|
||||
|
||||
if( tess->mesh != NULL ) {
|
||||
__gl_meshDeleteMesh( tess->mesh );
|
||||
}
|
||||
tess->state = T_DORMANT;
|
||||
tess->lastEdge = NULL;
|
||||
tess->mesh = NULL;
|
||||
}
|
||||
|
||||
#define RequireState( tess, s ) if( tess->state != s ) static_GotoState(tess,s)
|
||||
|
||||
inline/*static*/ void static_GotoState( GLUtesselator *tess, enum TessState newState )
|
||||
{
|
||||
while( tess->state != newState ) {
|
||||
/* We change the current state one level at a time, to get to
|
||||
* the desired state.
|
||||
*/
|
||||
if( tess->state < newState ) {
|
||||
switch( tess->state ) {
|
||||
case T_DORMANT:
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_POLYGON );
|
||||
gluTessBeginPolygon( tess, NULL );
|
||||
break;
|
||||
case T_IN_POLYGON:
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_CONTOUR );
|
||||
gluTessBeginContour( tess );
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
} else {
|
||||
switch( tess->state ) {
|
||||
case T_IN_CONTOUR:
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_CONTOUR );
|
||||
gluTessEndContour( tess );
|
||||
break;
|
||||
case T_IN_POLYGON:
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_POLYGON );
|
||||
/* gluTessEndPolygon( tess ) is too much work! */
|
||||
static_MakeDormant( tess );
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluDeleteTess( GLUtesselator *tess )
|
||||
{
|
||||
RequireState( tess, T_DORMANT );
|
||||
memFree( tess );
|
||||
}
|
||||
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluTessProperty( GLUtesselator *tess, GLUenum which, GLUdouble value )
|
||||
{
|
||||
GLUenum windingRule;
|
||||
|
||||
switch( which ) {
|
||||
case GLU_TESS_TOLERANCE:
|
||||
if( value < 0.0 || value > 1.0 ) break;
|
||||
tess->relTolerance = value;
|
||||
return;
|
||||
|
||||
case GLU_TESS_WINDING_RULE:
|
||||
windingRule = (GLUenum) value;
|
||||
if( windingRule != value ) break; /* not an integer */
|
||||
|
||||
switch( windingRule ) {
|
||||
case GLU_TESS_WINDING_ODD:
|
||||
case GLU_TESS_WINDING_NONZERO:
|
||||
case GLU_TESS_WINDING_POSITIVE:
|
||||
case GLU_TESS_WINDING_NEGATIVE:
|
||||
case GLU_TESS_WINDING_ABS_GEQ_TWO:
|
||||
tess->windingRule = windingRule;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
case GLU_TESS_BOUNDARY_ONLY:
|
||||
tess->boundaryOnly = (value != 0);
|
||||
return;
|
||||
|
||||
default:
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM );
|
||||
return;
|
||||
}
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_VALUE );
|
||||
}
|
||||
|
||||
/* Returns tessellator property */
|
||||
inline void GLUAPIENTRY
|
||||
gluGetTessProperty( GLUtesselator *tess, GLUenum which, GLUdouble *value )
|
||||
{
|
||||
switch (which) {
|
||||
case GLU_TESS_TOLERANCE:
|
||||
/* tolerance should be in range [0..1] */
|
||||
assert(0.0 <= tess->relTolerance && tess->relTolerance <= 1.0);
|
||||
*value= tess->relTolerance;
|
||||
break;
|
||||
case GLU_TESS_WINDING_RULE:
|
||||
assert(tess->windingRule == GLU_TESS_WINDING_ODD ||
|
||||
tess->windingRule == GLU_TESS_WINDING_NONZERO ||
|
||||
tess->windingRule == GLU_TESS_WINDING_POSITIVE ||
|
||||
tess->windingRule == GLU_TESS_WINDING_NEGATIVE ||
|
||||
tess->windingRule == GLU_TESS_WINDING_ABS_GEQ_TWO);
|
||||
*value= tess->windingRule;
|
||||
break;
|
||||
case GLU_TESS_BOUNDARY_ONLY:
|
||||
assert(tess->boundaryOnly == GLU_TRUE || tess->boundaryOnly == GLU_FALSE);
|
||||
*value= tess->boundaryOnly;
|
||||
break;
|
||||
default:
|
||||
*value= 0.0;
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM );
|
||||
break;
|
||||
}
|
||||
} /* gluGetTessProperty() */
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluTessNormal( GLUtesselator *tess, GLUdouble x, GLUdouble y, GLUdouble z )
|
||||
{
|
||||
tess->normal[0] = x;
|
||||
tess->normal[1] = y;
|
||||
tess->normal[2] = z;
|
||||
}
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluTessCallback( GLUtesselator *tess, GLUenum which, _GLUfuncptr fn)
|
||||
{
|
||||
switch( which ) {
|
||||
case GLU_TESS_BEGIN:
|
||||
tess->callBegin = (fn == NULL) ? &static_noBegin : (void (GLUAPIENTRY *)(GLUenum)) fn;
|
||||
return;
|
||||
case GLU_TESS_BEGIN_DATA:
|
||||
tess->callBeginData = (fn == NULL) ?
|
||||
&__gl_noBeginData : (void (GLUAPIENTRY *)(GLUenum, void *)) fn;
|
||||
return;
|
||||
case GLU_TESS_EDGE_FLAG:
|
||||
tess->callEdgeFlag = (fn == NULL) ? &static_noEdgeFlag :
|
||||
(void (GLUAPIENTRY *)(GLUboolean)) fn;
|
||||
/* If the client wants boundary edges to be flagged,
|
||||
* we render everything as separate triangles (no strips or fans).
|
||||
*/
|
||||
tess->flagBoundary = (fn != NULL);
|
||||
return;
|
||||
case GLU_TESS_EDGE_FLAG_DATA:
|
||||
tess->callEdgeFlagData= (fn == NULL) ?
|
||||
&__gl_noEdgeFlagData : (void (GLUAPIENTRY *)(GLUboolean, void *)) fn;
|
||||
/* If the client wants boundary edges to be flagged,
|
||||
* we render everything as separate triangles (no strips or fans).
|
||||
*/
|
||||
tess->flagBoundary = (fn != NULL);
|
||||
return;
|
||||
case GLU_TESS_VERTEX:
|
||||
tess->callVertex = (fn == NULL) ? &static_noVertex :
|
||||
(void (GLUAPIENTRY *)(void *)) fn;
|
||||
return;
|
||||
case GLU_TESS_VERTEX_DATA:
|
||||
tess->callVertexData = (fn == NULL) ?
|
||||
&__gl_noVertexData : (void (GLUAPIENTRY *)(void *, void *)) fn;
|
||||
return;
|
||||
case GLU_TESS_END:
|
||||
tess->callEnd = (fn == NULL) ? &static_noEnd : (void (GLUAPIENTRY *)(void)) fn;
|
||||
return;
|
||||
case GLU_TESS_END_DATA:
|
||||
tess->callEndData = (fn == NULL) ? &__gl_noEndData :
|
||||
(void (GLUAPIENTRY *)(void *)) fn;
|
||||
return;
|
||||
case GLU_TESS_ERROR:
|
||||
tess->callError = (fn == NULL) ? &static_noError : (void (GLUAPIENTRY *)(GLUenum)) fn;
|
||||
return;
|
||||
case GLU_TESS_ERROR_DATA:
|
||||
tess->callErrorData = (fn == NULL) ?
|
||||
&__gl_noErrorData : (void (GLUAPIENTRY *)(GLUenum, void *)) fn;
|
||||
return;
|
||||
case GLU_TESS_COMBINE:
|
||||
tess->callCombine = (fn == NULL) ? &static_noCombine :
|
||||
(void (GLUAPIENTRY *)(GLUdouble [3],void *[4], GLUfloat [4], void ** )) fn;
|
||||
return;
|
||||
case GLU_TESS_COMBINE_DATA:
|
||||
tess->callCombineData = (fn == NULL) ? &__gl_noCombineData :
|
||||
(void (GLUAPIENTRY *)(GLUdouble [3],
|
||||
void *[4],
|
||||
GLUfloat [4],
|
||||
void **,
|
||||
void *)) fn;
|
||||
return;
|
||||
case GLU_TESS_MESH:
|
||||
tess->callMesh = (fn == NULL) ? &static_noMesh : (void (GLUAPIENTRY *)(GLUmesh *)) fn;
|
||||
return;
|
||||
default:
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
inline/*static*/ int static_AddVertex( GLUtesselator *tess, GLUdouble coords[3], void *data )
|
||||
{
|
||||
GLUhalfEdge *e;
|
||||
|
||||
e = tess->lastEdge;
|
||||
if( e == NULL ) {
|
||||
/* Make a self-loop (one vertex, one edge). */
|
||||
|
||||
e = __gl_meshMakeEdge( tess->mesh );
|
||||
if (e == NULL) return 0;
|
||||
if ( !__gl_meshSplice( e, e->Sym ) ) return 0;
|
||||
} else {
|
||||
/* Create a new vertex and edge which immediately follow e
|
||||
* in the ordering around the left face.
|
||||
*/
|
||||
if (__gl_meshSplitEdge( e ) == NULL) return 0;
|
||||
e = e->Lnext;
|
||||
}
|
||||
|
||||
/* The new vertex is now e->Org. */
|
||||
e->Org->data = data;
|
||||
e->Org->coords[0] = coords[0];
|
||||
e->Org->coords[1] = coords[1];
|
||||
e->Org->coords[2] = coords[2];
|
||||
|
||||
/* The winding of an edge says how the winding number changes as we
|
||||
* cross from the edge''s right face to its left face. We add the
|
||||
* vertices in such an order that a CCW contour will add +1 to
|
||||
* the winding number of the region inside the contour.
|
||||
*/
|
||||
e->winding = 1;
|
||||
e->Sym->winding = -1;
|
||||
|
||||
tess->lastEdge = e;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
inline/*static*/ void static_CacheVertex( GLUtesselator *tess, GLUdouble coords[3], void *data )
|
||||
{
|
||||
CachedVertex *v = &tess->cache[tess->cacheCount];
|
||||
|
||||
v->data = data;
|
||||
v->coords[0] = coords[0];
|
||||
v->coords[1] = coords[1];
|
||||
v->coords[2] = coords[2];
|
||||
++tess->cacheCount;
|
||||
}
|
||||
|
||||
|
||||
inline/*static*/ int static_EmptyCache( GLUtesselator *tess )
|
||||
{
|
||||
CachedVertex *v = tess->cache;
|
||||
CachedVertex *vLast;
|
||||
|
||||
tess->mesh = __gl_meshNewMesh();
|
||||
if (tess->mesh == NULL) return 0;
|
||||
|
||||
for( vLast = v + tess->cacheCount; v < vLast; ++v ) {
|
||||
if ( !static_AddVertex( tess, v->coords, v->data ) ) return 0;
|
||||
}
|
||||
tess->cacheCount = 0;
|
||||
tess->emptyCache = GLU_FALSE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluTessVertex( GLUtesselator *tess, GLUdouble coords[3], void *data )
|
||||
{
|
||||
int i, tooLarge = GLU_FALSE;
|
||||
GLUdouble x, clamped[3];
|
||||
|
||||
RequireState( tess, T_IN_CONTOUR );
|
||||
|
||||
if( tess->emptyCache ) {
|
||||
if ( !static_EmptyCache( tess ) ) {
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
|
||||
return;
|
||||
}
|
||||
tess->lastEdge = NULL;
|
||||
}
|
||||
for( i = 0; i < 3; ++i ) {
|
||||
x = coords[i];
|
||||
if( x < - GLU_TESS_MAX_COORD ) {
|
||||
x = - GLU_TESS_MAX_COORD;
|
||||
tooLarge = GLU_TRUE;
|
||||
}
|
||||
if( x > GLU_TESS_MAX_COORD ) {
|
||||
x = GLU_TESS_MAX_COORD;
|
||||
tooLarge = GLU_TRUE;
|
||||
}
|
||||
clamped[i] = x;
|
||||
}
|
||||
if( tooLarge ) {
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_TESS_COORD_TOO_LARGE );
|
||||
}
|
||||
|
||||
if( tess->mesh == NULL ) {
|
||||
if( tess->cacheCount < GLU_TESS_MAX_CACHE ) {
|
||||
static_CacheVertex( tess, clamped, data );
|
||||
return;
|
||||
}
|
||||
if ( !static_EmptyCache( tess ) ) {
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ( !static_AddVertex( tess, clamped, data ) ) {
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluTessBeginPolygon( GLUtesselator *tess, void *data )
|
||||
{
|
||||
RequireState( tess, T_DORMANT );
|
||||
|
||||
tess->state = T_IN_POLYGON;
|
||||
tess->cacheCount = 0;
|
||||
tess->emptyCache = GLU_FALSE;
|
||||
tess->mesh = NULL;
|
||||
|
||||
tess->polygonData= data;
|
||||
}
|
||||
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluTessBeginContour( GLUtesselator *tess )
|
||||
{
|
||||
RequireState( tess, T_IN_POLYGON );
|
||||
|
||||
tess->state = T_IN_CONTOUR;
|
||||
tess->lastEdge = NULL;
|
||||
if( tess->cacheCount > 0 ) {
|
||||
/* Just set a flag so we don't get confused by empty contours
|
||||
* -- these can be generated accidentally with the obsolete
|
||||
* NextContour() interface.
|
||||
*/
|
||||
tess->emptyCache = GLU_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluTessEndContour( GLUtesselator *tess )
|
||||
{
|
||||
RequireState( tess, T_IN_CONTOUR );
|
||||
tess->state = T_IN_POLYGON;
|
||||
}
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluTessEndPolygon( GLUtesselator *tess )
|
||||
{
|
||||
GLUmesh *mesh;
|
||||
|
||||
if (setjmp(tess->env) != 0) {
|
||||
/* come back here if out of memory */
|
||||
CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
|
||||
return;
|
||||
}
|
||||
|
||||
RequireState( tess, T_IN_POLYGON );
|
||||
tess->state = T_DORMANT;
|
||||
|
||||
if( tess->mesh == NULL ) {
|
||||
if( ! tess->flagBoundary && tess->callMesh == &static_noMesh ) {
|
||||
|
||||
/* Try some special code to make the easy cases go quickly
|
||||
* (eg. convex polygons). This code does NOT handle multiple contours,
|
||||
* intersections, edge flags, and of course it does not generate
|
||||
* an explicit mesh either.
|
||||
*/
|
||||
if( __gl_renderCache( tess )) {
|
||||
tess->polygonData= NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ( !static_EmptyCache( tess ) ) longjmp(tess->env,1); /* could've used a label*/
|
||||
}
|
||||
|
||||
/* Determine the polygon normal and project vertices onto the plane
|
||||
* of the polygon.
|
||||
*/
|
||||
__gl_projectPolygon( tess );
|
||||
|
||||
/* __gl_computeInterior( tess ) computes the planar arrangement specified
|
||||
* by the given contours, and further subdivides this arrangement
|
||||
* into regions. Each region is marked "inside" if it belongs
|
||||
* to the polygon, according to the rule given by tess->windingRule.
|
||||
* Each interior region is guaranteed be monotone.
|
||||
*/
|
||||
if ( !__gl_computeInterior( tess ) ) {
|
||||
longjmp(tess->env,1); /* could've used a label */
|
||||
}
|
||||
|
||||
mesh = tess->mesh;
|
||||
if( ! tess->fatalError ) {
|
||||
int rc = 1;
|
||||
|
||||
/* If the user wants only the boundary contours, we throw away all edges
|
||||
* except those which separate the interior from the exterior.
|
||||
* Otherwise we tessellate all the regions marked "inside".
|
||||
*/
|
||||
if( tess->boundaryOnly ) {
|
||||
rc = __gl_meshSetWindingNumber( mesh, 1, GLU_TRUE );
|
||||
} else {
|
||||
rc = __gl_meshTessellateInterior( mesh );
|
||||
}
|
||||
if (rc == 0) longjmp(tess->env,1); /* could've used a label */
|
||||
|
||||
__gl_meshCheckMesh( mesh );
|
||||
|
||||
if( tess->callBegin != &static_noBegin || tess->callEnd != &static_noEnd
|
||||
|| tess->callVertex != &static_noVertex || tess->callEdgeFlag != &static_noEdgeFlag
|
||||
|| tess->callBeginData != &__gl_noBeginData
|
||||
|| tess->callEndData != &__gl_noEndData
|
||||
|| tess->callVertexData != &__gl_noVertexData
|
||||
|| tess->callEdgeFlagData != &__gl_noEdgeFlagData )
|
||||
{
|
||||
if( tess->boundaryOnly ) {
|
||||
__gl_renderBoundary( tess, mesh ); /* output boundary contours */
|
||||
} else {
|
||||
__gl_renderMesh( tess, mesh ); /* output strips and fans */
|
||||
}
|
||||
}
|
||||
if( tess->callMesh != &static_noMesh ) {
|
||||
|
||||
/* Throw away the exterior faces, so that all faces are interior.
|
||||
* This way the user doesn't have to check the "inside" flag,
|
||||
* and we don't need to even reveal its existence. It also leaves
|
||||
* the freedom for an implementation to not generate the exterior
|
||||
* faces in the first place.
|
||||
*/
|
||||
__gl_meshDiscardExterior( mesh );
|
||||
(*tess->callMesh)( mesh ); /* user wants the mesh itself */
|
||||
tess->mesh = NULL;
|
||||
tess->polygonData= NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
__gl_meshDeleteMesh( mesh );
|
||||
tess->polygonData= NULL;
|
||||
tess->mesh = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************/
|
||||
|
||||
/* Obsolete calls -- for backward compatibility */
|
||||
|
||||
/*
|
||||
inline void GLUAPIENTRY
|
||||
gluBeginPolygon( GLUtesselator *tess )
|
||||
{
|
||||
gluTessBeginPolygon( tess, NULL );
|
||||
gluTessBeginContour( tess );
|
||||
}
|
||||
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluNextContour( GLUtesselator *tess, GLUenum type )
|
||||
{
|
||||
gluTessEndContour( tess );
|
||||
gluTessBeginContour( tess );
|
||||
}
|
||||
|
||||
|
||||
inline void GLUAPIENTRY
|
||||
gluEndPolygon( GLUtesselator *tess )
|
||||
{
|
||||
gluTessEndContour( tess );
|
||||
gluTessEndPolygon( tess );
|
||||
}
|
||||
*/
|
||||
|
||||
#include "undef"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* 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 including the dates of first publication and
|
||||
* either this permission notice or a reference to
|
||||
* http://oss.sgi.com/projects/FreeB/
|
||||
* 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
|
||||
* SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc.
|
||||
* shall not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization from
|
||||
* Silicon Graphics, Inc.
|
||||
*/
|
||||
/*
|
||||
** Author: Eric Veach, July 1994.
|
||||
**
|
||||
*/
|
||||
@@ -0,0 +1,45 @@
|
||||
// see license file for original license.
|
||||
|
||||
#ifndef tools_glutess_memalloc
|
||||
#define tools_glutess_memalloc
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
/// inlined C code : ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include <tools/mem>
|
||||
#include <cstdlib>
|
||||
namespace tools {
|
||||
inline void* mem_alloc(size_t a_size){
|
||||
tools::mem::increment(tools::s_malloc().c_str());
|
||||
return ::malloc(a_size);
|
||||
}
|
||||
inline void* mem_realloc(void* a_ptr,size_t a_size){
|
||||
if(a_ptr==NULL) tools::mem::increment(tools::s_malloc().c_str());
|
||||
return ::realloc(a_ptr,a_size);
|
||||
}
|
||||
inline void mem_free(void* a_ptr){
|
||||
if(a_ptr!=NULL) tools::mem::decrement(tools::s_malloc().c_str());
|
||||
::free(a_ptr);
|
||||
}
|
||||
inline int mem_init( size_t /*maxFast*/) {return 1;}
|
||||
|
||||
}
|
||||
#else
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
namespace tools {
|
||||
inline void* mem_alloc(size_t a_size) {return ::memset( ::malloc( a_size ), 0xa5, a_size);}
|
||||
inline void* mem_realloc(void* a_ptr,size_t a_size){return ::realloc(a_ptr,a_size);}
|
||||
inline void mem_free(void* a_ptr){::free(a_ptr);}
|
||||
inline int mem_init( size_t /*maxFast*/) {return 1;}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define memAlloc tools::mem_alloc
|
||||
#define memRealloc tools::mem_realloc
|
||||
#define memFree tools::mem_free
|
||||
#define memInit tools::mem_init
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,970 @@
|
||||
// see license file for original license.
|
||||
|
||||
#ifndef tools_glutess_mesh
|
||||
#define tools_glutess_mesh
|
||||
|
||||
#include "_glu"
|
||||
|
||||
typedef struct GLUmesh GLUmesh;
|
||||
|
||||
typedef struct GLUvertex GLUvertex;
|
||||
typedef struct GLUface GLUface;
|
||||
typedef struct GLUhalfEdge GLUhalfEdge;
|
||||
|
||||
typedef struct ActiveRegion ActiveRegion; /* Internal data */
|
||||
|
||||
/* The mesh structure is similar in spirit, notation, and operations
|
||||
* to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives
|
||||
* for the manipulation of general subdivisions and the computation of
|
||||
* Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985).
|
||||
* For a simplified description, see the course notes for CS348a,
|
||||
* "Mathematical Foundations of Computer Graphics", available at the
|
||||
* Stanford bookstore (and taught during the fall quarter).
|
||||
* The implementation also borrows a tiny subset of the graph-based approach
|
||||
* use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction
|
||||
* to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988).
|
||||
*
|
||||
* The fundamental data structure is the "half-edge". Two half-edges
|
||||
* go together to make an edge, but they point in opposite directions.
|
||||
* Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym),
|
||||
* its origin vertex (Org), the face on its left side (Lface), and the
|
||||
* adjacent half-edges in the CCW direction around the origin vertex
|
||||
* (Onext) and around the left face (Lnext). There is also a "next"
|
||||
* pointer for the global edge list (see below).
|
||||
*
|
||||
* The notation used for mesh navigation:
|
||||
* Sym = the mate of a half-edge (same edge, but opposite direction)
|
||||
* Onext = edge CCW around origin vertex (keep same origin)
|
||||
* Dnext = edge CCW around destination vertex (keep same dest)
|
||||
* Lnext = edge CCW around left face (dest becomes new origin)
|
||||
* Rnext = edge CCW around right face (origin becomes new dest)
|
||||
*
|
||||
* "prev" means to substitute CW for CCW in the definitions above.
|
||||
*
|
||||
* The mesh keeps global lists of all vertices, faces, and edges,
|
||||
* stored as doubly-linked circular lists with a dummy header node.
|
||||
* The mesh stores pointers to these dummy headers (vHead, fHead, eHead).
|
||||
*
|
||||
* The circular edge list is special; since half-edges always occur
|
||||
* in pairs (e and e->Sym), each half-edge stores a pointer in only
|
||||
* one direction. Starting at eHead and following the e->next pointers
|
||||
* will visit each *edge* once (ie. e or e->Sym, but not both).
|
||||
* e->Sym stores a pointer in the opposite direction, thus it is
|
||||
* always true that e->Sym->next->Sym->next == e.
|
||||
*
|
||||
* Each vertex has a pointer to next and previous vertices in the
|
||||
* circular list, and a pointer to a half-edge with this vertex as
|
||||
* the origin (NULL if this is the dummy header). There is also a
|
||||
* field "data" for client data.
|
||||
*
|
||||
* Each face has a pointer to the next and previous faces in the
|
||||
* circular list, and a pointer to a half-edge with this face as
|
||||
* the left face (NULL if this is the dummy header). There is also
|
||||
* a field "data" for client data.
|
||||
*
|
||||
* Note that what we call a "face" is really a loop; faces may consist
|
||||
* of more than one loop (ie. not simply connected), but there is no
|
||||
* record of this in the data structure. The mesh may consist of
|
||||
* several disconnected regions, so it may not be possible to visit
|
||||
* the entire mesh by starting at a half-edge and traversing the edge
|
||||
* structure.
|
||||
*
|
||||
* The mesh does NOT support isolated vertices; a vertex is deleted along
|
||||
* with its last edge. Similarly when two faces are merged, one of the
|
||||
* faces is deleted (see __gl_meshDelete below). For mesh operations,
|
||||
* all face (loop) and vertex pointers must not be NULL. However, once
|
||||
* mesh manipulation is finished, __gl_MeshZapFace can be used to delete
|
||||
* faces of the mesh, one at a time. All external faces can be "zapped"
|
||||
* before the mesh is returned to the client; then a NULL face indicates
|
||||
* a region which is not part of the output polygon.
|
||||
*/
|
||||
|
||||
struct GLUvertex {
|
||||
GLUvertex *next; /* next vertex (never NULL) */
|
||||
GLUvertex *prev; /* previous vertex (never NULL) */
|
||||
GLUhalfEdge *anEdge; /* a half-edge with this origin */
|
||||
void *data; /* client's data */
|
||||
|
||||
/* Internal data (keep hidden) */
|
||||
GLUdouble coords[3]; /* vertex location in 3D */
|
||||
GLUdouble s, t; /* projection onto the sweep plane */
|
||||
long pqHandle; /* to allow deletion from priority queue */
|
||||
};
|
||||
|
||||
struct GLUface {
|
||||
GLUface *next; /* next face (never NULL) */
|
||||
GLUface *prev; /* previous face (never NULL) */
|
||||
GLUhalfEdge *anEdge; /* a half edge with this left face */
|
||||
void *data; /* room for client's data */
|
||||
|
||||
/* Internal data (keep hidden) */
|
||||
GLUface *trail; /* "stack" for conversion to strips */
|
||||
GLUboolean marked; /* flag for conversion to strips */
|
||||
GLUboolean inside; /* this face is in the polygon interior */
|
||||
};
|
||||
|
||||
struct GLUhalfEdge {
|
||||
GLUhalfEdge *next; /* doubly-linked list (prev==Sym->next) */
|
||||
GLUhalfEdge *Sym; /* same edge, opposite direction */
|
||||
GLUhalfEdge *Onext; /* next edge CCW around origin */
|
||||
GLUhalfEdge *Lnext; /* next edge CCW around left face */
|
||||
GLUvertex *Org; /* origin vertex (Overtex too long) */
|
||||
GLUface *Lface; /* left face */
|
||||
|
||||
/* Internal data (keep hidden) */
|
||||
ActiveRegion *activeRegion; /* a region with this upper edge (sweep.c) */
|
||||
int winding; /* change in winding number when crossing
|
||||
from the right face to the left face */
|
||||
};
|
||||
|
||||
#define Rface Sym->Lface
|
||||
#define Dst Sym->Org
|
||||
|
||||
#define Oprev Sym->Lnext
|
||||
#define Lprev Onext->Sym
|
||||
#define Dprev Lnext->Sym
|
||||
#define Rprev Sym->Onext
|
||||
#define Dnext Rprev->Sym /* 3 pointers */
|
||||
#define Rnext Oprev->Sym /* 3 pointers */
|
||||
|
||||
|
||||
struct GLUmesh {
|
||||
GLUvertex vHead; /* dummy header for vertex list */
|
||||
GLUface fHead; /* dummy header for face list */
|
||||
GLUhalfEdge eHead; /* dummy header for edge list */
|
||||
GLUhalfEdge eHeadSym; /* and its symmetric counterpart */
|
||||
};
|
||||
|
||||
/* The mesh operations below have three motivations: completeness,
|
||||
* convenience, and efficiency. The basic mesh operations are MakeEdge,
|
||||
* Splice, and Delete. All the other edge operations can be implemented
|
||||
* in terms of these. The other operations are provided for convenience
|
||||
* and/or efficiency.
|
||||
*
|
||||
* When a face is split or a vertex is added, they are inserted into the
|
||||
* global list *before* the existing vertex or face (ie. e->Org or e->Lface).
|
||||
* This makes it easier to process all vertices or faces in the global lists
|
||||
* without worrying about processing the same data twice. As a convenience,
|
||||
* when a face is split, the "inside" flag is copied from the old face.
|
||||
* Other internal data (v->data, v->activeRegion, f->data, f->marked,
|
||||
* f->trail, e->winding) is set to zero.
|
||||
*
|
||||
* ********************** Basic Edge Operations **************************
|
||||
*
|
||||
* __gl_meshMakeEdge( mesh ) creates one edge, two vertices, and a loop.
|
||||
* The loop (face) consists of the two new half-edges.
|
||||
*
|
||||
* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
|
||||
* mesh connectivity and topology. It changes the mesh so that
|
||||
* eOrg->Onext <- OLD( eDst->Onext )
|
||||
* eDst->Onext <- OLD( eOrg->Onext )
|
||||
* where OLD(...) means the value before the meshSplice operation.
|
||||
*
|
||||
* This can have two effects on the vertex structure:
|
||||
* - if eOrg->Org != eDst->Org, the two vertices are merged together
|
||||
* - if eOrg->Org == eDst->Org, the origin is split into two vertices
|
||||
* In both cases, eDst->Org is changed and eOrg->Org is untouched.
|
||||
*
|
||||
* Similarly (and independently) for the face structure,
|
||||
* - if eOrg->Lface == eDst->Lface, one loop is split into two
|
||||
* - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
|
||||
* In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
|
||||
*
|
||||
* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases:
|
||||
* if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
|
||||
* eDel->Lface is deleted. Otherwise, we are splitting one loop into two;
|
||||
* the newly created loop will contain eDel->Dst. If the deletion of eDel
|
||||
* would create isolated vertices, those are deleted as well.
|
||||
*
|
||||
* ********************** Other Edge Operations **************************
|
||||
*
|
||||
* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
|
||||
* eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
|
||||
* eOrg and eNew will have the same left face.
|
||||
*
|
||||
* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
|
||||
* such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org.
|
||||
* eOrg and eNew will have the same left face.
|
||||
*
|
||||
* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
|
||||
* to eDst->Org, and returns the corresponding half-edge eNew.
|
||||
* If eOrg->Lface == eDst->Lface, this splits one loop into two,
|
||||
* and the newly created loop is eNew->Lface. Otherwise, two disjoint
|
||||
* loops are merged into one, and the loop eDst->Lface is destroyed.
|
||||
*
|
||||
* ************************ Other Operations *****************************
|
||||
*
|
||||
* __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
|
||||
* and no loops (what we usually call a "face").
|
||||
*
|
||||
* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
|
||||
* both meshes, and returns the new mesh (the old meshes are destroyed).
|
||||
*
|
||||
* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
|
||||
*
|
||||
* __gl_meshZapFace( fZap ) destroys a face and removes it from the
|
||||
* global face list. All edges of fZap will have a NULL pointer as their
|
||||
* left face. Any edges which also have a NULL pointer as their right face
|
||||
* are deleted entirely (along with any isolated vertices this produces).
|
||||
* An entire mesh can be deleted by zapping its faces, one at a time,
|
||||
* in any order. Zapped faces cannot be used in further mesh operations!
|
||||
*
|
||||
* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
/// inlined C code : ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
//#include "gluos"
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
#include "memalloc"
|
||||
|
||||
inline/*static*/ GLUvertex *static_allocVertex()
|
||||
{
|
||||
return (GLUvertex *)memAlloc( sizeof( GLUvertex ));
|
||||
}
|
||||
|
||||
inline/*static*/ GLUface *static_allocFace()
|
||||
{
|
||||
return (GLUface *)memAlloc( sizeof( GLUface ));
|
||||
}
|
||||
|
||||
/************************ Utility Routines ************************/
|
||||
|
||||
/* Allocate and free half-edges in pairs for efficiency.
|
||||
* The *only* place that should use this fact is allocation/free.
|
||||
*/
|
||||
typedef struct { GLUhalfEdge e, eSym; } EdgePair;
|
||||
|
||||
/* MakeEdge creates a new pair of half-edges which form their own loop.
|
||||
* No vertex or face structures are allocated, but these must be assigned
|
||||
* before the current edge operation is completed.
|
||||
*/
|
||||
inline/*static*/ GLUhalfEdge *static_MakeEdge( GLUhalfEdge *eNext )
|
||||
{
|
||||
GLUhalfEdge *e;
|
||||
GLUhalfEdge *eSym;
|
||||
GLUhalfEdge *ePrev;
|
||||
EdgePair *pair = (EdgePair *)memAlloc( sizeof( EdgePair ));
|
||||
if (pair == NULL) return NULL;
|
||||
|
||||
e = &pair->e;
|
||||
eSym = &pair->eSym;
|
||||
|
||||
/* Make sure eNext points to the first edge of the edge pair */
|
||||
if( eNext->Sym < eNext ) { eNext = eNext->Sym; }
|
||||
|
||||
/* Insert in circular doubly-linked list before eNext.
|
||||
* Note that the prev pointer is stored in Sym->next.
|
||||
*/
|
||||
ePrev = eNext->Sym->next;
|
||||
eSym->next = ePrev;
|
||||
ePrev->Sym->next = e;
|
||||
e->next = eNext;
|
||||
eNext->Sym->next = eSym;
|
||||
|
||||
e->Sym = eSym;
|
||||
e->Onext = e;
|
||||
e->Lnext = eSym;
|
||||
e->Org = NULL;
|
||||
e->Lface = NULL;
|
||||
e->winding = 0;
|
||||
e->activeRegion = NULL;
|
||||
|
||||
eSym->Sym = e;
|
||||
eSym->Onext = eSym;
|
||||
eSym->Lnext = e;
|
||||
eSym->Org = NULL;
|
||||
eSym->Lface = NULL;
|
||||
eSym->winding = 0;
|
||||
eSym->activeRegion = NULL;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the
|
||||
* CS348a notes (see mesh.h). Basically it modifies the mesh so that
|
||||
* a->Onext and b->Onext are exchanged. This can have various effects
|
||||
* depending on whether a and b belong to different face or vertex rings.
|
||||
* For more explanation see __gl_meshSplice() below.
|
||||
*/
|
||||
inline/*static*/ void static_Splice( GLUhalfEdge *a, GLUhalfEdge *b )
|
||||
{
|
||||
GLUhalfEdge *aOnext = a->Onext;
|
||||
GLUhalfEdge *bOnext = b->Onext;
|
||||
|
||||
aOnext->Sym->Lnext = b;
|
||||
bOnext->Sym->Lnext = a;
|
||||
a->Onext = bOnext;
|
||||
b->Onext = aOnext;
|
||||
}
|
||||
|
||||
/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the
|
||||
* origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives
|
||||
* a place to insert the new vertex in the global vertex list. We insert
|
||||
* the new vertex *before* vNext so that algorithms which walk the vertex
|
||||
* list will not see the newly created vertices.
|
||||
*/
|
||||
inline/*static*/ void static_MakeVertex( GLUvertex *newVertex,
|
||||
GLUhalfEdge *eOrig, GLUvertex *vNext )
|
||||
{
|
||||
GLUhalfEdge *e;
|
||||
GLUvertex *vPrev;
|
||||
GLUvertex *vNew = newVertex;
|
||||
|
||||
assert(vNew != NULL);
|
||||
|
||||
/* insert in circular doubly-linked list before vNext */
|
||||
vPrev = vNext->prev;
|
||||
vNew->prev = vPrev;
|
||||
vPrev->next = vNew;
|
||||
vNew->next = vNext;
|
||||
vNext->prev = vNew;
|
||||
|
||||
vNew->anEdge = eOrig;
|
||||
vNew->data = NULL;
|
||||
/* leave coords, s, t undefined */
|
||||
|
||||
/* fix other edges on this vertex loop */
|
||||
e = eOrig;
|
||||
do {
|
||||
e->Org = vNew;
|
||||
e = e->Onext;
|
||||
} while( e != eOrig );
|
||||
}
|
||||
|
||||
/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left
|
||||
* face of all edges in the face loop to which eOrig belongs. "fNext" gives
|
||||
* a place to insert the new face in the global face list. We insert
|
||||
* the new face *before* fNext so that algorithms which walk the face
|
||||
* list will not see the newly created faces.
|
||||
*/
|
||||
inline/*static*/ void static_MakeFace( GLUface *newFace, GLUhalfEdge *eOrig, GLUface *fNext )
|
||||
{
|
||||
GLUhalfEdge *e;
|
||||
GLUface *fPrev;
|
||||
GLUface *fNew = newFace;
|
||||
|
||||
assert(fNew != NULL);
|
||||
|
||||
/* insert in circular doubly-linked list before fNext */
|
||||
fPrev = fNext->prev;
|
||||
fNew->prev = fPrev;
|
||||
fPrev->next = fNew;
|
||||
fNew->next = fNext;
|
||||
fNext->prev = fNew;
|
||||
|
||||
fNew->anEdge = eOrig;
|
||||
fNew->data = NULL;
|
||||
fNew->trail = NULL;
|
||||
fNew->marked = GLU_FALSE;
|
||||
|
||||
/* The new face is marked "inside" if the old one was. This is a
|
||||
* convenience for the common case where a face has been split in two.
|
||||
*/
|
||||
fNew->inside = fNext->inside;
|
||||
|
||||
/* fix other edges on this face loop */
|
||||
e = eOrig;
|
||||
do {
|
||||
e->Lface = fNew;
|
||||
e = e->Lnext;
|
||||
} while( e != eOrig );
|
||||
}
|
||||
|
||||
/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym),
|
||||
* and removes from the global edge list.
|
||||
*/
|
||||
inline/*static*/ void static_KillEdge( GLUhalfEdge *eDel )
|
||||
{
|
||||
GLUhalfEdge *ePrev, *eNext;
|
||||
|
||||
/* Half-edges are allocated in pairs, see EdgePair above */
|
||||
if( eDel->Sym < eDel ) { eDel = eDel->Sym; }
|
||||
|
||||
/* delete from circular doubly-linked list */
|
||||
eNext = eDel->next;
|
||||
ePrev = eDel->Sym->next;
|
||||
eNext->Sym->next = ePrev;
|
||||
ePrev->Sym->next = eNext;
|
||||
|
||||
memFree( eDel );
|
||||
}
|
||||
|
||||
|
||||
/* KillVertex( vDel ) destroys a vertex and removes it from the global
|
||||
* vertex list. It updates the vertex loop to point to a given new vertex.
|
||||
*/
|
||||
inline/*static*/ void static_KillVertex( GLUvertex *vDel, GLUvertex *newOrg )
|
||||
{
|
||||
GLUhalfEdge *e, *eStart = vDel->anEdge;
|
||||
GLUvertex *vPrev, *vNext;
|
||||
|
||||
/* change the origin of all affected edges */
|
||||
e = eStart;
|
||||
do {
|
||||
e->Org = newOrg;
|
||||
e = e->Onext;
|
||||
} while( e != eStart );
|
||||
|
||||
/* delete from circular doubly-linked list */
|
||||
vPrev = vDel->prev;
|
||||
vNext = vDel->next;
|
||||
vNext->prev = vPrev;
|
||||
vPrev->next = vNext;
|
||||
|
||||
memFree( vDel );
|
||||
}
|
||||
|
||||
/* KillFace( fDel ) destroys a face and removes it from the global face
|
||||
* list. It updates the face loop to point to a given new face.
|
||||
*/
|
||||
inline/*static*/ void static_KillFace( GLUface *fDel, GLUface *newLface )
|
||||
{
|
||||
GLUhalfEdge *e, *eStart = fDel->anEdge;
|
||||
GLUface *fPrev, *fNext;
|
||||
|
||||
/* change the left face of all affected edges */
|
||||
e = eStart;
|
||||
do {
|
||||
e->Lface = newLface;
|
||||
e = e->Lnext;
|
||||
} while( e != eStart );
|
||||
|
||||
/* delete from circular doubly-linked list */
|
||||
fPrev = fDel->prev;
|
||||
fNext = fDel->next;
|
||||
fNext->prev = fPrev;
|
||||
fPrev->next = fNext;
|
||||
|
||||
memFree( fDel );
|
||||
}
|
||||
|
||||
|
||||
/****************** Basic Edge Operations **********************/
|
||||
|
||||
/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face).
|
||||
* The loop consists of the two new half-edges.
|
||||
*/
|
||||
inline GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh )
|
||||
{
|
||||
GLUvertex *newVertex1= static_allocVertex();
|
||||
GLUvertex *newVertex2= static_allocVertex();
|
||||
GLUface *newFace= static_allocFace();
|
||||
GLUhalfEdge *e;
|
||||
|
||||
/* if any one is null then all get freed */
|
||||
if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) {
|
||||
if (newVertex1 != NULL) memFree(newVertex1);
|
||||
if (newVertex2 != NULL) memFree(newVertex2);
|
||||
if (newFace != NULL) memFree(newFace);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
e = static_MakeEdge( &mesh->eHead );
|
||||
if (e == NULL) {
|
||||
memFree(newVertex1);
|
||||
memFree(newVertex2);
|
||||
memFree(newFace);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static_MakeVertex( newVertex1, e, &mesh->vHead );
|
||||
static_MakeVertex( newVertex2, e->Sym, &mesh->vHead );
|
||||
static_MakeFace( newFace, e, &mesh->fHead );
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
|
||||
* mesh connectivity and topology. It changes the mesh so that
|
||||
* eOrg->Onext <- OLD( eDst->Onext )
|
||||
* eDst->Onext <- OLD( eOrg->Onext )
|
||||
* where OLD(...) means the value before the meshSplice operation.
|
||||
*
|
||||
* This can have two effects on the vertex structure:
|
||||
* - if eOrg->Org != eDst->Org, the two vertices are merged together
|
||||
* - if eOrg->Org == eDst->Org, the origin is split into two vertices
|
||||
* In both cases, eDst->Org is changed and eOrg->Org is untouched.
|
||||
*
|
||||
* Similarly (and independently) for the face structure,
|
||||
* - if eOrg->Lface == eDst->Lface, one loop is split into two
|
||||
* - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
|
||||
* In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
|
||||
*
|
||||
* Some special cases:
|
||||
* If eDst == eOrg, the operation has no effect.
|
||||
* If eDst == eOrg->Lnext, the new face will have a single edge.
|
||||
* If eDst == eOrg->Lprev, the old face will have a single edge.
|
||||
* If eDst == eOrg->Onext, the new vertex will have a single edge.
|
||||
* If eDst == eOrg->Oprev, the old vertex will have a single edge.
|
||||
*/
|
||||
inline int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
|
||||
{
|
||||
int joiningLoops = GLU_FALSE;
|
||||
int joiningVertices = GLU_FALSE;
|
||||
|
||||
if( eOrg == eDst ) return 1;
|
||||
|
||||
if( eDst->Org != eOrg->Org ) {
|
||||
/* We are merging two disjoint vertices -- destroy eDst->Org */
|
||||
joiningVertices = GLU_TRUE;
|
||||
static_KillVertex( eDst->Org, eOrg->Org );
|
||||
}
|
||||
if( eDst->Lface != eOrg->Lface ) {
|
||||
/* We are connecting two disjoint loops -- destroy eDst->Lface */
|
||||
joiningLoops = GLU_TRUE;
|
||||
static_KillFace( eDst->Lface, eOrg->Lface );
|
||||
}
|
||||
|
||||
/* Change the edge structure */
|
||||
static_Splice( eDst, eOrg );
|
||||
|
||||
if( ! joiningVertices ) {
|
||||
GLUvertex *newVertex= static_allocVertex();
|
||||
if (newVertex == NULL) return 0;
|
||||
|
||||
/* We split one vertex into two -- the new vertex is eDst->Org.
|
||||
* Make sure the old vertex points to a valid half-edge.
|
||||
*/
|
||||
static_MakeVertex( newVertex, eDst, eOrg->Org );
|
||||
eOrg->Org->anEdge = eOrg;
|
||||
}
|
||||
if( ! joiningLoops ) {
|
||||
GLUface *newFace= static_allocFace();
|
||||
if (newFace == NULL) return 0;
|
||||
|
||||
/* We split one loop into two -- the new loop is eDst->Lface.
|
||||
* Make sure the old face points to a valid half-edge.
|
||||
*/
|
||||
static_MakeFace( newFace, eDst, eOrg->Lface );
|
||||
eOrg->Lface->anEdge = eOrg;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases:
|
||||
* if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
|
||||
* eDel->Lface is deleted. Otherwise, we are splitting one loop into two;
|
||||
* the newly created loop will contain eDel->Dst. If the deletion of eDel
|
||||
* would create isolated vertices, those are deleted as well.
|
||||
*
|
||||
* This function could be implemented as two calls to __gl_meshSplice
|
||||
* plus a few calls to memFree, but this would allocate and delete
|
||||
* unnecessary vertices and faces.
|
||||
*/
|
||||
inline int __gl_meshDelete( GLUhalfEdge *eDel )
|
||||
{
|
||||
GLUhalfEdge *eDelSym = eDel->Sym;
|
||||
int joiningLoops = GLU_FALSE;
|
||||
|
||||
/* First step: disconnect the origin vertex eDel->Org. We make all
|
||||
* changes to get a consistent mesh in this "intermediate" state.
|
||||
*/
|
||||
if( eDel->Lface != eDel->Rface ) {
|
||||
/* We are joining two loops into one -- remove the left face */
|
||||
joiningLoops = GLU_TRUE;
|
||||
static_KillFace( eDel->Lface, eDel->Rface );
|
||||
}
|
||||
|
||||
if( eDel->Onext == eDel ) {
|
||||
static_KillVertex( eDel->Org, NULL );
|
||||
} else {
|
||||
/* Make sure that eDel->Org and eDel->Rface point to valid half-edges */
|
||||
eDel->Rface->anEdge = eDel->Oprev;
|
||||
eDel->Org->anEdge = eDel->Onext;
|
||||
|
||||
static_Splice( eDel, eDel->Oprev );
|
||||
if( ! joiningLoops ) {
|
||||
GLUface *newFace= static_allocFace();
|
||||
if (newFace == NULL) return 0;
|
||||
|
||||
/* We are splitting one loop into two -- create a new loop for eDel. */
|
||||
static_MakeFace( newFace, eDel, eDel->Lface );
|
||||
}
|
||||
}
|
||||
|
||||
/* Claim: the mesh is now in a consistent state, except that eDel->Org
|
||||
* may have been deleted. Now we disconnect eDel->Dst.
|
||||
*/
|
||||
if( eDelSym->Onext == eDelSym ) {
|
||||
static_KillVertex( eDelSym->Org, NULL );
|
||||
static_KillFace( eDelSym->Lface, NULL );
|
||||
} else {
|
||||
/* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */
|
||||
eDel->Lface->anEdge = eDelSym->Oprev;
|
||||
eDelSym->Org->anEdge = eDelSym->Onext;
|
||||
static_Splice( eDelSym, eDelSym->Oprev );
|
||||
}
|
||||
|
||||
/* Any isolated vertices or faces have already been freed. */
|
||||
static_KillEdge( eDel );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/******************** Other Edge Operations **********************/
|
||||
|
||||
/* All these routines can be implemented with the basic edge
|
||||
* operations above. They are provided for convenience and efficiency.
|
||||
*/
|
||||
|
||||
|
||||
/* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
|
||||
* eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
|
||||
* eOrg and eNew will have the same left face.
|
||||
*/
|
||||
inline GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg )
|
||||
{
|
||||
GLUhalfEdge *eNewSym;
|
||||
GLUhalfEdge *eNew = static_MakeEdge( eOrg );
|
||||
if (eNew == NULL) return NULL;
|
||||
|
||||
eNewSym = eNew->Sym;
|
||||
|
||||
/* Connect the new edge appropriately */
|
||||
static_Splice( eNew, eOrg->Lnext );
|
||||
|
||||
/* Set the vertex and face information */
|
||||
eNew->Org = eOrg->Dst;
|
||||
{
|
||||
GLUvertex *newVertex= static_allocVertex();
|
||||
if (newVertex == NULL) return NULL;
|
||||
|
||||
static_MakeVertex( newVertex, eNewSym, eNew->Org );
|
||||
}
|
||||
eNew->Lface = eNewSym->Lface = eOrg->Lface;
|
||||
|
||||
return eNew;
|
||||
}
|
||||
|
||||
|
||||
/* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
|
||||
* such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org.
|
||||
* eOrg and eNew will have the same left face.
|
||||
*/
|
||||
inline GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg )
|
||||
{
|
||||
GLUhalfEdge *eNew;
|
||||
GLUhalfEdge *tempHalfEdge= __gl_meshAddEdgeVertex( eOrg );
|
||||
if (tempHalfEdge == NULL) return NULL;
|
||||
|
||||
eNew = tempHalfEdge->Sym;
|
||||
|
||||
/* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */
|
||||
static_Splice( eOrg->Sym, eOrg->Sym->Oprev );
|
||||
static_Splice( eOrg->Sym, eNew );
|
||||
|
||||
/* Set the vertex and face information */
|
||||
eOrg->Dst = eNew->Org;
|
||||
eNew->Dst->anEdge = eNew->Sym; /* may have pointed to eOrg->Sym */
|
||||
eNew->Rface = eOrg->Rface;
|
||||
eNew->winding = eOrg->winding; /* copy old winding information */
|
||||
eNew->Sym->winding = eOrg->Sym->winding;
|
||||
|
||||
return eNew;
|
||||
}
|
||||
|
||||
|
||||
/* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
|
||||
* to eDst->Org, and returns the corresponding half-edge eNew.
|
||||
* If eOrg->Lface == eDst->Lface, this splits one loop into two,
|
||||
* and the newly created loop is eNew->Lface. Otherwise, two disjoint
|
||||
* loops are merged into one, and the loop eDst->Lface is destroyed.
|
||||
*
|
||||
* If (eOrg == eDst), the new face will have only two edges.
|
||||
* If (eOrg->Lnext == eDst), the old face is reduced to a single edge.
|
||||
* If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges.
|
||||
*/
|
||||
inline GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
|
||||
{
|
||||
GLUhalfEdge *eNewSym;
|
||||
int joiningLoops = GLU_FALSE;
|
||||
GLUhalfEdge *eNew = static_MakeEdge( eOrg );
|
||||
if (eNew == NULL) return NULL;
|
||||
|
||||
eNewSym = eNew->Sym;
|
||||
|
||||
if( eDst->Lface != eOrg->Lface ) {
|
||||
/* We are connecting two disjoint loops -- destroy eDst->Lface */
|
||||
joiningLoops = GLU_TRUE;
|
||||
static_KillFace( eDst->Lface, eOrg->Lface );
|
||||
}
|
||||
|
||||
/* Connect the new edge appropriately */
|
||||
static_Splice( eNew, eOrg->Lnext );
|
||||
static_Splice( eNewSym, eDst );
|
||||
|
||||
/* Set the vertex and face information */
|
||||
eNew->Org = eOrg->Dst;
|
||||
eNewSym->Org = eDst->Org;
|
||||
eNew->Lface = eNewSym->Lface = eOrg->Lface;
|
||||
|
||||
/* Make sure the old face points to a valid half-edge */
|
||||
eOrg->Lface->anEdge = eNewSym;
|
||||
|
||||
if( ! joiningLoops ) {
|
||||
GLUface *newFace= static_allocFace();
|
||||
if (newFace == NULL) return NULL;
|
||||
|
||||
/* We split one loop into two -- the new loop is eNew->Lface */
|
||||
static_MakeFace( newFace, eNew, eOrg->Lface );
|
||||
}
|
||||
return eNew;
|
||||
}
|
||||
|
||||
|
||||
/******************** Other Operations **********************/
|
||||
|
||||
/* __gl_meshZapFace( fZap ) destroys a face and removes it from the
|
||||
* global face list. All edges of fZap will have a NULL pointer as their
|
||||
* left face. Any edges which also have a NULL pointer as their right face
|
||||
* are deleted entirely (along with any isolated vertices this produces).
|
||||
* An entire mesh can be deleted by zapping its faces, one at a time,
|
||||
* in any order. Zapped faces cannot be used in further mesh operations!
|
||||
*/
|
||||
inline void __gl_meshZapFace( GLUface *fZap )
|
||||
{
|
||||
GLUhalfEdge *eStart = fZap->anEdge;
|
||||
GLUhalfEdge *e, *eNext, *eSym;
|
||||
GLUface *fPrev, *fNext;
|
||||
|
||||
/* walk around face, deleting edges whose right face is also NULL */
|
||||
eNext = eStart->Lnext;
|
||||
do {
|
||||
e = eNext;
|
||||
eNext = e->Lnext;
|
||||
|
||||
e->Lface = NULL;
|
||||
if( e->Rface == NULL ) {
|
||||
/* delete the edge -- see __gl_MeshDelete above */
|
||||
|
||||
if( e->Onext == e ) {
|
||||
static_KillVertex( e->Org, NULL );
|
||||
} else {
|
||||
/* Make sure that e->Org points to a valid half-edge */
|
||||
e->Org->anEdge = e->Onext;
|
||||
static_Splice( e, e->Oprev );
|
||||
}
|
||||
eSym = e->Sym;
|
||||
if( eSym->Onext == eSym ) {
|
||||
static_KillVertex( eSym->Org, NULL );
|
||||
} else {
|
||||
/* Make sure that eSym->Org points to a valid half-edge */
|
||||
eSym->Org->anEdge = eSym->Onext;
|
||||
static_Splice( eSym, eSym->Oprev );
|
||||
}
|
||||
static_KillEdge( e );
|
||||
}
|
||||
} while( e != eStart );
|
||||
|
||||
/* delete from circular doubly-linked list */
|
||||
fPrev = fZap->prev;
|
||||
fNext = fZap->next;
|
||||
fNext->prev = fPrev;
|
||||
fPrev->next = fNext;
|
||||
|
||||
memFree( fZap );
|
||||
}
|
||||
|
||||
|
||||
/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
|
||||
* and no loops (what we usually call a "face").
|
||||
*/
|
||||
inline GLUmesh *__gl_meshNewMesh( void )
|
||||
{
|
||||
GLUvertex *v;
|
||||
GLUface *f;
|
||||
GLUhalfEdge *e;
|
||||
GLUhalfEdge *eSym;
|
||||
GLUmesh *mesh = (GLUmesh *)memAlloc( sizeof( GLUmesh ));
|
||||
if (mesh == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
v = &mesh->vHead;
|
||||
f = &mesh->fHead;
|
||||
e = &mesh->eHead;
|
||||
eSym = &mesh->eHeadSym;
|
||||
|
||||
v->next = v->prev = v;
|
||||
v->anEdge = NULL;
|
||||
v->data = NULL;
|
||||
|
||||
f->next = f->prev = f;
|
||||
f->anEdge = NULL;
|
||||
f->data = NULL;
|
||||
f->trail = NULL;
|
||||
f->marked = GLU_FALSE;
|
||||
f->inside = GLU_FALSE;
|
||||
|
||||
e->next = e;
|
||||
e->Sym = eSym;
|
||||
e->Onext = NULL;
|
||||
e->Lnext = NULL;
|
||||
e->Org = NULL;
|
||||
e->Lface = NULL;
|
||||
e->winding = 0;
|
||||
e->activeRegion = NULL;
|
||||
|
||||
eSym->next = eSym;
|
||||
eSym->Sym = e;
|
||||
eSym->Onext = NULL;
|
||||
eSym->Lnext = NULL;
|
||||
eSym->Org = NULL;
|
||||
eSym->Lface = NULL;
|
||||
eSym->winding = 0;
|
||||
eSym->activeRegion = NULL;
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
/* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
|
||||
* both meshes, and returns the new mesh (the old meshes are destroyed).
|
||||
*/
|
||||
inline GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 )
|
||||
{
|
||||
GLUface *f1 = &mesh1->fHead;
|
||||
GLUvertex *v1 = &mesh1->vHead;
|
||||
GLUhalfEdge *e1 = &mesh1->eHead;
|
||||
GLUface *f2 = &mesh2->fHead;
|
||||
GLUvertex *v2 = &mesh2->vHead;
|
||||
GLUhalfEdge *e2 = &mesh2->eHead;
|
||||
|
||||
/* Add the faces, vertices, and edges of mesh2 to those of mesh1 */
|
||||
if( f2->next != f2 ) {
|
||||
f1->prev->next = f2->next;
|
||||
f2->next->prev = f1->prev;
|
||||
f2->prev->next = f1;
|
||||
f1->prev = f2->prev;
|
||||
}
|
||||
|
||||
if( v2->next != v2 ) {
|
||||
v1->prev->next = v2->next;
|
||||
v2->next->prev = v1->prev;
|
||||
v2->prev->next = v1;
|
||||
v1->prev = v2->prev;
|
||||
}
|
||||
|
||||
if( e2->next != e2 ) {
|
||||
e1->Sym->next->Sym->next = e2->next;
|
||||
e2->next->Sym->next = e1->Sym->next;
|
||||
e2->Sym->next->Sym->next = e1;
|
||||
e1->Sym->next = e2->Sym->next;
|
||||
}
|
||||
|
||||
memFree( mesh2 );
|
||||
return mesh1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DELETE_BY_ZAPPING
|
||||
|
||||
/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
|
||||
*/
|
||||
inline void __gl_meshDeleteMesh( GLUmesh *mesh )
|
||||
{
|
||||
GLUface *fHead = &mesh->fHead;
|
||||
|
||||
while( fHead->next != fHead ) {
|
||||
__gl_meshZapFace( fHead->next );
|
||||
}
|
||||
assert( mesh->vHead.next == &mesh->vHead );
|
||||
|
||||
memFree( mesh );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
|
||||
*/
|
||||
inline void __gl_meshDeleteMesh( GLUmesh *mesh )
|
||||
{
|
||||
GLUface *f, *fNext;
|
||||
GLUvertex *v, *vNext;
|
||||
GLUhalfEdge *e, *eNext;
|
||||
|
||||
for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) {
|
||||
fNext = f->next;
|
||||
memFree( f );
|
||||
}
|
||||
|
||||
for( v = mesh->vHead.next; v != &mesh->vHead; v = vNext ) {
|
||||
vNext = v->next;
|
||||
memFree( v );
|
||||
}
|
||||
|
||||
for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) {
|
||||
/* One call frees both e and e->Sym (see EdgePair above) */
|
||||
eNext = e->next;
|
||||
memFree( e );
|
||||
}
|
||||
|
||||
memFree( mesh );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline void __gl_meshCheckMesh( GLUmesh *mesh )
|
||||
{
|
||||
GLUface *fHead = &mesh->fHead;
|
||||
GLUvertex *vHead = &mesh->vHead;
|
||||
GLUhalfEdge *eHead = &mesh->eHead;
|
||||
GLUface *f, *fPrev;
|
||||
GLUvertex *v, *vPrev;
|
||||
GLUhalfEdge *e, *ePrev;
|
||||
|
||||
fPrev = fHead;
|
||||
for( fPrev = fHead ; (f = fPrev->next) != fHead; fPrev = f) {
|
||||
assert( f->prev == fPrev );
|
||||
e = f->anEdge;
|
||||
do {
|
||||
assert( e->Sym != e );
|
||||
assert( e->Sym->Sym == e );
|
||||
assert( e->Lnext->Onext->Sym == e );
|
||||
assert( e->Onext->Sym->Lnext == e );
|
||||
assert( e->Lface == f );
|
||||
e = e->Lnext;
|
||||
} while( e != f->anEdge );
|
||||
}
|
||||
assert( f->prev == fPrev && f->anEdge == NULL && f->data == NULL );
|
||||
|
||||
vPrev = vHead;
|
||||
for( vPrev = vHead ; (v = vPrev->next) != vHead; vPrev = v) {
|
||||
assert( v->prev == vPrev );
|
||||
e = v->anEdge;
|
||||
do {
|
||||
assert( e->Sym != e );
|
||||
assert( e->Sym->Sym == e );
|
||||
assert( e->Lnext->Onext->Sym == e );
|
||||
assert( e->Onext->Sym->Lnext == e );
|
||||
assert( e->Org == v );
|
||||
e = e->Onext;
|
||||
} while( e != v->anEdge );
|
||||
}
|
||||
assert( v->prev == vPrev && v->anEdge == NULL && v->data == NULL );
|
||||
|
||||
ePrev = eHead;
|
||||
for( ePrev = eHead ; (e = ePrev->next) != eHead; ePrev = e) {
|
||||
assert( e->Sym->next == ePrev->Sym );
|
||||
assert( e->Sym != e );
|
||||
assert( e->Sym->Sym == e );
|
||||
assert( e->Org != NULL );
|
||||
assert( e->Dst != NULL );
|
||||
assert( e->Lnext->Onext->Sym == e );
|
||||
assert( e->Onext->Sym->Lnext == e );
|
||||
}
|
||||
assert( e->Sym->next == ePrev->Sym
|
||||
&& e->Sym == &mesh->eHeadSym
|
||||
&& e->Sym->Sym == e
|
||||
&& e->Org == NULL && e->Dst == NULL
|
||||
&& e->Lface == NULL && e->Rface == NULL );
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,205 @@
|
||||
// see license file for original license.
|
||||
|
||||
#ifndef tools_glutess_normal
|
||||
#define tools_glutess_normal
|
||||
|
||||
#include "_tess"
|
||||
|
||||
/* __gl_projectPolygon( tess ) determines the polygon normal
|
||||
* and project vertices onto the plane of the polygon.
|
||||
*/
|
||||
//void __gl_projectPolygon( GLUtesselator *tess );
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
/// inlined C code : ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
#include <cmath>
|
||||
|
||||
#define Dot(u,v) (u[0]*v[0] + u[1]*v[1] + u[2]*v[2])
|
||||
|
||||
inline/*static*/ int static_LongAxis( GLUdouble v[3] )
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if( GLU_ABS(v[1]) > GLU_ABS(v[0]) ) { i = 1; }
|
||||
if( GLU_ABS(v[2]) > GLU_ABS(v[i]) ) { i = 2; }
|
||||
return i;
|
||||
}
|
||||
|
||||
inline/*static*/ void static_ComputeNormal( GLUtesselator *tess, GLUdouble norm[3] )
|
||||
{
|
||||
GLUvertex *v, *v1, *v2;
|
||||
GLUdouble c, tLen2, maxLen2;
|
||||
GLUdouble maxVal[3], minVal[3], d1[3], d2[3], tNorm[3];
|
||||
GLUvertex *maxVert[3], *minVert[3];
|
||||
GLUvertex *vHead = &tess->mesh->vHead;
|
||||
int i;
|
||||
|
||||
maxVal[0] = maxVal[1] = maxVal[2] = -2 * GLU_TESS_MAX_COORD;
|
||||
minVal[0] = minVal[1] = minVal[2] = 2 * GLU_TESS_MAX_COORD;
|
||||
|
||||
for( v = vHead->next; v != vHead; v = v->next ) {
|
||||
for( i = 0; i < 3; ++i ) {
|
||||
c = v->coords[i];
|
||||
if( c < minVal[i] ) { minVal[i] = c; minVert[i] = v; }
|
||||
if( c > maxVal[i] ) { maxVal[i] = c; maxVert[i] = v; }
|
||||
}
|
||||
}
|
||||
|
||||
/* Find two vertices separated by at least 1/sqrt(3) of the maximum
|
||||
* distance between any two vertices
|
||||
*/
|
||||
i = 0;
|
||||
if( maxVal[1] - minVal[1] > maxVal[0] - minVal[0] ) { i = 1; }
|
||||
if( maxVal[2] - minVal[2] > maxVal[i] - minVal[i] ) { i = 2; }
|
||||
if( minVal[i] >= maxVal[i] ) {
|
||||
/* All vertices are the same -- normal doesn't matter */
|
||||
norm[0] = 0; norm[1] = 0; norm[2] = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look for a third vertex which forms the triangle with maximum area
|
||||
* (Length of normal == twice the triangle area)
|
||||
*/
|
||||
maxLen2 = 0;
|
||||
v1 = minVert[i];
|
||||
v2 = maxVert[i];
|
||||
d1[0] = v1->coords[0] - v2->coords[0];
|
||||
d1[1] = v1->coords[1] - v2->coords[1];
|
||||
d1[2] = v1->coords[2] - v2->coords[2];
|
||||
for( v = vHead->next; v != vHead; v = v->next ) {
|
||||
d2[0] = v->coords[0] - v2->coords[0];
|
||||
d2[1] = v->coords[1] - v2->coords[1];
|
||||
d2[2] = v->coords[2] - v2->coords[2];
|
||||
tNorm[0] = d1[1]*d2[2] - d1[2]*d2[1];
|
||||
tNorm[1] = d1[2]*d2[0] - d1[0]*d2[2];
|
||||
tNorm[2] = d1[0]*d2[1] - d1[1]*d2[0];
|
||||
tLen2 = tNorm[0]*tNorm[0] + tNorm[1]*tNorm[1] + tNorm[2]*tNorm[2];
|
||||
if( tLen2 > maxLen2 ) {
|
||||
maxLen2 = tLen2;
|
||||
norm[0] = tNorm[0];
|
||||
norm[1] = tNorm[1];
|
||||
norm[2] = tNorm[2];
|
||||
}
|
||||
}
|
||||
|
||||
if( maxLen2 <= 0 ) {
|
||||
/* All points lie on a single line -- any decent normal will do */
|
||||
norm[0] = norm[1] = norm[2] = 0;
|
||||
norm[static_LongAxis(d1)] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline/*static*/ void static_CheckOrientation( GLUtesselator *tess )
|
||||
{
|
||||
GLUdouble area;
|
||||
GLUface *f, *fHead = &tess->mesh->fHead;
|
||||
GLUvertex *v, *vHead = &tess->mesh->vHead;
|
||||
GLUhalfEdge *e;
|
||||
|
||||
/* When we compute the normal automatically, we choose the orientation
|
||||
* so that the sum of the signed areas of all contours is non-negative.
|
||||
*/
|
||||
area = 0;
|
||||
for( f = fHead->next; f != fHead; f = f->next ) {
|
||||
e = f->anEdge;
|
||||
if( e->winding <= 0 ) continue;
|
||||
do {
|
||||
area += (e->Org->s - e->Dst->s) * (e->Org->t + e->Dst->t);
|
||||
e = e->Lnext;
|
||||
} while( e != f->anEdge );
|
||||
}
|
||||
if( area < 0 ) {
|
||||
/* Reverse the orientation by flipping all the t-coordinates */
|
||||
for( v = vHead->next; v != vHead; v = v->next ) {
|
||||
v->t = - v->t;
|
||||
}
|
||||
tess->tUnit[0] = - tess->tUnit[0];
|
||||
tess->tUnit[1] = - tess->tUnit[1];
|
||||
tess->tUnit[2] = - tess->tUnit[2];
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SLANTED_SWEEP)
|
||||
/* The "feature merging" is not intended to be complete. There are
|
||||
* special cases where edges are nearly parallel to the sweep line
|
||||
* which are not implemented. The algorithm should still behave
|
||||
* robustly (ie. produce a reasonable tesselation) in the presence
|
||||
* of such edges, however it may miss features which could have been
|
||||
* merged. We could minimize this effect by choosing the sweep line
|
||||
* direction to be something unusual (ie. not parallel to one of the
|
||||
* coordinate axes).
|
||||
*/
|
||||
#define S_UNIT_X 0.50941539564955385 /* Pre-normalized */
|
||||
#define S_UNIT_Y 0.86052074622010633
|
||||
#else
|
||||
#define S_UNIT_X 1.0
|
||||
#define S_UNIT_Y 0.0
|
||||
#endif
|
||||
|
||||
/* Determine the polygon normal and project vertices onto the plane
|
||||
* of the polygon.
|
||||
*/
|
||||
inline void __gl_projectPolygon( GLUtesselator *tess )
|
||||
{
|
||||
GLUvertex *v, *vHead = &tess->mesh->vHead;
|
||||
GLUdouble norm[3];
|
||||
GLUdouble *sUnit, *tUnit;
|
||||
int i, computedNormal = GLU_FALSE;
|
||||
|
||||
norm[0] = tess->normal[0];
|
||||
norm[1] = tess->normal[1];
|
||||
norm[2] = tess->normal[2];
|
||||
if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
|
||||
static_ComputeNormal( tess, norm );
|
||||
computedNormal = GLU_TRUE;
|
||||
}
|
||||
sUnit = tess->sUnit;
|
||||
tUnit = tess->tUnit;
|
||||
i = static_LongAxis( norm );
|
||||
|
||||
#if defined(FOR_TRITE_TEST_PROGRAM) || defined(TRUE_PROJECT)
|
||||
/* Choose the initial sUnit vector to be approximately perpendicular
|
||||
* to the normal.
|
||||
*/
|
||||
Normalize( norm );
|
||||
|
||||
sUnit[i] = 0;
|
||||
sUnit[(i+1)%3] = S_UNIT_X;
|
||||
sUnit[(i+2)%3] = S_UNIT_Y;
|
||||
|
||||
/* Now make it exactly perpendicular */
|
||||
w = Dot( sUnit, norm );
|
||||
sUnit[0] -= w * norm[0];
|
||||
sUnit[1] -= w * norm[1];
|
||||
sUnit[2] -= w * norm[2];
|
||||
Normalize( sUnit );
|
||||
|
||||
/* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */
|
||||
tUnit[0] = norm[1]*sUnit[2] - norm[2]*sUnit[1];
|
||||
tUnit[1] = norm[2]*sUnit[0] - norm[0]*sUnit[2];
|
||||
tUnit[2] = norm[0]*sUnit[1] - norm[1]*sUnit[0];
|
||||
Normalize( tUnit );
|
||||
#else
|
||||
/* Project perpendicular to a coordinate axis -- better numerically */
|
||||
sUnit[i] = 0;
|
||||
sUnit[(i+1)%3] = S_UNIT_X;
|
||||
sUnit[(i+2)%3] = S_UNIT_Y;
|
||||
|
||||
tUnit[i] = 0;
|
||||
tUnit[(i+1)%3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y;
|
||||
tUnit[(i+2)%3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X;
|
||||
#endif
|
||||
|
||||
/* Project the vertices onto the sweep plane */
|
||||
for( v = vHead->next; v != vHead; v = v->next ) {
|
||||
v->s = Dot( v->coords, sUnit );
|
||||
v->t = Dot( v->coords, tUnit );
|
||||
}
|
||||
if( computedNormal ) {
|
||||
static_CheckOrientation( tess );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,572 @@
|
||||
// see license file for original license.
|
||||
|
||||
#ifndef tools_glutess_priorityq
|
||||
#define tools_glutess_priorityq
|
||||
|
||||
#include <climits> /* LONG_MAX */
|
||||
#include "memalloc"
|
||||
|
||||
/* Include all the code for the regular heap-based queue here. */
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//#include "priorityq-heap.ic"
|
||||
//#include "priorityq-heap"
|
||||
|
||||
/* Use #define's so that another heap implementation can use this one */
|
||||
|
||||
#define PQkey PQHeapKey
|
||||
#define PQhandle PQHeapHandle
|
||||
#define PriorityQ PriorityQHeap
|
||||
|
||||
#define pqNewPriorityQ(leq) __gl_pqHeapNewPriorityQ(leq)
|
||||
#define pqDeletePriorityQ(pq) __gl_pqHeapDeletePriorityQ(pq)
|
||||
|
||||
/* The basic operations are insertion of a new key (pqInsert),
|
||||
* and examination/extraction of a key whose value is minimum
|
||||
* (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete);
|
||||
* for this purpose pqInsert returns a "handle" which is supplied
|
||||
* as the argument.
|
||||
*
|
||||
* An initial heap may be created efficiently by calling pqInsert
|
||||
* repeatedly, then calling pqInit. In any case pqInit must be called
|
||||
* before any operations other than pqInsert are used.
|
||||
*
|
||||
* If the heap is empty, pqMinimum/pqExtractMin will return a NULL key.
|
||||
* This may also be tested with pqIsEmpty.
|
||||
*/
|
||||
#define pqInit(pq) __gl_pqHeapInit(pq)
|
||||
#define pqInsert(pq,key) __gl_pqHeapInsert(pq,key)
|
||||
#define pqMinimum(pq) __gl_pqHeapMinimum(pq)
|
||||
#define pqExtractMin(pq) __gl_pqHeapExtractMin(pq)
|
||||
#define pqDelete(pq,handle) __gl_pqHeapDelete(pq,handle)
|
||||
#define pqIsEmpty(pq) __gl_pqHeapIsEmpty(pq)
|
||||
|
||||
/* Since we support deletion the data structure is a little more
|
||||
* complicated than an ordinary heap. "nodes" is the heap itself;
|
||||
* active nodes are stored in the range 1..pq->size. When the
|
||||
* heap exceeds its allocated size (pq->max), its size doubles.
|
||||
* The children of node i are nodes 2i and 2i+1.
|
||||
*
|
||||
* Each node stores an index into an array "handles". Each handle
|
||||
* stores a key, plus a pointer back to the node which currently
|
||||
* represents that key (ie. nodes[handles[i].node].handle == i).
|
||||
*/
|
||||
|
||||
typedef void *PQkey;
|
||||
typedef long PQhandle;
|
||||
typedef struct PriorityQ PriorityQ;
|
||||
|
||||
typedef struct { PQhandle handle; } PQnode;
|
||||
typedef struct { PQkey key; PQhandle node; } PQhandleElem;
|
||||
|
||||
struct PriorityQ {
|
||||
PQnode *nodes;
|
||||
PQhandleElem *handles;
|
||||
long size, max;
|
||||
PQhandle freeList;
|
||||
int initialized;
|
||||
int (*leq)(PQkey key1, PQkey key2);
|
||||
};
|
||||
|
||||
#define __gl_pqHeapMinimum(pq) ((pq)->handles[(pq)->nodes[1].handle].key)
|
||||
#define __gl_pqHeapIsEmpty(pq) ((pq)->size == 0)
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//#define INIT_SIZE 32
|
||||
inline long INIT_SIZE() {
|
||||
static const long s_value = 32;
|
||||
return s_value;
|
||||
}
|
||||
|
||||
/* Violates modularity, but a little faster */
|
||||
#include "geom"
|
||||
#define LEQ(x,y) VertLeq((GLUvertex *)x, (GLUvertex *)y)
|
||||
|
||||
/* really __gl_pqHeapNewPriorityQ */
|
||||
inline PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) )
|
||||
{
|
||||
PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ ));
|
||||
if (pq == NULL) return NULL;
|
||||
|
||||
pq->size = 0;
|
||||
pq->max = INIT_SIZE();
|
||||
pq->nodes = (PQnode *)memAlloc( (INIT_SIZE() + 1) * sizeof(pq->nodes[0]) );
|
||||
if (pq->nodes == NULL) {
|
||||
memFree(pq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pq->handles = (PQhandleElem *)memAlloc( (INIT_SIZE() + 1) * sizeof(pq->handles[0]) );
|
||||
if (pq->handles == NULL) {
|
||||
memFree(pq->nodes);
|
||||
memFree(pq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pq->initialized = GLU_FALSE;
|
||||
pq->freeList = 0;
|
||||
pq->leq = leq;
|
||||
|
||||
pq->nodes[1].handle = 1; /* so that Minimum() returns NULL */
|
||||
pq->handles[1].key = NULL;
|
||||
return pq;
|
||||
}
|
||||
|
||||
/* really __gl_pqHeapDeletePriorityQ */
|
||||
inline void pqDeletePriorityQ( PriorityQ *pq )
|
||||
{
|
||||
memFree( pq->handles );
|
||||
memFree( pq->nodes );
|
||||
memFree( pq );
|
||||
}
|
||||
|
||||
|
||||
inline/*static*/ void static_FloatDown( PriorityQ *pq, long curr )
|
||||
{
|
||||
PQnode *n = pq->nodes;
|
||||
PQhandleElem *h = pq->handles;
|
||||
PQhandle hCurr, hChild;
|
||||
long child;
|
||||
|
||||
hCurr = n[curr].handle;
|
||||
for( ;; ) {
|
||||
child = curr << 1;
|
||||
if( child < pq->size && LEQ( h[n[child+1].handle].key,
|
||||
h[n[child].handle].key )) {
|
||||
++child;
|
||||
}
|
||||
|
||||
assert(child <= pq->max);
|
||||
|
||||
hChild = n[child].handle;
|
||||
if( child > pq->size || LEQ( h[hCurr].key, h[hChild].key )) {
|
||||
n[curr].handle = hCurr;
|
||||
h[hCurr].node = curr;
|
||||
break;
|
||||
}
|
||||
n[curr].handle = hChild;
|
||||
h[hChild].node = curr;
|
||||
curr = child;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline/*static*/ void static_FloatUp( PriorityQ *pq, long curr )
|
||||
{
|
||||
PQnode *n = pq->nodes;
|
||||
PQhandleElem *h = pq->handles;
|
||||
PQhandle hCurr, hParent;
|
||||
long parent;
|
||||
|
||||
hCurr = n[curr].handle;
|
||||
for( ;; ) {
|
||||
parent = curr >> 1;
|
||||
hParent = n[parent].handle;
|
||||
if( parent == 0 || LEQ( h[hParent].key, h[hCurr].key )) {
|
||||
n[curr].handle = hCurr;
|
||||
h[hCurr].node = curr;
|
||||
break;
|
||||
}
|
||||
n[curr].handle = hParent;
|
||||
h[hParent].node = curr;
|
||||
curr = parent;
|
||||
}
|
||||
}
|
||||
|
||||
/* really __gl_pqHeapInit */
|
||||
inline void pqInit( PriorityQ *pq )
|
||||
{
|
||||
long i;
|
||||
|
||||
/* This method of building a heap is O(n), rather than O(n lg n). */
|
||||
|
||||
for( i = pq->size; i >= 1; --i ) {
|
||||
static_FloatDown( pq, i );
|
||||
}
|
||||
pq->initialized = GLU_TRUE;
|
||||
}
|
||||
|
||||
/* really __gl_pqHeapInsert */
|
||||
/* returns LONG_MAX iff out of memory */
|
||||
inline PQhandle pqInsert( PriorityQ *pq, PQkey keyNew )
|
||||
{
|
||||
long curr;
|
||||
PQhandle free;
|
||||
|
||||
curr = ++ pq->size;
|
||||
if( (curr*2) > pq->max ) {
|
||||
PQnode *saveNodes= pq->nodes;
|
||||
PQhandleElem *saveHandles= pq->handles;
|
||||
|
||||
/* If the heap overflows, double its size. */
|
||||
pq->max <<= 1;
|
||||
pq->nodes = (PQnode *)memRealloc( pq->nodes,
|
||||
(size_t)
|
||||
((pq->max + 1) * sizeof( pq->nodes[0] )));
|
||||
if (pq->nodes == NULL) {
|
||||
pq->nodes = saveNodes; /* restore ptr to free upon return */
|
||||
return LONG_MAX;
|
||||
}
|
||||
pq->handles = (PQhandleElem *)memRealloc( pq->handles,
|
||||
(size_t)
|
||||
((pq->max + 1) *
|
||||
sizeof( pq->handles[0] )));
|
||||
if (pq->handles == NULL) {
|
||||
pq->handles = saveHandles; /* restore ptr to free upon return */
|
||||
return LONG_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
if( pq->freeList == 0 ) {
|
||||
free = curr;
|
||||
} else {
|
||||
free = pq->freeList;
|
||||
pq->freeList = pq->handles[free].node;
|
||||
}
|
||||
|
||||
pq->nodes[curr].handle = free;
|
||||
pq->handles[free].node = curr;
|
||||
pq->handles[free].key = keyNew;
|
||||
|
||||
if( pq->initialized ) {
|
||||
static_FloatUp( pq, curr );
|
||||
}
|
||||
assert(free != LONG_MAX);
|
||||
return free;
|
||||
}
|
||||
|
||||
/* really __gl_pqHeapExtractMin */
|
||||
inline PQkey pqExtractMin( PriorityQ *pq )
|
||||
{
|
||||
PQnode *n = pq->nodes;
|
||||
PQhandleElem *h = pq->handles;
|
||||
PQhandle hMin = n[1].handle;
|
||||
PQkey min = h[hMin].key;
|
||||
|
||||
if( pq->size > 0 ) {
|
||||
n[1].handle = n[pq->size].handle;
|
||||
h[n[1].handle].node = 1;
|
||||
|
||||
h[hMin].key = NULL;
|
||||
h[hMin].node = pq->freeList;
|
||||
pq->freeList = hMin;
|
||||
|
||||
if( -- pq->size > 0 ) {
|
||||
static_FloatDown( pq, 1 );
|
||||
}
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
/* really __gl_pqHeapDelete */
|
||||
inline void pqDelete( PriorityQ *pq, PQhandle hCurr )
|
||||
{
|
||||
PQnode *n = pq->nodes;
|
||||
PQhandleElem *h = pq->handles;
|
||||
long curr;
|
||||
|
||||
assert( hCurr >= 1 && hCurr <= pq->max && h[hCurr].key != NULL );
|
||||
|
||||
curr = h[hCurr].node;
|
||||
n[curr].handle = n[pq->size].handle;
|
||||
h[n[curr].handle].node = curr;
|
||||
|
||||
if( curr <= -- pq->size ) {
|
||||
if( curr <= 1 || LEQ( h[n[curr>>1].handle].key, h[n[curr].handle].key )) {
|
||||
static_FloatDown( pq, curr );
|
||||
} else {
|
||||
static_FloatUp( pq, curr );
|
||||
}
|
||||
}
|
||||
h[hCurr].key = NULL;
|
||||
h[hCurr].node = pq->freeList;
|
||||
pq->freeList = hCurr;
|
||||
}
|
||||
|
||||
/* Now redefine all the function names to map to their "Sort" versions. */
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//#include "priorityq-sort"
|
||||
|
||||
#undef PQkey
|
||||
#undef PQhandle
|
||||
#undef PriorityQ
|
||||
#undef pqNewPriorityQ
|
||||
#undef pqDeletePriorityQ
|
||||
#undef pqInit
|
||||
#undef pqInsert
|
||||
#undef pqMinimum
|
||||
#undef pqExtractMin
|
||||
#undef pqDelete
|
||||
#undef pqIsEmpty
|
||||
|
||||
/* Use #define's so that another heap implementation can use this one */
|
||||
|
||||
#define PQkey PQSortKey
|
||||
#define PQhandle PQSortHandle
|
||||
#define PriorityQ PriorityQSort
|
||||
|
||||
#define pqNewPriorityQ(leq) __gl_pqSortNewPriorityQ(leq)
|
||||
#define pqDeletePriorityQ(pq) __gl_pqSortDeletePriorityQ(pq)
|
||||
|
||||
/* The basic operations are insertion of a new key (pqInsert),
|
||||
* and examination/extraction of a key whose value is minimum
|
||||
* (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete);
|
||||
* for this purpose pqInsert returns a "handle" which is supplied
|
||||
* as the argument.
|
||||
*
|
||||
* An initial heap may be created efficiently by calling pqInsert
|
||||
* repeatedly, then calling pqInit. In any case pqInit must be called
|
||||
* before any operations other than pqInsert are used.
|
||||
*
|
||||
* If the heap is empty, pqMinimum/pqExtractMin will return a NULL key.
|
||||
* This may also be tested with pqIsEmpty.
|
||||
*/
|
||||
#define pqInit(pq) __gl_pqSortInit(pq)
|
||||
#define pqInsert(pq,key) __gl_pqSortInsert(pq,key)
|
||||
#define pqMinimum(pq) __gl_pqSortMinimum(pq)
|
||||
#define pqExtractMin(pq) __gl_pqSortExtractMin(pq)
|
||||
#define pqDelete(pq,handle) __gl_pqSortDelete(pq,handle)
|
||||
#define pqIsEmpty(pq) __gl_pqSortIsEmpty(pq)
|
||||
|
||||
|
||||
/* Since we support deletion the data structure is a little more
|
||||
* complicated than an ordinary heap. "nodes" is the heap itself;
|
||||
* active nodes are stored in the range 1..pq->size. When the
|
||||
* heap exceeds its allocated size (pq->max), its size doubles.
|
||||
* The children of node i are nodes 2i and 2i+1.
|
||||
*
|
||||
* Each node stores an index into an array "handles". Each handle
|
||||
* stores a key, plus a pointer back to the node which currently
|
||||
* represents that key (ie. nodes[handles[i].node].handle == i).
|
||||
*/
|
||||
|
||||
typedef PQHeapKey PQkey;
|
||||
typedef PQHeapHandle PQhandle;
|
||||
typedef struct PriorityQ PriorityQ;
|
||||
|
||||
struct PriorityQ {
|
||||
PriorityQHeap *heap;
|
||||
PQkey *keys;
|
||||
PQkey **order;
|
||||
PQhandle size, max;
|
||||
int initialized;
|
||||
int (*leq)(PQkey key1, PQkey key2);
|
||||
};
|
||||
|
||||
/* really __gl_pqSortNewPriorityQ */
|
||||
inline PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) )
|
||||
{
|
||||
PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ ));
|
||||
if (pq == NULL) return NULL;
|
||||
|
||||
pq->heap = __gl_pqHeapNewPriorityQ( leq );
|
||||
if (pq->heap == NULL) {
|
||||
memFree(pq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pq->keys = (PQHeapKey *)memAlloc( INIT_SIZE() * sizeof(pq->keys[0]) );
|
||||
if (pq->keys == NULL) {
|
||||
__gl_pqHeapDeletePriorityQ(pq->heap);
|
||||
memFree(pq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pq->size = 0;
|
||||
pq->max = INIT_SIZE();
|
||||
pq->initialized = GLU_FALSE;
|
||||
pq->leq = leq;
|
||||
return pq;
|
||||
}
|
||||
|
||||
/* really __gl_pqSortDeletePriorityQ */
|
||||
inline void pqDeletePriorityQ( PriorityQ *pq )
|
||||
{
|
||||
assert(pq != NULL);
|
||||
if (pq->heap != NULL) __gl_pqHeapDeletePriorityQ( pq->heap );
|
||||
if (pq->order != NULL) memFree( pq->order );
|
||||
if (pq->keys != NULL) memFree( pq->keys );
|
||||
memFree( pq );
|
||||
}
|
||||
|
||||
|
||||
#define LT(x,y) (! LEQ(y,x))
|
||||
#define GT(x,y) (! LEQ(x,y))
|
||||
//#define pq_Swap(a,b) if(1){PQkey *tmp = *a; *a = *b; *b = tmp;}else
|
||||
#define pq_Swap(a,b) do{PQkey *tmp = *a; *a = *b; *b = tmp;} while(false)
|
||||
|
||||
/* really __gl_pqSortInit */
|
||||
inline int pqInit( PriorityQ *pq )
|
||||
{
|
||||
PQkey **p, **r, **i, **j, *piv;
|
||||
struct { PQkey **p, **r; } Stack[50], *top = Stack;
|
||||
unsigned long seed = 2016473283;
|
||||
|
||||
/* Create an array of indirect pointers to the keys, so that we
|
||||
* the handles we have returned are still valid.
|
||||
*/
|
||||
/*
|
||||
pq->order = (PQHeapKey **)memAlloc( (size_t)
|
||||
(pq->size * sizeof(pq->order[0])) );
|
||||
*/
|
||||
pq->order = (PQHeapKey **)memAlloc( (size_t)
|
||||
((pq->size+1) * sizeof(pq->order[0])) );
|
||||
/* the previous line is a patch to compensate for the fact that IBM */
|
||||
/* machines return a null on a malloc of zero bytes (unlike SGI), */
|
||||
/* so we have to put in this defense to guard against a memory */
|
||||
/* fault four lines down. from fossum@austin.ibm.com. */
|
||||
if (pq->order == NULL) return 0;
|
||||
|
||||
p = pq->order;
|
||||
r = p + pq->size - 1;
|
||||
for( piv = pq->keys, i = p; i <= r; ++piv, ++i ) {
|
||||
*i = piv;
|
||||
}
|
||||
|
||||
/* Sort the indirect pointers in descending order,
|
||||
* using randomized Quicksort
|
||||
*/
|
||||
top->p = p; top->r = r; ++top;
|
||||
while( --top >= Stack ) {
|
||||
p = top->p;
|
||||
r = top->r;
|
||||
while( r > p + 10 ) {
|
||||
seed = seed * 1539415821 + 1;
|
||||
i = p + seed % (r - p + 1);
|
||||
piv = *i;
|
||||
*i = *p;
|
||||
*p = piv;
|
||||
i = p - 1;
|
||||
j = r + 1;
|
||||
do {
|
||||
do { ++i; } while( GT( **i, *piv ));
|
||||
do { --j; } while( LT( **j, *piv ));
|
||||
pq_Swap( i, j );
|
||||
} while( i < j );
|
||||
pq_Swap( i, j ); /* Undo last swap */
|
||||
if( i - p < r - j ) {
|
||||
top->p = j+1; top->r = r; ++top;
|
||||
r = i-1;
|
||||
} else {
|
||||
top->p = p; top->r = i-1; ++top;
|
||||
p = j+1;
|
||||
}
|
||||
}
|
||||
/* Insertion sort small lists */
|
||||
for( i = p+1; i <= r; ++i ) {
|
||||
piv = *i;
|
||||
for( j = i; j > p && LT( **(j-1), *piv ); --j ) {
|
||||
*j = *(j-1);
|
||||
}
|
||||
*j = piv;
|
||||
}
|
||||
}
|
||||
pq->max = pq->size;
|
||||
pq->initialized = GLU_TRUE;
|
||||
__gl_pqHeapInit( pq->heap ); /* always succeeds */
|
||||
|
||||
#ifndef NDEBUG
|
||||
p = pq->order;
|
||||
r = p + pq->size - 1;
|
||||
for( i = p; i < r; ++i ) {
|
||||
assert( LEQ( **(i+1), **i ));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* really __gl_pqSortInsert */
|
||||
/* returns LONG_MAX iff out of memory */
|
||||
inline PQhandle pqInsert( PriorityQ *pq, PQkey keyNew )
|
||||
{
|
||||
long curr;
|
||||
|
||||
if( pq->initialized ) {
|
||||
return __gl_pqHeapInsert( pq->heap, keyNew );
|
||||
}
|
||||
curr = pq->size;
|
||||
if( ++ pq->size >= pq->max ) {
|
||||
PQkey *saveKey= pq->keys;
|
||||
|
||||
/* If the heap overflows, double its size. */
|
||||
pq->max <<= 1;
|
||||
pq->keys = (PQHeapKey *)memRealloc( pq->keys,
|
||||
(size_t)
|
||||
(pq->max * sizeof( pq->keys[0] )));
|
||||
if (pq->keys == NULL) {
|
||||
pq->keys = saveKey; /* restore ptr to free upon return */
|
||||
return LONG_MAX;
|
||||
}
|
||||
}
|
||||
assert(curr != LONG_MAX);
|
||||
pq->keys[curr] = keyNew;
|
||||
|
||||
/* Negative handles index the sorted array. */
|
||||
return -(curr+1);
|
||||
}
|
||||
|
||||
/* really __gl_pqSortExtractMin */
|
||||
inline PQkey pqExtractMin( PriorityQ *pq )
|
||||
{
|
||||
PQkey sortMin, heapMin;
|
||||
|
||||
if( pq->size == 0 ) {
|
||||
return __gl_pqHeapExtractMin( pq->heap );
|
||||
}
|
||||
sortMin = *(pq->order[pq->size-1]);
|
||||
if( ! __gl_pqHeapIsEmpty( pq->heap )) {
|
||||
heapMin = __gl_pqHeapMinimum( pq->heap );
|
||||
if( LEQ( heapMin, sortMin )) {
|
||||
return __gl_pqHeapExtractMin( pq->heap );
|
||||
}
|
||||
}
|
||||
do {
|
||||
-- pq->size;
|
||||
} while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL );
|
||||
return sortMin;
|
||||
}
|
||||
|
||||
/* really __gl_pqSortMinimum */
|
||||
inline PQkey pqMinimum( PriorityQ *pq )
|
||||
{
|
||||
PQkey sortMin, heapMin;
|
||||
|
||||
if( pq->size == 0 ) {
|
||||
return __gl_pqHeapMinimum( pq->heap );
|
||||
}
|
||||
sortMin = *(pq->order[pq->size-1]);
|
||||
if( ! __gl_pqHeapIsEmpty( pq->heap )) {
|
||||
heapMin = __gl_pqHeapMinimum( pq->heap );
|
||||
if( LEQ( heapMin, sortMin )) {
|
||||
return heapMin;
|
||||
}
|
||||
}
|
||||
return sortMin;
|
||||
}
|
||||
|
||||
/* really __gl_pqSortIsEmpty */
|
||||
inline int pqIsEmpty( PriorityQ *pq )
|
||||
{
|
||||
return (pq->size == 0) && __gl_pqHeapIsEmpty( pq->heap );
|
||||
}
|
||||
|
||||
/* really __gl_pqSortDelete */
|
||||
inline void pqDelete( PriorityQ *pq, PQhandle curr )
|
||||
{
|
||||
if( curr >= 0 ) {
|
||||
__gl_pqHeapDelete( pq->heap, curr );
|
||||
return;
|
||||
}
|
||||
curr = -(curr+1);
|
||||
assert( curr < pq->max && pq->keys[curr] != NULL );
|
||||
|
||||
pq->keys[curr] = NULL;
|
||||
while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ) {
|
||||
-- pq->size;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef tools_glutess_rename
|
||||
#define tools_glutess_rename
|
||||
|
||||
/* G.Barrand : namespace protection : */
|
||||
#define gluTessBeginContour inlib_gluTessBeginContour
|
||||
#define gluTessBeginPolygon inlib_gluTessBeginPolygon
|
||||
#define gluTessCallback inlib_gluTessCallback
|
||||
#define gluTessEndContour inlib_gluTessEndContour
|
||||
#define gluTessEndPolygon inlib_gluTessEndPolygon
|
||||
#define gluTessNormal inlib_gluTessNormal
|
||||
#define gluTessProperty inlib_gluTessProperty
|
||||
#define gluTessVertex inlib_gluTessVertex
|
||||
|
||||
/* internal */
|
||||
#define gluBeginPolygon inlib_gluBeginPolygon
|
||||
#define gluDeleteTess inlib_gluDeleteTess
|
||||
#define gluEndPolygon inlib_gluEndPolygon
|
||||
#define gluGetTessProperty inlib_gluGetTessProperty
|
||||
#define gluNewTess inlib_gluNewTess
|
||||
#define gluNextContour inlib_gluNextContour
|
||||
|
||||
#define __gl_computeInterior inlib__gl_computeInterior
|
||||
#define __gl_dictListDelete inlib__gl_dictListDelete
|
||||
#define __gl_dictListDeleteDict inlib__gl_dictListDeleteDict
|
||||
#define __gl_dictListInsertBefore inlib__gl_dictListInsertBefore
|
||||
#define __gl_dictListNewDict inlib__gl_dictListNewDict
|
||||
#define __gl_dictListSearch inlib__gl_dictListSearch
|
||||
|
||||
#define __gl_edgeEval inlib__gl_edgeEval
|
||||
#define __gl_edgeIntersect inlib__gl_edgeIntersect
|
||||
#define __gl_edgeSign inlib__gl_edgeSign
|
||||
/* done in memalloc.h :
|
||||
#define __gl_memInit inlib__gl_memInit
|
||||
*/
|
||||
#define __gl_meshAddEdgeVertex inlib__gl_meshAddEdgeVertex
|
||||
#define __gl_meshCheckMesh inlib__gl_meshCheckMesh
|
||||
#define __gl_meshConnect inlib__gl_meshConnect
|
||||
#define __gl_meshDelete inlib__gl_meshDelete
|
||||
#define __gl_meshDeleteMesh inlib__gl_meshDeleteMesh
|
||||
#define __gl_meshDiscardExterior inlib__gl_meshDiscardExterior
|
||||
#define __gl_meshMakeEdge inlib__gl_meshMakeEdge
|
||||
#define __gl_meshNewMesh inlib__gl_meshNewMesh
|
||||
#define __gl_meshSetWindingNumber inlib__gl_meshSetWindingNumber
|
||||
#define __gl_meshSplice inlib__gl_meshSplice
|
||||
#define __gl_meshSplitEdge inlib__gl_meshSplitEdge
|
||||
#define __gl_meshTessellateInterior inlib__gl_meshTessellateInterior
|
||||
#define __gl_meshTessellateMonoRegion inlib__gl_meshTessellateMonoRegion
|
||||
#define __gl_meshUnion inlib__gl_meshUnion
|
||||
#define __gl_meshZapFace inlib__gl_meshZapFace
|
||||
#define __gl_noBeginData inlib__gl_noBeginData
|
||||
#define __gl_noCombineData inlib__gl_noCombineData
|
||||
#define __gl_noEdgeFlagData inlib__gl_noEdgeFlagData
|
||||
#define __gl_noEndData inlib__gl_noEndData
|
||||
#define __gl_noErrorData inlib__gl_noErrorData
|
||||
#define __gl_noVertexData inlib__gl_noVertexData
|
||||
#define __gl_pqHeapDelete inlib__gl_pqHeapDelete
|
||||
#define __gl_pqHeapDeletePriorityQ inlib__gl_pqHeapDeletePriorityQ
|
||||
#define __gl_pqHeapExtractMin inlib__gl_pqHeapExtractMin
|
||||
#define __gl_pqHeapInit inlib__gl_pqHeapInit
|
||||
#define __gl_pqHeapInsert inlib__gl_pqHeapInsert
|
||||
#define __gl_pqHeapNewPriorityQ inlib__gl_pqHeapNewPriorityQ
|
||||
#define __gl_pqSortDelete inlib__gl_pqSortDelete
|
||||
#define __gl_pqSortDeletePriorityQ inlib__gl_pqSortDeletePriorityQ
|
||||
#define __gl_pqSortExtractMin inlib__gl_pqSortExtractMin
|
||||
#define __gl_pqSortInit inlib__gl_pqSortInit
|
||||
#define __gl_pqSortInsert inlib__gl_pqSortInsert
|
||||
#define __gl_pqSortIsEmpty inlib__gl_pqSortIsEmpty
|
||||
#define __gl_pqSortMinimum inlib__gl_pqSortMinimum
|
||||
#define __gl_pqSortNewPriorityQ inlib__gl_pqSortNewPriorityQ
|
||||
#define __gl_projectPolygon inlib__gl_projectPolygon
|
||||
#define __gl_renderBoundary inlib__gl_renderBoundary
|
||||
#define __gl_renderCache inlib__gl_renderCache
|
||||
#define __gl_renderMesh inlib__gl_renderMesh
|
||||
#define __gl_transEval inlib__gl_transEval
|
||||
#define __gl_transSign inlib__gl_transSign
|
||||
#define __gl_vertCCW inlib__gl_vertCCW
|
||||
#define __gl_vertLeq inlib__gl_vertLeq
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,483 @@
|
||||
// see license file for original license.
|
||||
|
||||
#ifndef tools_glutess_render
|
||||
#define tools_glutess_render
|
||||
|
||||
#include "mesh"
|
||||
|
||||
/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle
|
||||
* fans, strips, and separate triangles. A substantial effort is made
|
||||
* to use as few rendering primitives as possible (ie. to make the fans
|
||||
* and strips as large as possible).
|
||||
*
|
||||
* The rendering output is provided as callbacks (see the api).
|
||||
*/
|
||||
//void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh );
|
||||
//void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh );
|
||||
|
||||
//GLUboolean __gl_renderCache( GLUtesselator *tess );
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
/// inlined C code : ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
#include "_tess"
|
||||
|
||||
/* This structure remembers the information we need about a primitive
|
||||
* to be able to render it later, once we have determined which
|
||||
* primitive is able to use the most triangles.
|
||||
*/
|
||||
struct FaceCount {
|
||||
long size; /* number of triangles used */
|
||||
GLUhalfEdge *eStart; /* edge where this primitive starts */
|
||||
void (*render)(GLUtesselator *, GLUhalfEdge *, long);
|
||||
/* routine to render this primitive */
|
||||
};
|
||||
|
||||
inline/*static*/ struct FaceCount static_MaximumFan( GLUhalfEdge *eOrig );
|
||||
inline/*static*/ struct FaceCount static_MaximumStrip( GLUhalfEdge *eOrig );
|
||||
|
||||
inline/*static*/ void static_RenderFan( GLUtesselator *tess, GLUhalfEdge *eStart, long size );
|
||||
inline/*static*/ void static_RenderStrip( GLUtesselator *tess, GLUhalfEdge *eStart, long size );
|
||||
inline/*static*/ void static_RenderTriangle( GLUtesselator *tess, GLUhalfEdge *eStart,
|
||||
long size );
|
||||
|
||||
inline/*static*/ void static_RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig );
|
||||
inline/*static*/ void static_RenderLonelyTriangles( GLUtesselator *tess, GLUface *head );
|
||||
|
||||
|
||||
|
||||
/************************ Strips and Fans decomposition ******************/
|
||||
|
||||
/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle
|
||||
* fans, strips, and separate triangles. A substantial effort is made
|
||||
* to use as few rendering primitives as possible (ie. to make the fans
|
||||
* and strips as large as possible).
|
||||
*
|
||||
* The rendering output is provided as callbacks (see the api).
|
||||
*/
|
||||
inline void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh )
|
||||
{
|
||||
GLUface *f;
|
||||
|
||||
/* Make a list of separate triangles so we can render them all at once */
|
||||
tess->lonelyTriList = NULL;
|
||||
|
||||
for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
|
||||
f->marked = GLU_FALSE;
|
||||
}
|
||||
for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
|
||||
|
||||
/* We examine all faces in an arbitrary order. Whenever we find
|
||||
* an unprocessed face F, we output a group of faces including F
|
||||
* whose size is maximum.
|
||||
*/
|
||||
if( f->inside && ! f->marked ) {
|
||||
static_RenderMaximumFaceGroup( tess, f );
|
||||
assert( f->marked );
|
||||
}
|
||||
}
|
||||
if( tess->lonelyTriList != NULL ) {
|
||||
static_RenderLonelyTriangles( tess, tess->lonelyTriList );
|
||||
tess->lonelyTriList = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline/*static*/ void static_RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig )
|
||||
{
|
||||
/* We want to find the largest triangle fan or strip of unmarked faces
|
||||
* which includes the given face fOrig. There are 3 possible fans
|
||||
* passing through fOrig (one centered at each vertex), and 3 possible
|
||||
* strips (one for each CCW permutation of the vertices). Our strategy
|
||||
* is to try all of these, and take the primitive which uses the most
|
||||
* triangles (a greedy approach).
|
||||
*/
|
||||
GLUhalfEdge *e = fOrig->anEdge;
|
||||
struct FaceCount max, newFace;
|
||||
|
||||
max.size = 1;
|
||||
max.eStart = e;
|
||||
max.render = &static_RenderTriangle;
|
||||
|
||||
if( ! tess->flagBoundary ) {
|
||||
newFace = static_MaximumFan( e ); if( newFace.size > max.size ) { max = newFace; }
|
||||
newFace = static_MaximumFan( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
|
||||
newFace = static_MaximumFan( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
|
||||
|
||||
newFace = static_MaximumStrip( e ); if( newFace.size > max.size ) { max = newFace; }
|
||||
newFace = static_MaximumStrip( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
|
||||
newFace = static_MaximumStrip( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
|
||||
}
|
||||
(*(max.render))( tess, max.eStart, max.size );
|
||||
}
|
||||
|
||||
|
||||
/* Macros which keep track of faces we have marked temporarily, and allow
|
||||
* us to backtrack when necessary. With triangle fans, this is not
|
||||
* really necessary, since the only awkward case is a loop of triangles
|
||||
* around a single origin vertex. However with strips the situation is
|
||||
* more complicated, and we need a general tracking method like the
|
||||
* one here.
|
||||
*/
|
||||
#define Marked(f) (! (f)->inside || (f)->marked)
|
||||
|
||||
#define AddToTrail(f,t) ((f)->trail = (t), (t) = (f), (f)->marked = GLU_TRUE)
|
||||
|
||||
//#define FreeTrail(t) if( 1 ) { while( (t) != NULL ) { (t)->marked = GLU_FALSE; t = (t)->trail; } } else
|
||||
#define FreeTrail(t) do { while( (t) != NULL ) { (t)->marked = GLU_FALSE; t = (t)->trail; } } while(false)
|
||||
|
||||
inline/*static*/ struct FaceCount static_MaximumFan( GLUhalfEdge *eOrig )
|
||||
{
|
||||
/* eOrig->Lface is the face we want to render. We want to find the size
|
||||
* of a maximal fan around eOrig->Org. To do this we just walk around
|
||||
* the origin vertex as far as possible in both directions.
|
||||
*/
|
||||
struct FaceCount newFace = { 0, NULL, &static_RenderFan };
|
||||
GLUface *trail = NULL;
|
||||
GLUhalfEdge *e;
|
||||
|
||||
for( e = eOrig; ! Marked( e->Lface ); e = e->Onext ) {
|
||||
AddToTrail( e->Lface, trail );
|
||||
++newFace.size;
|
||||
}
|
||||
for( e = eOrig; ! Marked( e->Rface ); e = e->Oprev ) {
|
||||
AddToTrail( e->Rface, trail );
|
||||
++newFace.size;
|
||||
}
|
||||
newFace.eStart = e;
|
||||
/*LINTED*/
|
||||
FreeTrail( trail );
|
||||
return newFace;
|
||||
}
|
||||
|
||||
|
||||
#define IsEven(n) (((n) & 1) == 0)
|
||||
|
||||
inline/*static*/ struct FaceCount static_MaximumStrip( GLUhalfEdge *eOrig )
|
||||
{
|
||||
/* Here we are looking for a maximal strip that contains the vertices
|
||||
* eOrig->Org, eOrig->Dst, eOrig->Lnext->Dst (in that order or the
|
||||
* reverse, such that all triangles are oriented CCW).
|
||||
*
|
||||
* Again we walk forward and backward as far as possible. However for
|
||||
* strips there is a twist: to get CCW orientations, there must be
|
||||
* an *even* number of triangles in the strip on one side of eOrig.
|
||||
* We walk the strip starting on a side with an even number of triangles;
|
||||
* if both side have an odd number, we are forced to shorten one side.
|
||||
*/
|
||||
struct FaceCount newFace = { 0, NULL, &static_RenderStrip };
|
||||
long headSize = 0, tailSize = 0;
|
||||
GLUface *trail = NULL;
|
||||
GLUhalfEdge *e, *eTail, *eHead;
|
||||
|
||||
for( e = eOrig; ! Marked( e->Lface ); ++tailSize, e = e->Onext ) {
|
||||
AddToTrail( e->Lface, trail );
|
||||
++tailSize;
|
||||
e = e->Dprev;
|
||||
if( Marked( e->Lface )) break;
|
||||
AddToTrail( e->Lface, trail );
|
||||
}
|
||||
eTail = e;
|
||||
|
||||
for( e = eOrig; ! Marked( e->Rface ); ++headSize, e = e->Dnext ) {
|
||||
AddToTrail( e->Rface, trail );
|
||||
++headSize;
|
||||
e = e->Oprev;
|
||||
if( Marked( e->Rface )) break;
|
||||
AddToTrail( e->Rface, trail );
|
||||
}
|
||||
eHead = e;
|
||||
|
||||
newFace.size = tailSize + headSize;
|
||||
if( IsEven( tailSize )) {
|
||||
newFace.eStart = eTail->Sym;
|
||||
} else if( IsEven( headSize )) {
|
||||
newFace.eStart = eHead;
|
||||
} else {
|
||||
/* Both sides have odd length, we must shorten one of them. In fact,
|
||||
* we must start from eHead to guarantee inclusion of eOrig->Lface.
|
||||
*/
|
||||
--newFace.size;
|
||||
newFace.eStart = eHead->Onext;
|
||||
}
|
||||
/*LINTED*/
|
||||
FreeTrail( trail );
|
||||
return newFace;
|
||||
}
|
||||
|
||||
|
||||
inline/*static*/ void static_RenderTriangle( GLUtesselator *tess, GLUhalfEdge *e, long size )
|
||||
{
|
||||
/* Just add the triangle to a triangle list, so we can render all
|
||||
* the separate triangles at once.
|
||||
*/
|
||||
assert( size == 1 );
|
||||
AddToTrail( e->Lface, tess->lonelyTriList );
|
||||
// the following line should suppress compiler warning about unused parameter 'size'
|
||||
// observed on MacOS/clang
|
||||
(void)size;
|
||||
}
|
||||
|
||||
|
||||
inline/*static*/ void static_RenderLonelyTriangles( GLUtesselator *tess, GLUface *f )
|
||||
{
|
||||
/* Now we render all the separate triangles which could not be
|
||||
* grouped into a triangle fan or strip.
|
||||
*/
|
||||
GLUhalfEdge *e;
|
||||
int newState;
|
||||
int edgeState = -1; /* force edge state output for first vertex */
|
||||
|
||||
CALL_BEGIN_OR_BEGIN_DATA( GLU_TRIANGLES );
|
||||
|
||||
for( ; f != NULL; f = f->trail ) {
|
||||
/* Loop once for each edge (there will always be 3 edges) */
|
||||
|
||||
e = f->anEdge;
|
||||
do {
|
||||
if( tess->flagBoundary ) {
|
||||
/* Set the "edge state" to GLU_TRUE just before we output the
|
||||
* first vertex of each edge on the polygon boundary.
|
||||
*/
|
||||
newState = ! e->Rface->inside;
|
||||
if( edgeState != newState ) {
|
||||
edgeState = newState;
|
||||
CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA( edgeState );
|
||||
}
|
||||
}
|
||||
CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
|
||||
|
||||
e = e->Lnext;
|
||||
} while( e != f->anEdge );
|
||||
}
|
||||
CALL_END_OR_END_DATA();
|
||||
}
|
||||
|
||||
|
||||
inline/*static*/ void static_RenderFan( GLUtesselator *tess, GLUhalfEdge *e, long size )
|
||||
{
|
||||
/* Render as many CCW triangles as possible in a fan starting from
|
||||
* edge "e". The fan *should* contain exactly "size" triangles
|
||||
* (otherwise we've goofed up somewhere).
|
||||
*/
|
||||
CALL_BEGIN_OR_BEGIN_DATA( GLU_TRIANGLE_FAN );
|
||||
CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
|
||||
CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
|
||||
|
||||
while( ! Marked( e->Lface )) {
|
||||
e->Lface->marked = GLU_TRUE;
|
||||
--size;
|
||||
e = e->Onext;
|
||||
CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
|
||||
}
|
||||
|
||||
assert( size == 0 );
|
||||
CALL_END_OR_END_DATA();
|
||||
}
|
||||
|
||||
|
||||
inline/*static*/ void static_RenderStrip( GLUtesselator *tess, GLUhalfEdge *e, long size )
|
||||
{
|
||||
/* Render as many CCW triangles as possible in a strip starting from
|
||||
* edge "e". The strip *should* contain exactly "size" triangles
|
||||
* (otherwise we've goofed up somewhere).
|
||||
*/
|
||||
CALL_BEGIN_OR_BEGIN_DATA( GLU_TRIANGLE_STRIP );
|
||||
CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
|
||||
CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
|
||||
|
||||
while( ! Marked( e->Lface )) {
|
||||
e->Lface->marked = GLU_TRUE;
|
||||
--size;
|
||||
e = e->Dprev;
|
||||
CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
|
||||
if( Marked( e->Lface )) break;
|
||||
|
||||
e->Lface->marked = GLU_TRUE;
|
||||
--size;
|
||||
e = e->Onext;
|
||||
CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
|
||||
}
|
||||
|
||||
assert( size == 0 );
|
||||
CALL_END_OR_END_DATA();
|
||||
}
|
||||
|
||||
|
||||
/************************ Boundary contour decomposition ******************/
|
||||
|
||||
/* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one
|
||||
* contour for each face marked "inside". The rendering output is
|
||||
* provided as callbacks (see the api).
|
||||
*/
|
||||
inline void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh )
|
||||
{
|
||||
GLUface *f;
|
||||
GLUhalfEdge *e;
|
||||
|
||||
for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
|
||||
if( f->inside ) {
|
||||
CALL_BEGIN_OR_BEGIN_DATA( GLU_LINE_LOOP );
|
||||
e = f->anEdge;
|
||||
do {
|
||||
CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
|
||||
e = e->Lnext;
|
||||
} while( e != f->anEdge );
|
||||
CALL_END_OR_END_DATA();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************ Quick-and-dirty decomposition ******************/
|
||||
|
||||
//#define SIGN_INCONSISTENT 2
|
||||
inline int SIGN_INCONSISTENT() {
|
||||
static const int s_value = 2;
|
||||
return s_value;
|
||||
}
|
||||
|
||||
inline/*static*/ int static_ComputeNormal( GLUtesselator *tess, GLUdouble norm[3], int check )
|
||||
/*
|
||||
* If check==GLU_FALSE, we compute the polygon normal and place it in norm[].
|
||||
* If check==GLU_TRUE, we check that each triangle in the fan from v0 has a
|
||||
* consistent orientation with respect to norm[]. If triangles are
|
||||
* consistently oriented CCW, return 1; if CW, return -1; if all triangles
|
||||
* are degenerate return 0; otherwise (no consistent orientation) return
|
||||
* SIGN_INCONSISTENT.
|
||||
*/
|
||||
{
|
||||
CachedVertex *v0 = tess->cache;
|
||||
CachedVertex *vn = v0 + tess->cacheCount;
|
||||
CachedVertex *vc;
|
||||
GLUdouble dot, xc, yc, zc, xp, yp, zp, n[3];
|
||||
int sign = 0;
|
||||
|
||||
/* Find the polygon normal. It is important to get a reasonable
|
||||
* normal even when the polygon is self-intersecting (eg. a bowtie).
|
||||
* Otherwise, the computed normal could be very tiny, but perpendicular
|
||||
* to the true plane of the polygon due to numerical noise. Then all
|
||||
* the triangles would appear to be degenerate and we would incorrectly
|
||||
* decompose the polygon as a fan (or simply not render it at all).
|
||||
*
|
||||
* We use a sum-of-triangles normal algorithm rather than the more
|
||||
* efficient sum-of-trapezoids method (used in CheckOrientation()
|
||||
* in normal.c). This lets us explicitly reverse the signed area
|
||||
* of some triangles to get a reasonable normal in the self-intersecting
|
||||
* case.
|
||||
*/
|
||||
if( ! check ) {
|
||||
norm[0] = norm[1] = norm[2] = 0.0;
|
||||
}
|
||||
|
||||
vc = v0 + 1;
|
||||
xc = vc->coords[0] - v0->coords[0];
|
||||
yc = vc->coords[1] - v0->coords[1];
|
||||
zc = vc->coords[2] - v0->coords[2];
|
||||
while( ++vc < vn ) {
|
||||
xp = xc; yp = yc; zp = zc;
|
||||
xc = vc->coords[0] - v0->coords[0];
|
||||
yc = vc->coords[1] - v0->coords[1];
|
||||
zc = vc->coords[2] - v0->coords[2];
|
||||
|
||||
/* Compute (vp - v0) cross (vc - v0) */
|
||||
n[0] = yp*zc - zp*yc;
|
||||
n[1] = zp*xc - xp*zc;
|
||||
n[2] = xp*yc - yp*xc;
|
||||
|
||||
dot = n[0]*norm[0] + n[1]*norm[1] + n[2]*norm[2];
|
||||
if( ! check ) {
|
||||
/* Reverse the contribution of back-facing triangles to get
|
||||
* a reasonable normal for self-intersecting polygons (see above)
|
||||
*/
|
||||
if( dot >= 0 ) {
|
||||
norm[0] += n[0]; norm[1] += n[1]; norm[2] += n[2];
|
||||
} else {
|
||||
norm[0] -= n[0]; norm[1] -= n[1]; norm[2] -= n[2];
|
||||
}
|
||||
} else if( dot != 0 ) {
|
||||
/* Check the new orientation for consistency with previous triangles */
|
||||
if( dot > 0 ) {
|
||||
if( sign < 0 ) return SIGN_INCONSISTENT();
|
||||
sign = 1;
|
||||
} else {
|
||||
if( sign > 0 ) return SIGN_INCONSISTENT();
|
||||
sign = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sign;
|
||||
}
|
||||
|
||||
/* __gl_renderCache( tess ) takes a single contour and tries to render it
|
||||
* as a triangle fan. This handles convex polygons, as well as some
|
||||
* non-convex polygons if we get lucky.
|
||||
*
|
||||
* Returns GLU_TRUE if the polygon was successfully rendered. The rendering
|
||||
* output is provided as callbacks (see the api).
|
||||
*/
|
||||
inline GLUboolean __gl_renderCache( GLUtesselator *tess )
|
||||
{
|
||||
CachedVertex *v0 = tess->cache;
|
||||
CachedVertex *vn = v0 + tess->cacheCount;
|
||||
CachedVertex *vc;
|
||||
GLUdouble norm[3];
|
||||
int sign;
|
||||
|
||||
if( tess->cacheCount < 3 ) {
|
||||
/* Degenerate contour -- no output */
|
||||
return GLU_TRUE;
|
||||
}
|
||||
|
||||
norm[0] = tess->normal[0];
|
||||
norm[1] = tess->normal[1];
|
||||
norm[2] = tess->normal[2];
|
||||
if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
|
||||
static_ComputeNormal( tess, norm, GLU_FALSE );
|
||||
}
|
||||
|
||||
sign = static_ComputeNormal( tess, norm, GLU_TRUE );
|
||||
if( sign == SIGN_INCONSISTENT() ) {
|
||||
/* Fan triangles did not have a consistent orientation */
|
||||
return GLU_FALSE;
|
||||
}
|
||||
if( sign == 0 ) {
|
||||
/* All triangles were degenerate */
|
||||
return GLU_TRUE;
|
||||
}
|
||||
|
||||
/* Make sure we do the right thing for each winding rule */
|
||||
switch( tess->windingRule ) {
|
||||
case GLU_TESS_WINDING_ODD:
|
||||
case GLU_TESS_WINDING_NONZERO:
|
||||
break;
|
||||
case GLU_TESS_WINDING_POSITIVE:
|
||||
if( sign < 0 ) return GLU_TRUE;
|
||||
break;
|
||||
case GLU_TESS_WINDING_NEGATIVE:
|
||||
if( sign > 0 ) return GLU_TRUE;
|
||||
break;
|
||||
case GLU_TESS_WINDING_ABS_GEQ_TWO:
|
||||
return GLU_TRUE;
|
||||
}
|
||||
|
||||
CALL_BEGIN_OR_BEGIN_DATA( tess->boundaryOnly ? GLU_LINE_LOOP
|
||||
: (tess->cacheCount > 3) ? GLU_TRIANGLE_FAN
|
||||
: GLU_TRIANGLES );
|
||||
|
||||
CALL_VERTEX_OR_VERTEX_DATA( v0->data );
|
||||
if( sign > 0 ) {
|
||||
for( vc = v0+1; vc < vn; ++vc ) {
|
||||
CALL_VERTEX_OR_VERTEX_DATA( vc->data );
|
||||
}
|
||||
} else {
|
||||
for( vc = vn-1; vc > v0; --vc ) {
|
||||
CALL_VERTEX_OR_VERTEX_DATA( vc->data );
|
||||
}
|
||||
}
|
||||
CALL_END_OR_END_DATA();
|
||||
return GLU_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,203 @@
|
||||
// see license file for original license.
|
||||
|
||||
#ifndef tools_glutess_tessmono
|
||||
#define tools_glutess_tessmono
|
||||
|
||||
/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region
|
||||
* (what else would it do??) The region must consist of a single
|
||||
* loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this
|
||||
* case means that any vertical line intersects the interior of the
|
||||
* region in a single interval.
|
||||
*
|
||||
* Tessellation consists of adding interior edges (actually pairs of
|
||||
* half-edges), to split the region into non-overlapping triangles.
|
||||
*
|
||||
* __gl_meshTessellateInterior( mesh ) tessellates each region of
|
||||
* the mesh which is marked "inside" the polygon. Each such region
|
||||
* must be monotone.
|
||||
*
|
||||
* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces
|
||||
* which are not marked "inside" the polygon. Since further mesh operations
|
||||
* on NULL faces are not allowed, the main purpose is to clean up the
|
||||
* mesh so that exterior loops are not represented in the data structure.
|
||||
*
|
||||
* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the
|
||||
* winding numbers on all edges so that regions marked "inside" the
|
||||
* polygon have a winding number of "value", and regions outside
|
||||
* have a winding number of 0.
|
||||
*
|
||||
* If keepOnlyBoundary is GLU_TRUE, it also deletes all edges which do not
|
||||
* separate an interior region from an exterior one.
|
||||
*/
|
||||
|
||||
//int __gl_meshTessellateMonoRegion( GLUface *face );
|
||||
//int __gl_meshTessellateInterior( GLUmesh *mesh );
|
||||
//void __gl_meshDiscardExterior( GLUmesh *mesh );
|
||||
//int __gl_meshSetWindingNumber( GLUmesh *mesh, int value,
|
||||
// GLUboolean keepOnlyBoundary );
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
/// inlined C code : ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
#include "geom"
|
||||
#include "mesh"
|
||||
|
||||
/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region
|
||||
* (what else would it do??) The region must consist of a single
|
||||
* loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this
|
||||
* case means that any vertical line intersects the interior of the
|
||||
* region in a single interval.
|
||||
*
|
||||
* Tessellation consists of adding interior edges (actually pairs of
|
||||
* half-edges), to split the region into non-overlapping triangles.
|
||||
*
|
||||
* The basic idea is explained in Preparata and Shamos (which I don''t
|
||||
* have handy right now), although their implementation is more
|
||||
* complicated than this one. The are two edge chains, an upper chain
|
||||
* and a lower chain. We process all vertices from both chains in order,
|
||||
* from right to left.
|
||||
*
|
||||
* The algorithm ensures that the following invariant holds after each
|
||||
* vertex is processed: the untessellated region consists of two
|
||||
* chains, where one chain (say the upper) is a single edge, and
|
||||
* the other chain is concave. The left vertex of the single edge
|
||||
* is always to the left of all vertices in the concave chain.
|
||||
*
|
||||
* Each step consists of adding the rightmost unprocessed vertex to one
|
||||
* of the two chains, and forming a fan of triangles from the rightmost
|
||||
* of two chain endpoints. Determining whether we can add each triangle
|
||||
* to the fan is a simple orientation test. By making the fan as large
|
||||
* as possible, we restore the invariant (check it yourself).
|
||||
*/
|
||||
inline int __gl_meshTessellateMonoRegion( GLUface *face )
|
||||
{
|
||||
GLUhalfEdge *up, *lo;
|
||||
|
||||
/* All edges are oriented CCW around the boundary of the region.
|
||||
* First, find the half-edge whose origin vertex is rightmost.
|
||||
* Since the sweep goes from left to right, face->anEdge should
|
||||
* be close to the edge we want.
|
||||
*/
|
||||
up = face->anEdge;
|
||||
assert( up->Lnext != up && up->Lnext->Lnext != up );
|
||||
|
||||
for( ; VertLeq( up->Dst, up->Org ); up = up->Lprev )
|
||||
;
|
||||
for( ; VertLeq( up->Org, up->Dst ); up = up->Lnext )
|
||||
;
|
||||
lo = up->Lprev;
|
||||
|
||||
while( up->Lnext != lo ) {
|
||||
if( VertLeq( up->Dst, lo->Org )) {
|
||||
/* up->Dst is on the left. It is safe to form triangles from lo->Org.
|
||||
* The EdgeGoesLeft test guarantees progress even when some triangles
|
||||
* are CW, given that the upper and lower chains are truly monotone.
|
||||
*/
|
||||
while( lo->Lnext != up && (EdgeGoesLeft( lo->Lnext )
|
||||
|| EdgeSign( lo->Org, lo->Dst, lo->Lnext->Dst ) <= 0 )) {
|
||||
GLUhalfEdge *tempHalfEdge= __gl_meshConnect( lo->Lnext, lo );
|
||||
if (tempHalfEdge == NULL) return 0;
|
||||
lo = tempHalfEdge->Sym;
|
||||
}
|
||||
lo = lo->Lprev;
|
||||
} else {
|
||||
/* lo->Org is on the left. We can make CCW triangles from up->Dst. */
|
||||
while( lo->Lnext != up && (EdgeGoesRight( up->Lprev )
|
||||
|| EdgeSign( up->Dst, up->Org, up->Lprev->Org ) >= 0 )) {
|
||||
GLUhalfEdge *tempHalfEdge= __gl_meshConnect( up, up->Lprev );
|
||||
if (tempHalfEdge == NULL) return 0;
|
||||
up = tempHalfEdge->Sym;
|
||||
}
|
||||
up = up->Lnext;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now lo->Org == up->Dst == the leftmost vertex. The remaining region
|
||||
* can be tessellated in a fan from this leftmost vertex.
|
||||
*/
|
||||
assert( lo->Lnext != up );
|
||||
while( lo->Lnext->Lnext != up ) {
|
||||
GLUhalfEdge *tempHalfEdge= __gl_meshConnect( lo->Lnext, lo );
|
||||
if (tempHalfEdge == NULL) return 0;
|
||||
lo = tempHalfEdge->Sym;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* __gl_meshTessellateInterior( mesh ) tessellates each region of
|
||||
* the mesh which is marked "inside" the polygon. Each such region
|
||||
* must be monotone.
|
||||
*/
|
||||
inline int __gl_meshTessellateInterior( GLUmesh *mesh )
|
||||
{
|
||||
GLUface *f, *next;
|
||||
|
||||
/*LINTED*/
|
||||
for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) {
|
||||
/* Make sure we don''t try to tessellate the new triangles. */
|
||||
next = f->next;
|
||||
if( f->inside ) {
|
||||
if ( !__gl_meshTessellateMonoRegion( f ) ) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces
|
||||
* which are not marked "inside" the polygon. Since further mesh operations
|
||||
* on NULL faces are not allowed, the main purpose is to clean up the
|
||||
* mesh so that exterior loops are not represented in the data structure.
|
||||
*/
|
||||
inline void __gl_meshDiscardExterior( GLUmesh *mesh )
|
||||
{
|
||||
GLUface *f, *next;
|
||||
|
||||
/*LINTED*/
|
||||
for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) {
|
||||
/* Since f will be destroyed, save its next pointer. */
|
||||
next = f->next;
|
||||
if( ! f->inside ) {
|
||||
__gl_meshZapFace( f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#define MARKED_FOR_DELETION 0x7fffffff
|
||||
|
||||
/* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the
|
||||
* winding numbers on all edges so that regions marked "inside" the
|
||||
* polygon have a winding number of "value", and regions outside
|
||||
* have a winding number of 0.
|
||||
*
|
||||
* If keepOnlyBoundary is GLU_TRUE, it also deletes all edges which do not
|
||||
* separate an interior region from an exterior one.
|
||||
*/
|
||||
inline int __gl_meshSetWindingNumber( GLUmesh *mesh, int value,
|
||||
GLUboolean keepOnlyBoundary )
|
||||
{
|
||||
GLUhalfEdge *e, *eNext;
|
||||
|
||||
for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) {
|
||||
eNext = e->next;
|
||||
if( e->Rface->inside != e->Lface->inside ) {
|
||||
|
||||
/* This is a boundary edge (one side is interior, one is exterior). */
|
||||
e->winding = (e->Lface->inside) ? value : -value;
|
||||
} else {
|
||||
|
||||
/* Both regions are interior, or both are exterior. */
|
||||
if( ! keepOnlyBoundary ) {
|
||||
e->winding = 0;
|
||||
} else {
|
||||
if ( !__gl_meshDelete( e ) ) return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,231 @@
|
||||
#ifndef tools_glutess_undef
|
||||
#define tools_glutess_undef
|
||||
|
||||
#undef GLU_TESS_MAX_CACHE
|
||||
#undef CALL_BEGIN_OR_BEGIN_DATA
|
||||
#undef CALL_VERTEX_OR_VERTEX_DATA
|
||||
#undef CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA
|
||||
#undef CALL_END_OR_END_DATA
|
||||
#undef CALL_COMBINE_OR_COMBINE_DATA
|
||||
#undef CALL_ERROR_OR_ERROR_DATA
|
||||
#undef __gl_dictListDelete
|
||||
#undef __gl_dictListDeleteDict
|
||||
#undef __gl_dictListInsertBefore
|
||||
#undef __gl_dictListNewDict
|
||||
#undef __gl_dictListSearch
|
||||
#undef DictKey
|
||||
#undef Dict
|
||||
#undef DictNode
|
||||
#undef dictNewDict
|
||||
#undef dictDeleteDict
|
||||
#undef dictSearch
|
||||
#undef dictInsert
|
||||
#undef dictInsertBefore
|
||||
#undef dictDelete
|
||||
#undef dictKey
|
||||
#undef dictSucc
|
||||
#undef dictPred
|
||||
#undef dictMin
|
||||
#undef dictMax
|
||||
#undef __gl_dictListKey
|
||||
#undef __gl_dictListSucc
|
||||
#undef __gl_dictListPred
|
||||
#undef __gl_dictListMin
|
||||
#undef __gl_dictListMax
|
||||
#undef __gl_dictListInsert
|
||||
#undef VertEq
|
||||
#undef VertLeq
|
||||
#undef EdgeEval
|
||||
#undef EdgeSign
|
||||
#undef TransLeq
|
||||
#undef TransEval
|
||||
#undef TransSign
|
||||
#undef EdgeGoesLeft
|
||||
#undef EdgeGoesRight
|
||||
#undef VertL1dist
|
||||
#undef VertCCW
|
||||
#undef VertLeq
|
||||
#undef Interpolate
|
||||
#undef Swap
|
||||
#undef GLUAPI
|
||||
/*
|
||||
#undef GLUAPIENTRY
|
||||
#undef GLU_TESS_BEGIN_DATA
|
||||
#undef GLU_TESS_VERTEX_DATA
|
||||
#undef GLU_TESS_END_DATA
|
||||
#undef GLU_TESS_ERROR_DATA
|
||||
#undef GLU_TESS_COMBINE_DATA
|
||||
#undef GLU_TESS_WINDING_RULE
|
||||
#undef GLU_TESS_WINDING_ODD
|
||||
#undef GLU_TESS_WINDING_POSITIVE
|
||||
#undef GLU_TESS_WINDING_NEGATIVE
|
||||
*/
|
||||
#undef GLU_MIN
|
||||
#undef GLU_MAX
|
||||
#undef GLU_ABS
|
||||
#undef GLU_FALSE
|
||||
#undef GLU_TRUE
|
||||
#undef GLU_LINE_LOOP
|
||||
#undef GLU_TRIANGLES
|
||||
#undef GLU_TRIANGLE_STRIP
|
||||
#undef GLU_TRIANGLE_FAN
|
||||
#undef GLU_TESS_MAX_COORD
|
||||
#undef GLU_INVALID_ENUM
|
||||
#undef GLU_INVALID_VALUE
|
||||
#undef GLU_OUT_OF_MEMORY
|
||||
#undef GLU_INCOMPATIBLE_GL_VERSION
|
||||
#undef GLU_INVALID_OPERATION
|
||||
#undef GLU_TESS_BEGIN
|
||||
#undef GLU_TESS_VERTEX
|
||||
#undef GLU_TESS_END
|
||||
#undef GLU_TESS_ERROR
|
||||
#undef GLU_TESS_EDGE_FLAG
|
||||
#undef GLU_EDGE_FLAG
|
||||
#undef GLU_TESS_COMBINE
|
||||
#undef GLU_TESS_EDGE_FLAG_DATA
|
||||
#undef GLU_CW
|
||||
#undef GLU_CCW
|
||||
#undef GLU_INTERIOR
|
||||
#undef GLU_EXTERIOR
|
||||
#undef GLU_UNKNOWN
|
||||
#undef GLU_TESS_BOUNDARY_ONLY
|
||||
#undef GLU_TESS_TOLERANCE
|
||||
#undef GLU_TESS_ERROR1
|
||||
#undef GLU_TESS_ERROR2
|
||||
#undef GLU_TESS_ERROR3
|
||||
#undef GLU_TESS_ERROR4
|
||||
#undef GLU_TESS_ERROR5
|
||||
#undef GLU_TESS_ERROR6
|
||||
#undef GLU_TESS_ERROR7
|
||||
#undef GLU_TESS_ERROR8
|
||||
#undef GLU_TESS_MISSING_BEGIN_POLYGON
|
||||
#undef GLU_TESS_MISSING_BEGIN_CONTOUR
|
||||
#undef GLU_TESS_MISSING_END_POLYGON
|
||||
#undef GLU_TESS_MISSING_END_CONTOUR
|
||||
#undef GLU_TESS_COORD_TOO_LARGE
|
||||
#undef GLU_TESS_NEED_COMBINE_CALLBACK
|
||||
#undef GLU_TESS_WINDING_NONZERO
|
||||
#undef GLU_TESS_WINDING_ABS_GEQ_TWO
|
||||
#undef memAlloc
|
||||
#undef memRealloc
|
||||
#undef memFree
|
||||
#undef memInit
|
||||
#undef Rface
|
||||
#undef Dst
|
||||
#undef Oprev
|
||||
#undef Lprev
|
||||
#undef Dprev
|
||||
#undef Rprev
|
||||
#undef Dnext
|
||||
#undef Rnext
|
||||
#undef Dot
|
||||
#undef S_UNIT_X
|
||||
#undef S_UNIT_Y
|
||||
#undef PQkey
|
||||
#undef PQhandle
|
||||
#undef PriorityQ
|
||||
#undef pqNewPriorityQ
|
||||
#undef pqDeletePriorityQ
|
||||
#undef pqInit
|
||||
#undef pqInsert
|
||||
#undef pqMinimum
|
||||
#undef pqExtractMin
|
||||
#undef pqDelete
|
||||
#undef pqIsEmpty
|
||||
#undef __gl_pqHeapMinimum
|
||||
#undef __gl_pqHeapIsEmpty
|
||||
#undef LEQ
|
||||
#undef PQkey
|
||||
#undef PQhandle
|
||||
#undef PriorityQ
|
||||
#undef pqNewPriorityQ
|
||||
#undef pqDeletePriorityQ
|
||||
#undef pqInit
|
||||
#undef pqInsert
|
||||
#undef pqMinimum
|
||||
#undef pqExtractMin
|
||||
#undef pqDelete
|
||||
#undef pqIsEmpty
|
||||
#undef LT
|
||||
#undef GT
|
||||
#undef pq_Swap
|
||||
//#undef gluTessBeginContour
|
||||
//#undef gluTessBeginPolygon
|
||||
//#undef gluTessCallback
|
||||
//#undef gluTessEndContour
|
||||
//#undef gluTessEndPolygon
|
||||
//#undef gluTessNormal
|
||||
//#undef gluTessProperty
|
||||
//#undef gluTessVertex
|
||||
//#undef gluBeginPolygon
|
||||
//#undef gluDeleteTess
|
||||
//#undef gluEndPolygon
|
||||
//#undef gluGetTessProperty
|
||||
//#undef gluNewTess
|
||||
//#undef gluNextContour
|
||||
#undef __gl_computeInterior
|
||||
#undef __gl_dictListDelete
|
||||
#undef __gl_dictListDeleteDict
|
||||
#undef __gl_dictListInsertBefore
|
||||
#undef __gl_dictListNewDict
|
||||
#undef __gl_dictListSearch
|
||||
#undef __gl_edgeEval
|
||||
#undef __gl_edgeIntersect
|
||||
#undef __gl_edgeSign
|
||||
#undef __gl_memInit
|
||||
#undef __gl_meshAddEdgeVertex
|
||||
#undef __gl_meshCheckMesh
|
||||
#undef __gl_meshConnect
|
||||
#undef __gl_meshDelete
|
||||
#undef __gl_meshDeleteMesh
|
||||
#undef __gl_meshDiscardExterior
|
||||
#undef __gl_meshMakeEdge
|
||||
#undef __gl_meshNewMesh
|
||||
#undef __gl_meshSetWindingNumber
|
||||
#undef __gl_meshSplice
|
||||
#undef __gl_meshSplitEdge
|
||||
#undef __gl_meshTessellateInterior
|
||||
#undef __gl_meshTessellateMonoRegion
|
||||
#undef __gl_meshUnion
|
||||
#undef __gl_meshZapFace
|
||||
#undef __gl_noBeginData
|
||||
#undef __gl_noCombineData
|
||||
#undef __gl_noEdgeFlagData
|
||||
#undef __gl_noEndData
|
||||
#undef __gl_noErrorData
|
||||
#undef __gl_noVertexData
|
||||
#undef __gl_pqHeapDelete
|
||||
#undef __gl_pqHeapDeletePriorityQ
|
||||
#undef __gl_pqHeapExtractMin
|
||||
#undef __gl_pqHeapInit
|
||||
#undef __gl_pqHeapInsert
|
||||
#undef __gl_pqHeapNewPriorityQ
|
||||
#undef __gl_pqSortDelete
|
||||
#undef __gl_pqSortDeletePriorityQ
|
||||
#undef __gl_pqSortExtractMin
|
||||
#undef __gl_pqSortInit
|
||||
#undef __gl_pqSortInsert
|
||||
#undef __gl_pqSortIsEmpty
|
||||
#undef __gl_pqSortMinimum
|
||||
#undef __gl_pqSortNewPriorityQ
|
||||
#undef __gl_projectPolygon
|
||||
#undef __gl_renderBoundary
|
||||
#undef __gl_renderCache
|
||||
#undef __gl_renderMesh
|
||||
#undef __gl_transEval
|
||||
#undef __gl_transSign
|
||||
#undef __gl_vertCCW
|
||||
#undef __gl_vertLeq
|
||||
#undef Marked
|
||||
#undef AddToTrail
|
||||
#undef FreeTrail
|
||||
#undef IsEven
|
||||
#undef RegionBelow
|
||||
#undef RegionAbove
|
||||
#undef DebugEvent
|
||||
#undef AddWinding
|
||||
#undef GLU_TESS_DEFAULT_TOLERANCE
|
||||
#undef GLU_TESS_MESH
|
||||
#undef RequireState
|
||||
|
||||
#endif
|
||||
@@ -1,107 +0,0 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_gzip_buffer
|
||||
#define tools_gzip_buffer
|
||||
|
||||
// what is needed for root file compression with zlib.
|
||||
|
||||
// The gzip library is libz.
|
||||
// Someone must not confuse zlib with zip.
|
||||
// In particular to use zip someone has to
|
||||
// link to -lz that contains inflate, deflate.
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace tools {
|
||||
|
||||
inline bool gzip_buffer(std::ostream& a_out,
|
||||
unsigned int a_level,
|
||||
unsigned int a_srcsize,const char* a_src,
|
||||
unsigned int a_tgtsize,char* a_tgt,
|
||||
unsigned int& a_irep) {
|
||||
|
||||
z_stream stream; // decompression stream
|
||||
|
||||
stream.next_in = (Bytef*)(a_src);
|
||||
stream.avail_in = (uInt)(a_srcsize);
|
||||
stream.next_out = (Bytef*)a_tgt;
|
||||
stream.avail_out = (uInt)(a_tgtsize);
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
int err = deflateInit(&stream,a_level);
|
||||
if(err!=Z_OK) {
|
||||
a_out << "tools::wroot::zip :"
|
||||
<< " error in zlib/deflateInit." << std::endl;
|
||||
a_irep = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if(err!=Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
a_out << "tools::wroot::zip :"
|
||||
<< " error in zlib/deflate." << std::endl;
|
||||
a_irep = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
deflateEnd(&stream);
|
||||
|
||||
//a_out << "tools::gzip_buffer : ok "
|
||||
// << stream.total_out << std::endl;
|
||||
|
||||
a_irep = stream.total_out;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool gunzip_buffer(std::ostream& a_out,
|
||||
unsigned int a_srcsize,const char* a_src,
|
||||
unsigned int a_tgtsize,char* a_tgt,
|
||||
unsigned int& a_irep) {
|
||||
|
||||
z_stream stream; // decompression stream
|
||||
|
||||
stream.next_in = (Bytef*)(a_src);
|
||||
stream.avail_in = (uInt)(a_srcsize);
|
||||
stream.next_out = (Bytef*)a_tgt;
|
||||
stream.avail_out = (uInt)(a_tgtsize);
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
int err = inflateInit(&stream);
|
||||
if (err != Z_OK) {
|
||||
a_out << "tools::gunzip_buffer :"
|
||||
<< " error " << err << " in zlib/inflateInit." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
inflateEnd(&stream);
|
||||
a_out << "tools::gunzip_buffer :"
|
||||
<< " error " << err << " in zlib/inflate." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
inflateEnd(&stream);
|
||||
|
||||
//a_out << "tools::gunzip_buffer : zlib : ok "
|
||||
// << stream.total_out << std::endl;
|
||||
|
||||
a_irep = stream.total_out;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//exlib_build_use inlib zlib
|
||||
@@ -6,9 +6,6 @@
|
||||
|
||||
// A C interface to HBOOK.
|
||||
|
||||
// It is done in way that limits the number of #define.
|
||||
// Only two remains for WIN32.
|
||||
|
||||
#ifdef WIN32
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
SUBROUTINE OCLOSE(IUNIT)
|
||||
IMPLICIT NONE
|
||||
INTEGER IUNIT
|
||||
CLOSE(IUNIT)
|
||||
RETURN
|
||||
END
|
||||
@@ -1,9 +0,0 @@
|
||||
INTEGER*4 FUNCTION SETNTUC()
|
||||
INTEGER NNTUC
|
||||
PARAMETER (NNTUC = 200)
|
||||
INTEGER*4 NVAR,P
|
||||
COMMON /NTUC/ NVAR,P(NNTUC)
|
||||
NVAR = 0
|
||||
SETNTUC = NNTUC
|
||||
RETURN
|
||||
END
|
||||
@@ -1,10 +0,0 @@
|
||||
INTEGER*4 FUNCTION SETPAWC()
|
||||
INTEGER NPAWC
|
||||
PARAMETER (NPAWC = 1000000)
|
||||
INTEGER P
|
||||
COMMON /PAWC/ P(NPAWC)
|
||||
INTEGER IQUEST
|
||||
COMMON/QUEST/IQUEST(100)
|
||||
SETPAWC = NPAWC
|
||||
RETURN
|
||||
END
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <tools/sto>
|
||||
#include <tools/scast>
|
||||
#include <tools/stype>
|
||||
#include <tools/sout>
|
||||
#include <tools/num2s>
|
||||
#include <tools/ntuple_booking>
|
||||
|
||||
#include "CHBOOK"
|
||||
@@ -144,7 +146,7 @@ public:
|
||||
if(tools::find_named<icol>(m_cols,a_name)) return 0;
|
||||
|
||||
std::string block("blk"); //8 chars max.
|
||||
block += tools::to<unsigned int>(m_cols.size());
|
||||
if(!tools::numas<unsigned int>(m_cols.size(),block)){}
|
||||
if(block.size()>8) return 0;
|
||||
|
||||
column<T>* col = new column<T>(a_name);
|
||||
|
||||
@@ -0,0 +1,728 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_hershey
|
||||
#define tools_hershey
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// drawn fonts comming from CERNLIB ! A long story now. //////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace tools {
|
||||
|
||||
class hershey {
|
||||
private:
|
||||
enum {
|
||||
H_ROMAN = 1,
|
||||
H_DIGIT = 2,
|
||||
H_MATH = 3,
|
||||
H_SPECIAL = 4,
|
||||
H_GREEK = 5,
|
||||
H_UPPER = 1,
|
||||
H_LOWER = 2,
|
||||
H_NBITMX = 30
|
||||
};
|
||||
public:
|
||||
|
||||
static unsigned int max_poly() { return 8;} //font special reaches 8
|
||||
static unsigned int max_point() {return 160;} // 40 * 4
|
||||
|
||||
static void special_char_points(char a_char,float a_scale, //input
|
||||
int& a_number,int* a_mx_point,
|
||||
float* aX,float* aY,float& a_width){
|
||||
// PAW special characters.
|
||||
extract(H_SPECIAL,
|
||||
H_UPPER,a_char,a_scale,a_number,a_mx_point,aX,aY,a_width);
|
||||
}
|
||||
|
||||
static void latin_char_points(char a_char,float a_scale, //input
|
||||
int& a_number,int* a_mx_point,
|
||||
float* aX,float* aY,float& a_width){
|
||||
|
||||
// Latin correspondance with HPLSOF
|
||||
// ABCDEFGHIJKLMNOPQRSTUVWXYZ done with H_ROMAN UPPER
|
||||
// abcdefghijklmnopqrstuvwxyz done with H_ROMAN LOWER
|
||||
// 0123456789 done with H_DIGIT
|
||||
// .,/()-+=* done with H_MATH
|
||||
// $!#>?:;<[]{}%& done with H_SPECIAL
|
||||
|
||||
switch(a_char) {
|
||||
case 'A':extract(H_ROMAN,H_UPPER,'A',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'B':extract(H_ROMAN,H_UPPER,'B',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'C':extract(H_ROMAN,H_UPPER,'C',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'D':extract(H_ROMAN,H_UPPER,'D',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'E':extract(H_ROMAN,H_UPPER,'E',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'F':extract(H_ROMAN,H_UPPER,'F',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'G':extract(H_ROMAN,H_UPPER,'G',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'H':extract(H_ROMAN,H_UPPER,'H',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'I':extract(H_ROMAN,H_UPPER,'I',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'J':extract(H_ROMAN,H_UPPER,'J',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'K':extract(H_ROMAN,H_UPPER,'K',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'L':extract(H_ROMAN,H_UPPER,'L',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'M':extract(H_ROMAN,H_UPPER,'M',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'N':extract(H_ROMAN,H_UPPER,'N',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'O':extract(H_ROMAN,H_UPPER,'O',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'P':extract(H_ROMAN,H_UPPER,'P',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'Q':extract(H_ROMAN,H_UPPER,'Q',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'R':extract(H_ROMAN,H_UPPER,'R',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'S':extract(H_ROMAN,H_UPPER,'S',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'T':extract(H_ROMAN,H_UPPER,'T',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'U':extract(H_ROMAN,H_UPPER,'U',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'V':extract(H_ROMAN,H_UPPER,'V',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'W':extract(H_ROMAN,H_UPPER,'W',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'X':extract(H_ROMAN,H_UPPER,'X',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'Y':extract(H_ROMAN,H_UPPER,'Y',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'Z':extract(H_ROMAN,H_UPPER,'Z',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
|
||||
case 'a':extract(H_ROMAN,H_LOWER,'A',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'b':extract(H_ROMAN,H_LOWER,'B',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'c':extract(H_ROMAN,H_LOWER,'C',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'd':extract(H_ROMAN,H_LOWER,'D',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'e':extract(H_ROMAN,H_LOWER,'E',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'f':extract(H_ROMAN,H_LOWER,'F',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'g':extract(H_ROMAN,H_LOWER,'G',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'h':extract(H_ROMAN,H_LOWER,'H',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'i':extract(H_ROMAN,H_LOWER,'I',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'j':extract(H_ROMAN,H_LOWER,'J',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'k':extract(H_ROMAN,H_LOWER,'K',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'l':extract(H_ROMAN,H_LOWER,'L',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'm':extract(H_ROMAN,H_LOWER,'M',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'n':extract(H_ROMAN,H_LOWER,'N',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'o':extract(H_ROMAN,H_LOWER,'O',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'p':extract(H_ROMAN,H_LOWER,'P',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'q':extract(H_ROMAN,H_LOWER,'Q',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'r':extract(H_ROMAN,H_LOWER,'R',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 's':extract(H_ROMAN,H_LOWER,'S',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 't':extract(H_ROMAN,H_LOWER,'T',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'u':extract(H_ROMAN,H_LOWER,'U',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'v':extract(H_ROMAN,H_LOWER,'V',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'w':extract(H_ROMAN,H_LOWER,'W',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'x':extract(H_ROMAN,H_LOWER,'X',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'y':extract(H_ROMAN,H_LOWER,'Y',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'z':extract(H_ROMAN,H_LOWER,'Z',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
|
||||
case '0':extract(H_DIGIT,H_UPPER,'0',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '1':extract(H_DIGIT,H_UPPER,'1',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '2':extract(H_DIGIT,H_UPPER,'2',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '3':extract(H_DIGIT,H_UPPER,'3',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '4':extract(H_DIGIT,H_UPPER,'4',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '5':extract(H_DIGIT,H_UPPER,'5',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '6':extract(H_DIGIT,H_UPPER,'6',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '7':extract(H_DIGIT,H_UPPER,'7',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '8':extract(H_DIGIT,H_UPPER,'8',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '9':extract(H_DIGIT,H_UPPER,'9',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
|
||||
case '.':extract(H_MATH,H_UPPER,'.',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case ',':extract(H_MATH,H_UPPER,',',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '/':extract(H_MATH,H_UPPER,'/',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '(':extract(H_MATH,H_UPPER,'(',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case ')':extract(H_MATH,H_UPPER,')',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '-':extract(H_MATH,H_UPPER,'-',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '+':extract(H_MATH,H_UPPER,'+',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '=':extract(H_MATH,H_UPPER,'=',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '*':extract(H_MATH,H_UPPER,'*',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
|
||||
case '$':extract(H_SPECIAL,H_UPPER,'D',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '!':extract(H_SPECIAL,H_UPPER,'E',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '#':extract(H_SPECIAL,H_UPPER,'F',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '>':extract(H_SPECIAL,H_UPPER,'G',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '?':extract(H_SPECIAL,H_UPPER,'H',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case ':':extract(H_SPECIAL,H_UPPER,'J',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case ';':extract(H_SPECIAL,H_UPPER,'K',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '<':extract(H_SPECIAL,H_UPPER,'L',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '[':extract(H_SPECIAL,H_UPPER,'M',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case ']':extract(H_SPECIAL,H_UPPER,'N',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '{':extract(H_SPECIAL,H_UPPER,'P',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '}':extract(H_SPECIAL,H_UPPER,'Q',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '%':extract(H_SPECIAL,H_UPPER,'Y',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case '&':extract(H_SPECIAL,H_UPPER,'W',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
|
||||
case '_':
|
||||
a_number = 1;
|
||||
a_mx_point[0] = 2;
|
||||
aX[0] = 0;
|
||||
aY[0] = 0;
|
||||
aX[1] = a_scale;
|
||||
aY[1] = 0;
|
||||
a_width = a_scale;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
a_number = 0;
|
||||
a_width = a_scale/2;
|
||||
break;
|
||||
|
||||
default :
|
||||
a_number = 0;
|
||||
a_width = a_scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void greek_char_points(char a_char,float a_scale, //input
|
||||
int& a_number,int* a_mx_point,
|
||||
float* aX,float* aY,float& a_width){
|
||||
switch(a_char) {
|
||||
case 'A':extract(H_GREEK,H_UPPER,'A',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'B':extract(H_GREEK,H_UPPER,'B',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'C':extract(H_GREEK,H_UPPER,'C',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'D':extract(H_GREEK,H_UPPER,'D',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'E':extract(H_GREEK,H_UPPER,'E',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'F':extract(H_GREEK,H_UPPER,'F',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'G':extract(H_GREEK,H_UPPER,'G',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'H':extract(H_GREEK,H_UPPER,'H',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'I':extract(H_GREEK,H_UPPER,'I',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'J':extract(H_GREEK,H_UPPER,'J',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'K':extract(H_GREEK,H_UPPER,'K',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'L':extract(H_GREEK,H_UPPER,'L',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'M':extract(H_GREEK,H_UPPER,'M',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'N':extract(H_GREEK,H_UPPER,'N',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'O':extract(H_GREEK,H_UPPER,'O',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'P':extract(H_GREEK,H_UPPER,'P',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'Q':extract(H_GREEK,H_UPPER,'Q',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'R':extract(H_GREEK,H_UPPER,'R',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'S':extract(H_GREEK,H_UPPER,'S',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'T':extract(H_GREEK,H_UPPER,'T',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'U':extract(H_GREEK,H_UPPER,'U',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'V':extract(H_GREEK,H_UPPER,'V',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'W':extract(H_GREEK,H_UPPER,'W',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'X':extract(H_GREEK,H_UPPER,'X',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'Y':extract(H_GREEK,H_UPPER,'Y',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'Z':extract(H_GREEK,H_UPPER,'Z',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
|
||||
case 'a':extract(H_GREEK,H_LOWER,'A',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'b':extract(H_GREEK,H_LOWER,'B',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'c':extract(H_GREEK,H_LOWER,'C',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'd':extract(H_GREEK,H_LOWER,'D',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'e':extract(H_GREEK,H_LOWER,'E',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'f':extract(H_GREEK,H_LOWER,'F',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'g':extract(H_GREEK,H_LOWER,'G',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'h':extract(H_GREEK,H_LOWER,'H',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'i':extract(H_GREEK,H_LOWER,'I',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'j':extract(H_GREEK,H_LOWER,'J',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'k':extract(H_GREEK,H_LOWER,'K',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'l':extract(H_GREEK,H_LOWER,'L',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'm':extract(H_GREEK,H_LOWER,'M',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'n':extract(H_GREEK,H_LOWER,'N',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'o':extract(H_GREEK,H_LOWER,'O',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'p':extract(H_GREEK,H_LOWER,'P',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'q':extract(H_GREEK,H_LOWER,'Q',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'r':extract(H_GREEK,H_LOWER,'R',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 's':extract(H_GREEK,H_LOWER,'S',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 't':extract(H_GREEK,H_LOWER,'T',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'u':extract(H_GREEK,H_LOWER,'U',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'v':extract(H_GREEK,H_LOWER,'V',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'w':extract(H_GREEK,H_LOWER,'W',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'x':extract(H_GREEK,H_LOWER,'X',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'y':extract(H_GREEK,H_LOWER,'Y',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
case 'z':extract(H_GREEK,H_LOWER,'Z',a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
|
||||
default : latin_char_points(a_char,a_scale,a_number,a_mx_point,aX,aY,a_width);break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void extract(int aType,int aCase,char aC,float a_scale, //input
|
||||
int& aN,int* a_mx_point,
|
||||
float* aX,float* aY,float& a_width){
|
||||
int count;
|
||||
int npoly,ichr,iw,idif,ibit,kx,ky,iy0,ix0,dky,ipoint;
|
||||
float scale,size;
|
||||
float max_x;
|
||||
|
||||
ichr = 1;
|
||||
if (aType==H_DIGIT) {
|
||||
switch(aC) {
|
||||
case '0':ichr= 1;break;
|
||||
case '1':ichr= 2;break;
|
||||
case '2':ichr= 3;break;
|
||||
case '3':ichr= 4;break;
|
||||
case '4':ichr= 5;break;
|
||||
case '5':ichr= 6;break;
|
||||
case '6':ichr= 7;break;
|
||||
case '7':ichr= 8;break;
|
||||
case '8':ichr= 9;break;
|
||||
case '9':ichr=10;break;
|
||||
}
|
||||
} else if (aType==H_ROMAN) {
|
||||
switch(aC) {
|
||||
case 'A':ichr=11;break;
|
||||
case 'B':ichr=12;break;
|
||||
case 'C':ichr=13;break;
|
||||
case 'D':ichr=14;break;
|
||||
case 'E':ichr=15;break;
|
||||
case 'F':ichr=16;break;
|
||||
case 'G':ichr=17;break;
|
||||
case 'H':ichr=18;break;
|
||||
case 'I':ichr=19;break;
|
||||
case 'J':ichr=20;break;
|
||||
case 'K':ichr=21;break;
|
||||
case 'L':ichr=22;break;
|
||||
case 'M':ichr=23;break;
|
||||
case 'N':ichr=24;break;
|
||||
case 'O':ichr=25;break;
|
||||
case 'P':ichr=26;break;
|
||||
case 'Q':ichr=27;break;
|
||||
case 'R':ichr=28;break;
|
||||
case 'S':ichr=29;break;
|
||||
case 'T':ichr=30;break;
|
||||
case 'U':ichr=31;break;
|
||||
case 'V':ichr=32;break;
|
||||
case 'W':ichr=33;break;
|
||||
case 'X':ichr=34;break;
|
||||
case 'Y':ichr=35;break;
|
||||
case 'Z':ichr=36;break;
|
||||
}
|
||||
} else if (aType==H_GREEK) {
|
||||
switch(aC) {
|
||||
case 'A':ichr=1 ;break;
|
||||
case 'B':ichr=2 ;break;
|
||||
case 'C':ichr=7 ;break;
|
||||
case 'D':ichr=4 ;break;
|
||||
case 'E':ichr=5 ;break;
|
||||
case 'F':ichr=21;break;
|
||||
case 'G':ichr=3 ;break;
|
||||
case 'H':ichr=22;break;
|
||||
case 'I':ichr=9 ;break;
|
||||
case 'J':ichr=9 ;break;
|
||||
case 'K':ichr=10;break;
|
||||
case 'L':ichr=11;break;
|
||||
case 'M':ichr=12;break;
|
||||
case 'N':ichr=13;break;
|
||||
case 'O':ichr=15;break;
|
||||
case 'P':ichr=16;break;
|
||||
case 'Q':ichr=8 ;break;
|
||||
case 'R':ichr=17;break;
|
||||
case 'S':ichr=18;break;
|
||||
case 'T':ichr=19;break;
|
||||
case 'U':ichr=20;break;
|
||||
case 'V':ichr=22;break;
|
||||
case 'W':ichr=24;break;
|
||||
case 'X':ichr=14;break;
|
||||
case 'Y':ichr=23;break;
|
||||
case 'Z':ichr=6 ;break;
|
||||
}
|
||||
ichr += 36;
|
||||
} else if (aType==H_SPECIAL) {
|
||||
switch(aC) {
|
||||
case 'A':ichr=61;break;
|
||||
case 'B':ichr=62;break;
|
||||
case 'C':ichr=63;break;
|
||||
case 'D':ichr=64;break;
|
||||
case 'E':ichr=65;break;
|
||||
case 'F':ichr=66;break;
|
||||
case 'G':ichr=67;break;
|
||||
case 'H':ichr=68;break;
|
||||
case 'I':ichr=69;break;
|
||||
case 'J':ichr=70;break;
|
||||
case 'K':ichr=71;break;
|
||||
case 'L':ichr=72;break;
|
||||
case 'M':ichr=73;break;
|
||||
case 'N':ichr=74;break;
|
||||
case 'O':ichr=75;break;
|
||||
case 'P':ichr=76;break;
|
||||
case 'Q':ichr=77;break;
|
||||
case 'R':ichr=78;break;
|
||||
case 'S':ichr=79;break;
|
||||
case 'T':ichr=80;break;
|
||||
case 'U':ichr=81;break;
|
||||
case 'V':ichr=82;break;
|
||||
case 'W':ichr=83;break;
|
||||
case 'X':ichr=84;break;
|
||||
case 'Y':ichr=85;break;
|
||||
case 'Z':ichr=86;break;
|
||||
case '0':ichr=87;break;
|
||||
case '1':ichr=88;break;
|
||||
case '2':ichr=89;break;
|
||||
case '3':ichr=90;break;
|
||||
case '4':ichr=91;break;
|
||||
case '5':ichr=92;break;
|
||||
case '6':ichr=93;break;
|
||||
case '7':ichr=94;break;
|
||||
case '8':ichr=95;break;
|
||||
case '9':ichr=96;break;
|
||||
}
|
||||
} else if (aType==H_MATH) {
|
||||
switch(aC) {
|
||||
case '.':ichr= 97;break;
|
||||
case ',':ichr= 98;break;
|
||||
case '/':ichr= 99;break;
|
||||
case '(':ichr=100;break;
|
||||
case ')':ichr=101;break;
|
||||
case '-':ichr=102;break;
|
||||
case '+':ichr=103;break;
|
||||
case '=':ichr=104;break;
|
||||
case '*':ichr=105;break;
|
||||
}
|
||||
}
|
||||
|
||||
if (aCase==H_LOWER) ichr += 105;
|
||||
|
||||
// scale :
|
||||
size = a_scale;
|
||||
if(size<0.001) size = 0.25F;
|
||||
iy0 = 9;
|
||||
dky = 21;
|
||||
if (aType==H_SPECIAL) rescale(ichr,iy0,dky);
|
||||
scale = size/dky;
|
||||
|
||||
iw = hs(ichr-1) - 1;
|
||||
kx = (hx(iw) % 64 ) - 32;
|
||||
ky = (hy(iw) % 64 ) - 32;
|
||||
ibit = 1;
|
||||
idif = 1;
|
||||
ix0 = kx;
|
||||
// a character may be composed of many polylines :
|
||||
npoly = 0;
|
||||
ipoint = 0;
|
||||
max_x = 0;
|
||||
while(1) {
|
||||
count = 0;
|
||||
while(1) {
|
||||
ibit += 6;
|
||||
idif *= 64;
|
||||
if(ibit>=H_NBITMX) {
|
||||
ibit = 1;
|
||||
idif = 1;
|
||||
iw ++;
|
||||
}
|
||||
kx = ((hx(iw)/idif) % 64 ) - 32;
|
||||
ky = ((hy(iw)/idif) % 64 ) - 32;
|
||||
if(kx==31) break;
|
||||
aX[ipoint] = scale * (kx - ix0);
|
||||
aY[ipoint] = scale * (iy0 - ky);
|
||||
if (aX[ipoint] > max_x) max_x = aX[ipoint];
|
||||
ipoint ++;
|
||||
count ++;
|
||||
}
|
||||
// got one polyline :
|
||||
a_mx_point[npoly] = count;
|
||||
npoly ++;
|
||||
if(ky==31) break;
|
||||
}
|
||||
aN = npoly;
|
||||
a_width = max_x;
|
||||
}
|
||||
|
||||
static void rescale(int aIchr,int& aIy0,int& aDky){
|
||||
int iw,ibit,idif,kx,ky,kymin,kymax;
|
||||
|
||||
iw = hs(aIchr-1) - 1;
|
||||
kymin = 100;
|
||||
kymax = -100;
|
||||
ibit = 1;
|
||||
idif = 1;
|
||||
while(1) {
|
||||
while(1) {
|
||||
ibit += 6;
|
||||
idif *= 64;
|
||||
if(ibit>=H_NBITMX) {
|
||||
ibit = 1;
|
||||
idif = 1;
|
||||
iw ++;
|
||||
}
|
||||
kx = ((hx(iw)/idif) % 64 ) - 32;
|
||||
ky = ((hy(iw)/idif) % 64 ) - 32;
|
||||
if(kx==31) break;
|
||||
if(ky>kymax) kymax = ky;
|
||||
if(ky<kymin) kymin = ky;
|
||||
}
|
||||
if(ky==31) break;
|
||||
}
|
||||
//output :
|
||||
aIy0 = kymax;
|
||||
aDky = 21;
|
||||
if(kymin<kymax) {
|
||||
aDky = kymax-kymin;
|
||||
}
|
||||
}
|
||||
|
||||
private: //data
|
||||
static int hx(unsigned int a_index) {
|
||||
static const int s_hx[751] =
|
||||
{0x1969C7D6,0x217DC699,0x269E79A4,0x00FDF864,0x2185E716,0x0000003F,
|
||||
0x1C6DA696,0x2696489E,0x27663966,0x0000003F,0x238266D6,0x269E79A5,
|
||||
0x1A6DE864,0x00000FD9,0x3FA198D6,0x0003F8E3,0x1B69B956,0x279A485E,
|
||||
0x1E8649A7,0x00FD969B,0x208A5996,0x1B69A6DD,0x2692181D,0x219269E7,
|
||||
0x3F69B760,0x19FDD9D6,0x00000FE7,0x1A69B796,0x2692175B,0x229669E7,
|
||||
0x1965A6DE,0x258DF71A,0x1E8A59A6,0x0000003F,0x208E5996,0x1965A71F,
|
||||
0x2381F71A,0x239669A5,0x3F69B7A0,0x20FD8817,0x3F95BFE8,0x19FD9655,
|
||||
0x279E6962,0x19FE2966,0x279E6962,0x3F662966,0x23967A16,0x1969B75F,
|
||||
0x1F75B699,0x3FA27963,0x19FD9655,0x279A58E0,0x208E59A7,0x00000FD9,
|
||||
0x1AFDA696,0x3F89AFE7,0x0003F9DA,0x1AFDA696,0x3F89AFE7,0x23967A16,
|
||||
0x1969B75F,0x1F75B699,0x28A27963,0x00FE88FF,0x27FD9655,0x3F9D9FE7,
|
||||
0x00FE081C,0x228E4918,0x1A6DC7A0,0x00000FDA,0x27FD9655,0x3F9DEFD9,
|
||||
0x1AFDA696,0x00000FE6,0x18FD8614,0x3F828FE0,0x0003FA28,0x19FD9655,
|
||||
0x3F9E7FE7,0x1969C795,0x1C699618,0x279A489E,0x249A7A28,0x0003F7A2,
|
||||
0x19FD9655,0x279E6962,0x3F662966,0x1969C795,0x1C699618,0x279A489E,
|
||||
0x249A7A28,0x2787F7A2,0x0000003F,0x19FD9655,0x279E6962,0x3F662966,
|
||||
0x0003F9E0,0x1E8A59D6,0x1B69965B,0x279A58DD,0x1B7A2967,0x00000FD9,
|
||||
0x19FE0818,0x00000FE7,0x1C699655,0x279A485F,0x00000FE7,0x28FE0617,
|
||||
0x00000FE0,0x20FDB594,0x3F960FDB,0x0003F96A,0x27FE7656,0x00000FD9,
|
||||
0x3F820617,0x0003F828,0x19FD99D6,0x3F9D9FE7,0x20FD8817,0x3F95BFE8,
|
||||
0x19FD9655,0x279E6962,0x19FE2966,0x279E6962,0x3F662966,0x1AFDA696,
|
||||
0x00000FE6,0x20FD8817,0x3FA18FE8,0x1AFDA696,0x3F89AFE7,0x0003F9DA,
|
||||
0x19FD99D6,0x3F9D9FE7,0x27FD9655,0x3F9D9FE7,0x1969C795,0x1C699618,
|
||||
0x279A489E,0x249A7A28,0x2377F7A2,0x0000003F,0x00FE081C,0x27FD9655,
|
||||
0x3F9DEFD9,0x20FD8817,0x00000FE8,0x18FD8614,0x3F828FE0,0x0003FA28,
|
||||
0x19FD9655,0x3F9E7FE7,0x1DFE7657,0x3F9D9FE3,0x1969C795,0x1C699618,
|
||||
0x279A489E,0x249A7A28,0x0003F7A2,0x27FD9655,0x3F9D9FE7,0x19FD9655,
|
||||
0x279E6962,0x3F662966,0x3F660657,0x2767F9D9,0x0000003F,0x19FE0818,
|
||||
0x00000FE7,0x1B699657,0x2081F79D,0x259A79FF,0x3F8218A3,0x1EFE0816,
|
||||
0x1A65969B,0x2696279B,0x229669E7,0x00000FDE,0x19FE7656,0x00000FE7,
|
||||
0x17FE0815,0x1C6DA658,0x2696485F,0x00FE9A27,0x1969D656,0x217DC699,
|
||||
0x269E79A4,0x0003F9E3,0x18FE0814,0x3FA18FE8,0x00FE081C,0x1A69E79A,
|
||||
0x268A279E,0x3F7A28A6,0x22FDE796,0x26966FE2,0x1E8A59E7,0x1B69965B,
|
||||
0x3F9E58DD,0x258DD6D9,0x229679E6,0x1A6596DE,0x0003F69B,0x20FE081B,
|
||||
0x3F82181F,0x27FDA856,0x3FA1AFE0,0x0003F9D9,0x3F628614,0x1C6DA697,
|
||||
0x2696489E,0x20824966,0x2181F83F,0x00000FE0,0x2AA68A54,0x23967A6A,
|
||||
0x1D7A0862,0x228E4FDC,0x1B75E7E0,0x175965D9,0x0003F5D8,0x2181F81B,
|
||||
0x207E0FE0,0x0003F821,0x2181F81B,0x1F821FE0,0x1F821860,0x0000003F,
|
||||
0x3FA18A14,0x1EFDD759,0x3F91DFDE,0x0003F91D,0x23FE2899,0x3F8DCFE3,
|
||||
0x0003F8DC,0x3F6E56D8,0x256FF95B,0x0000003F,0x1E7E0899,0x218607DE,
|
||||
0x1F7E0FDF,0x218A2860,0x218A285D,0x3F81F7E0,0x1F82185F,0x2281F79E,
|
||||
0x0000003F,0x22860799,0x1F7E0862,0x21860FE1,0x1F79E7E0,0x1F79E7E3,
|
||||
0x3F821860,0x2181F7E1,0x1E8218A2,0x0000003F,0x3F81748F,0x20C3F816,
|
||||
0x0000003F,0x1865C814,0x1F75B658,0x27920FE0,0x23967A28,0x1F83F821,
|
||||
0x22860FDE,0x00FE27BF,0x1C79F814,0x1961865B,0x20FE071A,0x279648A1,
|
||||
0x249A7A28,0x00000FE0,0x1769E814,0x299A283F,0x2079A5FF,0x208A6A7F,
|
||||
0x0000003F,0x26922814,0x26A29A68,0x2387F864,0x1F863924,0x1F75C71D,
|
||||
0x1869C7FF,0x1C6985D7,0x1F83F81E,0x22860FDE,0x00FE27BF,0x28A6AA93,
|
||||
0x208A49A7,0x165D869E,0x207D85D6,0x1C7A0861,0x2379C6DB,0x2AAA99E5,
|
||||
0x0000003F,0x27FE7655,0x00000FD9,0x1DFDA998,0x1A6DD79E,0x2485D6DA,
|
||||
0x228A3FE6,0x259A6963,0x00000FE3,0x258E2815,0x2BAEAA67,0x23967A6A,
|
||||
0x196DD7A2,0x16555597,0x1E75B657,0x00000FE0,0x1C71D7DC,0x248E17DD,
|
||||
0x3F7E18E4,0x1E7BF75D,0x20FDF7FF,0x3F861FE0,0x238FF8A2,0x0000003F,
|
||||
0x2491C71C,0x3F75DFDC,0x1F7FF79E,0x21FE083F,0x3F8A2FE1,0x0003F8E3,
|
||||
0x2095B81B,0x20FDD83F,0x3F7E0FE3,0x0003F860,0x206E581B,0x20FE383F,
|
||||
0x3F860FDD,0x0003F7E0,0x1A99C81A,0x2083F824,0x20FDA83F,0x3F920FDC,
|
||||
0x0003F9A0,0x3F9A9993,0x17FE3A23,0x00000FE8,0x3F8A0798,0x20FE581B,
|
||||
0x00000FE0,0x3F697693,0x18FDD61D,0x00000FE9,0x3F8A0798,0x20FE581B,
|
||||
0x00000FE0,0x2181F81B,0x00FDF821,0x2181F81B,0x00000FE0,0x207E085B,
|
||||
0x3F7E0861,0x00FD7A55,0x1E822919,0x2281E75D,0x00000FE4,0x2281E719,
|
||||
0x1E8228E3,0x00000FDC,0x00FE95D3,0x17FE0813,0x00000FE9,0x17FE95D3,
|
||||
0x00000FE9,0x1BFE0818,0x3F6E5FE5,0x1D75E81B,0x238E281E,0x0003F822,
|
||||
0x3F82079B,0x2385F75B,0x3F8DD8A3,0x2385F75B,0x2183F863,0x1D7E18E3,
|
||||
0x0000003F,0x21FE185B,0x0003F91C,0x207DD79B,0x1F8228E2,0x3F89EFDD,
|
||||
0x1D7A089B,0x238A079D,0x3F75E822,0x1DFDF8DB,0x00000FE3,0x1F75D7DB,
|
||||
0x1F8638E1,0x1F75D7FF,0x3F8638E1,0x1E8228DB,0x238A079D,0x3F7A08A3,
|
||||
0x26FE6997,0x1B75F8A4,0x1F75B69A,0x00FE6922,0x1AFDA696,0x258E179C,
|
||||
0x218E59A6,0x00FDA71E,0x1F8A4997,0x1B69A6DD,0x269227DD,0x0000003F,
|
||||
0x26FE6997,0x1B75F8A4,0x1F75B69A,0x00FE6922,0x259A6697,0x1B75F8A4,
|
||||
0x1F75B69A,0x00FE6922,0x2086395B,0x3F91DFE0,0x24966997,0x26FDD7E2,
|
||||
0x1B75F8A4,0x1F75B69A,0x00FE6922,0x1BFDB6D7,0x2696381E,0x00000FE6,
|
||||
0x208607DC,0x3F820FDF,0x218A181B,0x20861FE0,0x0003F71E,0x25FDB6D7,
|
||||
0x3F99FFDB,0x00FE081C,0x15FD5551,0x207DD698,0x258E0FE0,0x3FAEBAA8,
|
||||
0x1BFDB6D7,0x2696381E,0x00000FE6,0x1A6DD7D7,0x227DD6DA,0x269E79A4,
|
||||
0x00FDF8A4,0x1AFDA696,0x258E179C,0x218E59A6,0x00FDA71E,0x26FE6997,
|
||||
0x1B75F8A4,0x1F75B69A,0x00FE6922,0x1DFDD759,0x3F96281E,0x1F8A5998,
|
||||
0x2379C6DC,0x229669A5,0x00FDB71F,0x2386081B,0x3F91DFE5,0x1E71B6D7,
|
||||
0x26FE68E1,0x00000FE6,0x26FE0698,0x00000FE0,0x20FDC615,0x3F920FDC,
|
||||
0x0003F928,0x26FE66D8,0x00000FDB,0x26FE0698,0x1969C7A0,0x0000003F,
|
||||
0x1BFDB998,0x3F99BFE6,0x1A6DD7D6,0x1E71A659,0x289E58E0,0x238A17FF,
|
||||
0x3FA279A5,0x1D7E18D7,0x3F65A6DC,0x269E7963,0x20FE08E5,0x24965922,
|
||||
0x1C75F863,0x00000FDB,0x1D71A617,0x2086181F,0x209A7A3F,0x0003F75E,
|
||||
0x1B75F897,0x1E71B69A,0x259648A0,0x1F7E08A4,0x3F9A48A0,0x1F8A4958,
|
||||
0x3F85E75D,0x1C6DB761,0x3F96385E,0x1F7E0898,0x26FE68E0,0x1B6DC7E2,
|
||||
0x228A179C,0x00FDE7E1,0x1C6985D6,0x3F69C75D,0x248A079C,0x3F8A59A6,
|
||||
0x1B657595,0x1C6DB71C,0x248E17DD,0x239669A5,0x23860821,0x0003FA25,
|
||||
0x1D75E81A,0x3F8E281E,0x27FD9757,0x1D7E3966,0x1F79CFDC,0x3F9238A1,
|
||||
0x1E75B658,0x3F6A0FE6,0x1CFD7756,0x217DD6DB,0x259FF963,0x299E5924,
|
||||
0x00000FEA,0x1B71D697,0x259A7FDA,0x3F69D823,0x1F7E0898,0x23FE68E0,
|
||||
0x1F75D7A0,0x1E8BF922,0x2175B6DC,0x3F7A08A2,0x1B71E818,0x217DD71B,
|
||||
0x259A6963,0x00FE08A4,0x23FDA795,0x17FE6964,0x00FE9719,0x1D71B6D7,
|
||||
0x2696385F,0x208A4966,0x3F5DB71E,0x1B75FA57,0x1E71B69A,0x259648A0,
|
||||
0x00FE18E4,0x18FDE856,0x00FE875A,0x1C6985D6,0x1D6DB75D,0x279A489F,
|
||||
0x00000FE7,0x1865B755,0x1F71A658,0x28A27962,0x1E822926,0x00000FDB,
|
||||
0x2375B657,0x27A3F9E5,0x3F6196E5,0x15FDC914,0x1B6DA616,0x1F75B69A,
|
||||
0x29A26922,0x0000003F,0x1761A714,0x1D6D9617,0x207E0FDF,0x289E58E1,
|
||||
0x00FE69E8,0x1BFE0818,0x3F95BFE5,0x00FE081E,0x209D9819,0x2066783F,
|
||||
0x0000003F,0x22FDF7D9,0x24925FE2,0x1C7A3965,0x3F96475C,0x2596475C,
|
||||
0x1C75F8A4,0x3F71D75C,0x21FE081E,0x21820FE1,0x0003F821,0x23FDE81B,
|
||||
0x3F91DFE1,0x0003F91D,0x3F6E56D8,0x2386079C,0x21860823,0x21820FE3,
|
||||
0x0003F821,0x279E6997,0x20862926,0x23FDD79F,0x1E7E0862,0x1A65969C,
|
||||
0x00000FDA,0x2186081E,0x21820FE0,0x0003F821,0x2186081E,0x20821FE0,
|
||||
0x00FE0861,0x3F95B958,0x1FFDE79B,0x3F8DEFDF,0x0003F8DE,0x22FE185B,
|
||||
0x3F89DFE2,0x0003F89D,0x3F95B958,0x256FF95B,0x0000003F,0x1E79F85A,
|
||||
0x1E7FF860,0x1EFE087F,0x1E82185F,0x1E7E1860,0x1EFE183F,0x1E821FDF,
|
||||
0x00FE17DE,0x228A17DB,0x2287F7E0,0x22FE07FF,0x2281F7E1,0x2285F7E0,
|
||||
0x22FDF83F,0x2281FFE1,0x00FDF862,0x3F81A5D5,0x20A7F819,0x0000003F,
|
||||
0x217DE795,0x1657F8A2,0x1B69A658,0x269A58DD,0x3FAEAA27,0x1E7FFAD5,
|
||||
0x3F86285F,0x20FE0818,0x3F860FDF,0x1F83F85F,0x1C7FF71E,0x248A183F,
|
||||
0x20FE487F,0x1EFD869C,0x2483F61A,0x268BFA26,0x1D7A0FE8,0x1D7A0FDD,
|
||||
0x238E283F,0x3F8E283F,0x20FE0818,0x3F820FE0,0x2183F7E0,0x20FE17FF,
|
||||
0x2183F79F,0x2281EFE2,0x1B71E83F,0x2592283F,0x2281E73F,0x1C7A0FE4,
|
||||
0x3F69965A,0x279A48A0,0x1E73F9A7,0x20FE48A0,0x1969B75E,0x20FDA618,
|
||||
0x279A58E2,0x1BFE6A28,0x3F96381D,0x20FDF818,0x3F85FFE1,0x28A268E0,
|
||||
0x27A27967,0x218E48E5,0x1B75C75F,0x196D9619,0x2075A618,0x0000003F,
|
||||
0x218A391A,0x1D71C760,0x1E821860,0x2385F75D,0x00000FE4,0x23FE375B,
|
||||
0x00000FDD,0x29AABAD7,0x1A761926,0x1A6175D8,0x299A485D,0x00FEBAEA,
|
||||
0x24967A16,0x1C79F862,0x1961865B,0x217DE71B,0x289E5922,0x00000FE8,
|
||||
0x1969C7D9,0x217DC699,0x269E79A4,0x00FDF864,0x2699A69A,0x00000FDA,
|
||||
0x209D9819,0x0000003F,0x2681A81A,0x00000FE0,0x1D61E818,0x288E581B,
|
||||
0x0003F822,0x239A3897,0x23963FE2,0x00FE56BF,0x1DFE081B,0x3F8E281E,
|
||||
0x00FE281E,0x1D69D797,0x1D6DDFDE,0x00FE66FF,0x1DFE081B,0x3F8E281E,
|
||||
0x00FE281E,0x2182085E,0x0003F821,0x2186081E,0x00000FE0,0x2182085E,
|
||||
0x0003F821,0x00FDC91B,0x1F7E089D,0x0003F8A0,0x2186079C,0x0003F7A0,
|
||||
0x00FE471A,0x1CFE081A,0x00000FE4,0x1CFE471A,0x00000FE4,0x1DFE081B,
|
||||
0x3F763FE3};
|
||||
return s_hx[a_index];
|
||||
}
|
||||
|
||||
static int hy(unsigned int a_index) {
|
||||
static const int s_hy[751] =
|
||||
{0x1D61552A,0x29A68960,0x18760968,0x00FD4515,0x2951762A,0x0000003F,
|
||||
0x1559866A,0x18595514,0x29A5F71A,0x0000003F,0x1C71452A,0x268E179D,
|
||||
0x27A29A68,0x00000FE5,0x208A252A,0x0003FA54,0x1C75452A,0x2179C6DB,
|
||||
0x29A689A3,0x00FE59E8,0x145155EA,0x2689D615,0x26A29A68,0x1C75F8A3,
|
||||
0x3F89F75C,0x1482952A,0x00000FD4,0x195D552A,0x2079D71B,0x29A27962,
|
||||
0x22967A29,0x1B71D7A0,0x145155D9,0x0000003F,0x2181E6EA,0x1A6DE821,
|
||||
0x15514557,0x289606D7,0x3F9A8A69,0x14829529,0x3F8A2829,0x1482952A,
|
||||
0x1A616554,0x1E81E75C,0x258A07DE,0x3FA69A27,0x1455766B,0x1C657554,
|
||||
0x29A26921,0x3F926A29,0x1482952A,0x1C657554,0x29A26921,0x00000FE9,
|
||||
0x14829529,0x2079E814,0x0003FA69,0x14829528,0x3F79E814,0x1455766B,
|
||||
0x1C657554,0x29A26921,0x21926A29,0x00FE1860,0x1482952B,0x3F79E829,
|
||||
0x00FE9524,0x289E4528,0x249E8A69,0x00000FE2,0x1482952A,0x3FA5D822,
|
||||
0x29829527,0x00000FE9,0x1482952C,0x20A54829,0x0003FA54,0x1482952B,
|
||||
0x3FA54829,0x195D552B,0x289A485C,0x249A8A69,0x155D9721,0x0003F514,
|
||||
0x1482952A,0x1B616554,0x3F7DF79D,0x195D552B,0x289A485C,0x249A8A69,
|
||||
0x155D9721,0x2B960514,0x0000003F,0x1482952A,0x1A616554,0x2079E75C,
|
||||
0x0003FA5E,0x145155EA,0x1C6D95D5,0x238607DD,0x28A69A26,0x00000FE6,
|
||||
0x14829528,0x00000FD4,0x289A352B,0x239A8A69,0x00000FD4,0x14829529,
|
||||
0x00000FE9,0x1482952C,0x20A54829,0x0003FA54,0x1482952A,0x00000FE9,
|
||||
0x20A5E529,0x0003F794,0x1482952A,0x3FA69814,0x14829529,0x3F8A2829,
|
||||
0x1482952A,0x1A616554,0x1E81E75C,0x258A07DE,0x3FA69A27,0x14829527,
|
||||
0x00000FD4,0x14829529,0x3FA69829,0x14829529,0x2079E814,0x0003FA69,
|
||||
0x1482952A,0x3FA69814,0x1482952B,0x3F79E829,0x195D552B,0x289A485C,
|
||||
0x249A8A69,0x155D9721,0x1E7A0514,0x0000003F,0x00FE9524,0x1482952A,
|
||||
0x3FA5D822,0x14829529,0x00000FE9,0x1482952C,0x20A54829,0x0003FA54,
|
||||
0x1482952B,0x3FA54829,0x1E814529,0x3FA6981E,0x195D552B,0x289A485C,
|
||||
0x249A8A69,0x155D9721,0x0003F514,0x1482952B,0x3F514829,0x1482952A,
|
||||
0x1B616554,0x3F7DF79D,0x20A5E529,0x29A60514,0x0000003F,0x14829528,
|
||||
0x00000FD4,0x14557669,0x296D7554,0x14557660,0x3F6D7554,0x1982952A,
|
||||
0x2281D6DA,0x228E4923,0x1969B760,0x00000FD9,0x2982952A,0x00000FD4,
|
||||
0x1A82952B,0x2285F6DA,0x1F8628E3,0x00FDA69B,0x1E8A9A6A,0x145155DA,
|
||||
0x2279A5D5,0x0003FA69,0x2082962C,0x3FA69820,0x00FF0424,0x2279E6A6,
|
||||
0x228A69A2,0x3F69A79E,0x1082D42A,0x1961782D,0x145155D8,0x1C6D95D5,
|
||||
0x208A07DD,0x1F79C6D9,0x29A268A0,0x24966A29,0x0003F9A5,0x27822525,
|
||||
0x3F9E8A68,0x1083042B,0x2075D830,0x0003F8E3,0x3FA605EC,0x15598669,
|
||||
0x18595514,0x227DD71A,0x28A689E0,0x00000FE7,0x124D246C,0x13450411,
|
||||
0x2CA1C615,0x1851282E,0x2FB6BA24,0x2DBAFC30,0x0003FBEE,0x1C75C6E5,
|
||||
0x29A2781B,0x0003F9E8,0x1C75C6E5,0x28A6881B,0x2DB2AA27,0x0000003F,
|
||||
0x3FA605EC,0x10830427,0x20410830,0x0003FC30,0x10830427,0x20410830,
|
||||
0x0003FC30,0x2085D668,0x269A08A2,0x0000003F,0x14491427,0x1D6D9616,
|
||||
0x154D181F,0x1E71A617,0x289A48A0,0x20BEDAE9,0x289E58E1,0x30BEEB2A,
|
||||
0x0000003F,0x14491427,0x1D6D9616,0x154D181F,0x1E71A617,0x289A48A0,
|
||||
0x20BEDAE9,0x289E58E1,0x30BEEB2A,0x0000003F,0x209DB6F0,0x29220A5C,
|
||||
0x0000003F,0x2179A5AC,0x259A6963,0x1E696823,0x269A58E1,0x278E08E5,
|
||||
0x2A9E382A,0x00FEAAA0,0x165D972C,0x207595D6,0x1C82A962,0x175965D9,
|
||||
0x258A0759,0x00000FEA,0x2075856C,0x20758560,0x2BA23820,0x2BA23820,
|
||||
0x0000003F,0x269A58AC,0x1E7E18E5,0x1D7E07DE,0x1659765B,0x1F75B657,
|
||||
0x1F79E7E0,0x269A58E1,0x278A08A5,0x2A9E282A,0x00FEAAA0,0x1B6DC76D,
|
||||
0x289A379C,0x259E8A69,0x1B720863,0x155155D9,0x267DC657,0x27A29A68,
|
||||
0x0000003F,0x1982766B,0x00000FE7,0x19826668,0x1C75D71A,0x1A69965A,
|
||||
0x258E2819,0x228E59A6,0x00000FE2,0x2592382B,0x1F863925,0x1C6DB71D,
|
||||
0x259648DD,0x1D7E18E4,0x1D71B6DC,0x00000FE0,0x217DD724,0x218E4923,
|
||||
0x2071C75F,0x227A085F,0x1D823760,0x208DD823,0x217E089E,0x0000003F,
|
||||
0x1C924724,0x208DD81C,0x237608DD,0x1D823760,0x208DD823,0x0003F8DD,
|
||||
0x1A8E36A5,0x1D822760,0x208A0822,0x0003F8A0,0x2675D9A5,0x2381E8E0,
|
||||
0x207A081E,0x0003F7A0,0x1E7A56A6,0x1A8206A5,0x2081E820,0x20960825,
|
||||
0x0003F7A0,0x208A07AD,0x2082581B,0x00000FE0,0x206976A8,0x1881D61D,
|
||||
0x00000FE9,0x208A07AD,0x2082581B,0x00000FE0,0x209A99A8,0x17823A23,
|
||||
0x00000FE8,0x155155A5,0x00FDA657,0x28A689E5,0x00000FE7,0x27A29A25,
|
||||
0x3FB6CAA8,0x00FF042B,0x19552427,0x2EAE789E,0x00000FF0,0x19552427,
|
||||
0x2EAE789E,0x00000FF0,0x00FE082D,0x208295ED,0x00000FE0,0x2381D76D,
|
||||
0x00000FE3,0x1D8266A8,0x3F8DD823,0x2179C6E5,0x1E863923,0x0003F6DC,
|
||||
0x3F91B765,0x1C6DB725,0x3F92481E,0x1C6DB725,0x1F7E07DE,0x239248E0,
|
||||
0x0000003F,0x1B8246E5,0x0003F861,0x1E79F6E5,0x2492385F,0x3F6DB823,
|
||||
0x1E71B6E5,0x218E48E1,0x3F85F79F,0x1B8246E5,0x00000FDB,0x1F79C6E5,
|
||||
0x1B6DC79F,0x248E07E0,0x3F7E08E4,0x208607A5,0x1E71B71E,0x3F9248E1,
|
||||
0x1E8296EA,0x1E71B6DC,0x29A268E1,0x00FE6A29,0x1E829529,0x1E71B6DC,
|
||||
0x29A268E1,0x00FE6A29,0x1B6DC7A9,0x268E179C,0x26A29A68,0x0000003F,
|
||||
0x1E82952A,0x1E71B6DC,0x29A268E1,0x00FE6A29,0x1D7E1869,0x1E71B6DC,
|
||||
0x29A268E1,0x00FE6A29,0x18554527,0x3F6DB829,0x2FBAB6EA,0x1E82FC30,
|
||||
0x1E71B6DC,0x29A268E1,0x00FE6A29,0x1F82952A,0x1F71B6DC,0x00000FE9,
|
||||
0x13515524,0x3FA5B814,0x13515525,0x2FB1B814,0x0003FC30,0x1B829528,
|
||||
0x3FA61825,0x00FE9524,0x1F8296EF,0x1F71B6DC,0x1B71F829,0x3FA5F71B,
|
||||
0x1F8296EA,0x1F71B6DC,0x00000FE9,0x2179C6EA,0x29A689A3,0x1E8639A8,
|
||||
0x00FDB6DC,0x1E8306E9,0x1E71B6DC,0x29A268E1,0x00FE6A29,0x1E8306EA,
|
||||
0x1E71B6DC,0x29A268E1,0x00FE6A29,0x218296E6,0x3F6DB71E,0x1B6DC7A9,
|
||||
0x2286079C,0x29A26963,0x00FE6A29,0x29A25527,0x3F6DB829,0x29A256EA,
|
||||
0x1B825A29,0x00000FE9,0x1B8296E8,0x00000FE9,0x1B8296EB,0x20A5B829,
|
||||
0x0003FA5B,0x1B8296E9,0x00000FE9,0x1B8296E8,0x30C2FB69,0x0000003F,
|
||||
0x1B8296E9,0x3FA6981B,0x2079C6EB,0x29A689A3,0x1B7A2968,0x1E71B6E0,
|
||||
0x3FA69A26,0x1B5D552A,0x20C2889E,0x1B656514,0x1D81D75C,0x2796281E,
|
||||
0x27A29A68,0x00000FE4,0x1B6DC7AA,0x2992075C,0x2981E6E0,0x0003FC2D,
|
||||
0x1E71B6E9,0x29A27921,0x208E6A29,0x155D96DD,0x3F5D5514,0x1B6DC768,
|
||||
0x2086079C,0x289A48A1,0x3F9A8A69,0x17595527,0x19819658,0x258E075B,
|
||||
0x2FB6BA67,0x00FEEC30,0x1B6DD7EA,0x20A6279C,0x1B6DC7A2,0x3FC2581D,
|
||||
0x1B6DD7EA,0x289A379C,0x23968A69,0x145586E0,0x1E6D8594,0x0003F8A0,
|
||||
0x289A26E5,0x3F967A69,0x1C8296E9,0x2181C6DB,0x238A1821,0x3FA29A68,
|
||||
0x16554528,0x3FA5B829,0x1F8306EB,0x28A699E4,0x226E08A6,0x27A69A26,
|
||||
0x00000FE5,0x2685B6E9,0x2079B829,0x3FA689A3,0x17595528,0x19819658,
|
||||
0x217DD6DA,0x238A08A2,0x2CAA89A4,0x3FC30BED,0x2179C6E9,0x29A689E4,
|
||||
0x1D8239A8,0x00FDB6DC,0x1B8296EB,0x1E8299A1,0x00FDB6DC,0x289E4869,
|
||||
0x239A8A69,0x1B6DC760,0x3FC2179C,0x1E71B6EB,0x29A27921,0x208E6A29,
|
||||
0x00FDB71D,0x1E8296EA,0x00FDB6DC,0x1B6DD7EA,0x299E479C,0x1E8A6A29,
|
||||
0x00000FDB,0x227DD72B,0x29A689E5,0x1D8239A8,0x2685D6DB,0x00000FF0,
|
||||
0x2E75B6E9,0x1D6E0C30,0x3FC2EAE0,0x1F83052B,0x1E71B6DD,0x29A689A3,
|
||||
0x1B7A39A8,0x0000003F,0x227DC6EB,0x28A69A25,0x28961825,0x22968A69,
|
||||
0x00FDB71F,0x208266E8,0x3F9A6820,0x00FE56A2,0x18924627,0x2871CA20,
|
||||
0x0000003F,0x1682A5A8,0x1B69A82A,0x1A65969B,0x208A179C,0x248A075C,
|
||||
0x249669A5,0x3F9248E3,0x1B8206E3,0x24923820,0x0003F8E3,0x1A8256A6,
|
||||
0x2079E825,0x0003F861,0x3F9A06A8,0x1C6DB725,0x1F8207DE,0x2492381E,
|
||||
0x0003F8E3,0x176185E9,0x1D698596,0x178299E3,0x289A3759,0x28A29AAA,
|
||||
0x00000FE9,0x1E7DF7A3,0x2492381E,0x0003F8E3,0x1E7DF7A3,0x2392481E,
|
||||
0x00FE7963,0x3F9A06A8,0x1682A5A5,0x2059682A,0x0003FAAA,0x1682A5A5,
|
||||
0x2059682A,0x0003FAAA,0x2085D668,0x269A08A2,0x0000003F,0x1A6175A5,
|
||||
0x1A5E079C,0x1881F720,0x207DE71A,0x289A48A1,0x26824860,0x26922829,
|
||||
0x00FEAA68,0x1A6175A6,0x1A5E079C,0x1881F720,0x207DE71A,0x289A48A1,
|
||||
0x26824860,0x26922829,0x00FEAA68,0x2095D769,0x2652099D,0x0000003F,
|
||||
0x145155EB,0x26A205D5,0x1865E8A4,0x1E6585D7,0x20A26922,0x29A20A28,
|
||||
0x3FA29AAA,0x218216E8,0x20AA182A,0x186E0AAA,0x15620556,0x155986E0,
|
||||
0x1B815620,0x1A81B659,0x196E06DA,0x1A6A06D9,0x1D71B81B,0x2075B820,
|
||||
0x2075C6E0,0x3F81D6E0,0x1C8195E8,0x208E181E,0x2A9E0AA7,0x1582AAA0,
|
||||
0x17560617,0x185D8818,0x1C75C660,0x1C75C660,0x1D71D760,0x2285E81D,
|
||||
0x208A1822,0x208A285E,0x228A08A1,0x238228A1,0x27A289E6,0x238289E5,
|
||||
0x27A289E6,0x288289E5,0x3FA289E8,0x2782A9E8,0x20AAA82A,0x239A8A27,
|
||||
0x1B7608A2,0x155986DA,0x1A6D8595,0x228A075B,0x27A289A3,0x0000003F,
|
||||
0x23860826,0x20863924,0x1B6DC79F,0x248E179C,0x00000FE4,0x1D823765,
|
||||
0x00000FE3,0x218E6A2B,0x1D71C75E,0x238A17DE,0x1F8A3924,0x00FD869D,
|
||||
0x238E282A,0x1C75E862,0x2281F75C,0x1E8628E3,0x1F75C71D,0x00000FE0,
|
||||
0x1F71A667,0x279E6921,0x1C7E1926,0x00FD965A,0x1A9A66A6,0x00000FDA,
|
||||
0x18924627,0x0000003F,0x20AA05A6,0x00000FD6,0x2175D5E8,0x1D8678E7,
|
||||
0x0003F5DD,0x2281E769,0x2281E823,0x00FE0820,0x1E8266E5,0x2079D69D,
|
||||
0x00FDD6DD,0x2281E769,0x2281E823,0x00FE0820,0x228256A5,0x208A39A3,
|
||||
0x00FE3963,0x1B6DC723,0x0003F7DD,0x239248E3,0x00000FE3,0x238E4923,
|
||||
0x0003F9E5,0x00FE56A5,0x2179C6A4,0x0003F963,0x2179C6A3,0x0003F963,
|
||||
0x00FE0826,0x20824726,0x00000FE0,0x2281E7A6,0x00000FE2,0x1E823765,
|
||||
0x3F89E822};
|
||||
return s_hy[a_index];
|
||||
}
|
||||
static int hs(unsigned int a_index) {
|
||||
static const int s_hs[210] =
|
||||
{ 1, 5, 7, 11, 15, 17, 21, 26, 28, 35, 40, 42, 47, 51, 55,
|
||||
58, 60, 65, 67, 68, 71, 73, 75, 78, 80, 85, 88, 94, 98,103,
|
||||
105,108,110,113,115,117,119,121,126,128,130,133,135,137,143,
|
||||
144,146,148,151,153,155,160,162,165,168,170,174,179,181,185,
|
||||
189,191,192,195,204,206,209,210,215,222,225,229,230,233,236,
|
||||
239,248,257,260,267,273,278,288,296,298,304,311,319,325,329,
|
||||
333,338,341,344,347,350,352,354,356,357,360,363,364,366,368,
|
||||
370,373,374,376,380,382,385,388,390,394,397,401,405,409,413,
|
||||
417,419,424,427,429,432,434,435,439,442,446,450,454,456,460,
|
||||
462,465,467,470,472,475,477,482,489,493,498,502,507,511,517,
|
||||
519,523,525,530,533,539,543,546,550,554,556,560,565,568,573,
|
||||
578,580,581,584,591,594,597,598,602,608,611,614,615,618,621,
|
||||
624,632,640,643,650,663,682,691,696,698,703,709,713,715,717,
|
||||
719,722,725,728,731,734,736,738,740,741,743,745,746,748,750};
|
||||
return s_hs[a_index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -205,6 +205,7 @@ public:
|
||||
return sw;
|
||||
}
|
||||
|
||||
TC Sxyw() const {return parent::m_in_range_plane_Sxyw[0];}
|
||||
public:
|
||||
//NOTE : print is a Python keyword.
|
||||
void hprint(std::ostream& a_out) {
|
||||
|
||||
@@ -293,6 +293,9 @@ public:
|
||||
return sw;
|
||||
}
|
||||
|
||||
TC Sxyw() const {return parent::m_in_range_plane_Sxyw[0];}
|
||||
TC Syzw() const {return parent::m_in_range_plane_Sxyw[1];}
|
||||
TC Szxw() const {return parent::m_in_range_plane_Sxyw[2];}
|
||||
public:
|
||||
//NOTE : print is a Python keyword.
|
||||
void hprint(std::ostream& a_out) {
|
||||
|
||||
@@ -54,7 +54,6 @@ public:
|
||||
}
|
||||
public:
|
||||
const std::string& title() const {return m_title;}
|
||||
std::string title() {return m_title;}
|
||||
int max_entries() const {return m_limit;}
|
||||
protected:
|
||||
static int UNLIMITED() {return -1;}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace histo {
|
||||
//TH is for a height.
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
class base_histo : public histo_data<TC,TO,TN,TW> {
|
||||
class base_histo : protected histo_data<TC,TO,TN,TW> {
|
||||
typedef histo_data<TC,TO,TN,TW> parent;
|
||||
private:
|
||||
static const std::string& s_class() {
|
||||
@@ -35,15 +35,24 @@ public:
|
||||
typedef axis<TC,TO> axis_t;
|
||||
typedef typename axis_t::bn_t bn_t;
|
||||
typedef unsigned int dim_t;
|
||||
typedef TC coordinate_t;
|
||||
typedef TO offset_t;
|
||||
typedef TN num_entries_t;
|
||||
typedef TW weight_t;
|
||||
typedef TH height_t;
|
||||
protected:
|
||||
virtual TH get_bin_height(TO) const = 0; //histo/profile
|
||||
protected:
|
||||
void base_from_data(const hd_t& a_from) {parent::operator=(a_from);}
|
||||
#ifdef tools_histo_base_histo //for backward compatibility with tools
|
||||
hd_t base_get_data() const {
|
||||
hd_t hd;
|
||||
hd = *this;
|
||||
return hd;
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
const hd_t& dac() const {return *this;} //data accessor.
|
||||
protected:
|
||||
base_histo():parent() {
|
||||
#ifdef TOOLS_MEM
|
||||
@@ -70,27 +79,20 @@ protected:
|
||||
|
||||
public:
|
||||
const std::string& title() const {return parent::m_title;}
|
||||
std::string title() {return parent::m_title;}
|
||||
bool set_title(const std::string& a_title){parent::m_title = a_title;return true;}
|
||||
dim_t dimension() const {return parent::m_dimension;}
|
||||
dim_t number_of_planes() const {return dim_planes(parent::m_dimension);}
|
||||
|
||||
TN entries() const {
|
||||
return parent::m_in_range_entries; //not set if reading a TH from a ROOT file.
|
||||
return parent::m_in_range_entries; //not set if reading a TH from a CERN-ROOT file.
|
||||
}
|
||||
TN all_entries() const {
|
||||
return parent::m_all_entries; //works also is reading histo from a ROOT file.
|
||||
return parent::m_all_entries; //works also is reading histo from a CERN-ROOT file.
|
||||
}
|
||||
/*
|
||||
|
||||
TN extra_entries() const {
|
||||
TN number = 0;
|
||||
for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
|
||||
if(histo::is_out(parent::m_axes,ibin)) {
|
||||
number += parent::m_bin_entries[ibin];
|
||||
}
|
||||
}
|
||||
return number;
|
||||
return parent::m_all_entries-parent::m_in_range_entries; //works also is reading histo from a CERN-ROOT file.
|
||||
}
|
||||
*/
|
||||
TW equivalent_bin_entries() const {
|
||||
TW sw = 0;
|
||||
TW sw2 = 0;
|
||||
@@ -163,6 +165,67 @@ public:
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool has_entries_per_bin() const { //to detect histos coming from TH streaming out of a root file.
|
||||
// it assumes that update_fast_getters() had been applied.
|
||||
if(parent::m_in_range_entries) return true;
|
||||
// may be a from-root histo :
|
||||
if(parent::m_in_range_Sw) return false;
|
||||
// no in range entries and weight :
|
||||
return true; //for exa not filled = ok.
|
||||
}
|
||||
|
||||
public: //histo_data
|
||||
bool get_ith_axis_Sxw(dim_t a_axis,TC& a_value) const {
|
||||
a_value = 0;
|
||||
if(a_axis>=parent::m_dimension) return false;
|
||||
for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
|
||||
if(!histo::is_out(parent::m_axes,ibin)) {
|
||||
a_value += parent::m_bin_Sxw[ibin][a_axis];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_ith_axis_Sx2w(dim_t a_axis,TC& a_value) const {
|
||||
a_value = 0;
|
||||
if(a_axis>=parent::m_dimension) return false;
|
||||
for(TO ibin=0;ibin<parent::m_bin_number;ibin++) {
|
||||
if(!histo::is_out(parent::m_axes,ibin)) {
|
||||
a_value += parent::m_bin_Sx2w[ibin][a_axis];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TW get_in_range_Sw() const {return parent::m_in_range_Sw;} //for CERN-ROOT file writing.
|
||||
TW get_in_range_Sw2() const {return parent::m_in_range_Sw2;} //for CERN-ROOT file writing.
|
||||
|
||||
/*
|
||||
TW get_all_Sw() const {
|
||||
TW sw = 0;
|
||||
for(TO ibin=0;ibin<m_bin_number;ibin++) sw += m_bin_Sw[ibin];
|
||||
return sw;
|
||||
}
|
||||
TN get_all_entries() const {
|
||||
TN number = 0;
|
||||
for(TO ibin=0;ibin<m_bin_number;ibin++) {
|
||||
number += m_bin_entries[ibin];
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
// for inlib/wroot/streamers :
|
||||
TN get_entries() const {
|
||||
TN number = 0;
|
||||
for(TO ibin=0;ibin<m_bin_number;ibin++) {
|
||||
if(!histo::is_out(m_axes,ibin)) {
|
||||
number += m_bin_entries[ibin];
|
||||
}
|
||||
}
|
||||
return number;
|
||||
}
|
||||
*/
|
||||
protected:
|
||||
enum {AxisX=0,AxisY=1,AxisZ=2};
|
||||
|
||||
@@ -176,10 +239,14 @@ protected:
|
||||
parent::m_bin_Sw2.clear();
|
||||
parent::m_bin_Sxw.clear();
|
||||
parent::m_bin_Sx2w.clear();
|
||||
parent::m_in_range_Sxw.clear();
|
||||
parent::m_in_range_Sx2w.clear();
|
||||
parent::m_axes.clear();
|
||||
parent::m_in_range_plane_Sxyw.clear();
|
||||
parent::m_annotations.clear();
|
||||
|
||||
parent::m_bin_number = 0;
|
||||
parent::m_dimension = 0;
|
||||
parent::m_annotations.clear();
|
||||
parent::m_all_entries = 0;
|
||||
parent::m_in_range_entries = 0;
|
||||
parent::m_in_range_Sw = 0;
|
||||
@@ -217,10 +284,14 @@ protected:
|
||||
parent::m_bin_Sw2.clear();
|
||||
parent::m_bin_Sxw.clear();
|
||||
parent::m_bin_Sx2w.clear();
|
||||
parent::m_in_range_Sxw.clear();
|
||||
parent::m_in_range_Sx2w.clear();
|
||||
parent::m_axes.clear();
|
||||
parent::m_in_range_plane_Sxyw.clear();
|
||||
parent::m_annotations.clear();
|
||||
|
||||
parent::m_bin_number = 0;
|
||||
parent::m_dimension = 0;
|
||||
parent::m_annotations.clear();
|
||||
parent::m_all_entries = 0;
|
||||
parent::m_in_range_entries = 0;
|
||||
parent::m_in_range_Sw = 0;
|
||||
@@ -257,6 +328,7 @@ protected:
|
||||
parent::m_bin_Sx2w[ibin][iaxis] = 0;
|
||||
}
|
||||
}
|
||||
parent::m_in_range_plane_Sxyw.assign(dim_planes(parent::m_dimension),0);
|
||||
//profile not done here.
|
||||
parent::reset_fast_getters();
|
||||
}
|
||||
@@ -286,6 +358,7 @@ protected:
|
||||
parent::m_axes[iaxis].m_offset = parent::m_axes[iaxis-1].m_offset * (parent::m_axes[iaxis-1].bins()+2);
|
||||
}
|
||||
|
||||
parent::m_in_range_plane_Sxyw.resize(dim_planes(parent::m_dimension),0);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -295,10 +368,11 @@ public:
|
||||
const std::vector<TW>& bins_sum_w2() const {return parent::m_bin_Sw2;}
|
||||
const std::vector< std::vector<TC> >& bins_sum_xw() const {return parent::m_bin_Sxw;}
|
||||
const std::vector< std::vector<TC> >& bins_sum_x2w() const {return parent::m_bin_Sx2w;}
|
||||
const std::vector<TC>& in_range_planes_xyw() const {return parent::m_in_range_plane_Sxyw;}
|
||||
|
||||
public:
|
||||
const axis_t& get_axis(int aIndex) const {return parent::m_axes[aIndex];}
|
||||
TO get_bins() const {return parent::m_bin_number;}
|
||||
offset_t get_bins() const {return parent::m_bin_number;}
|
||||
const std::string& get_title() const {return parent::m_title;}
|
||||
dim_t get_dimension() const {return parent::m_dimension;}
|
||||
bool is_valid() const {return (parent::m_dimension?true:false);}
|
||||
@@ -338,6 +412,8 @@ protected:
|
||||
parent::m_bin_Sx2w[ibin][iaxis] += a_histo.m_bin_Sx2w[ibin][iaxis];
|
||||
}
|
||||
}
|
||||
{dim_t nplane = parent::m_in_range_plane_Sxyw.size();
|
||||
for(dim_t iplane=0;iplane<nplane;iplane++) parent::m_in_range_plane_Sxyw[iplane] += a_histo.m_in_range_plane_Sxyw[iplane];}
|
||||
parent::update_fast_getters();
|
||||
}
|
||||
|
||||
@@ -355,6 +431,9 @@ protected:
|
||||
parent::m_bin_Sx2w[ibin][iaxis] -= a_histo.m_bin_Sx2w[ibin][iaxis];
|
||||
}
|
||||
}
|
||||
|
||||
//{for(dim_t iplane=0;iplane<nplane;iplane++) parent::m_in_range_plane_Sxyw[iplane] ??? a_histo.m_in_range_plane_Sxyw[iplane];}
|
||||
|
||||
parent::update_fast_getters();
|
||||
}
|
||||
|
||||
@@ -364,7 +443,7 @@ protected:
|
||||
// We build a new histo with one entry in each bin of weight :
|
||||
// this.w * a_histo.w
|
||||
// The current histo is overriden with this new histo.
|
||||
// The m_bin_Sw2 computation is consistent with FreeHEP and ROOT.
|
||||
// The m_bin_Sw2 computation is consistent with FreeHEP and CERN-ROOT.
|
||||
|
||||
if(!is_compatible(a_histo)) return false;
|
||||
|
||||
@@ -386,6 +465,8 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
//{for(dim_t iplane=0;iplane<nplane;iplane++) parent::m_in_range_plane_Sxyw[iplane] ??? a_histo.m_in_range_plane_Sxyw[iplane];}
|
||||
|
||||
parent::update_fast_getters();
|
||||
return true;
|
||||
}
|
||||
@@ -428,6 +509,9 @@ protected:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//{for(dim_t iplane=0;iplane<nplane;iplane++) parent::m_in_range_plane_Sxyw[iplane] ??? a_histo.m_in_range_plane_Sxyw[iplane];}
|
||||
|
||||
parent::update_fast_getters();
|
||||
return true;
|
||||
}
|
||||
@@ -443,6 +527,8 @@ protected:
|
||||
parent::m_bin_Sx2w[ibin][iaxis] *= a_factor;
|
||||
}
|
||||
}
|
||||
{dim_t nplane = parent::m_in_range_plane_Sxyw.size();
|
||||
for(dim_t iplane=0;iplane<nplane;iplane++) parent::m_in_range_plane_Sxyw[iplane] *= a_factor;}
|
||||
parent::update_fast_getters();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,6 @@ public:
|
||||
|
||||
public:
|
||||
const std::string& title() const {return m_title;}
|
||||
std::string title() {return m_title;}
|
||||
|
||||
void set_title(const std::string& a_s) {m_title = a_s;}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
bool scale(TW a_factor) {return multiply(a_factor);}
|
||||
|
||||
void copy_from_data(const hd_t& a_from) {parent::base_from_data(a_from);}
|
||||
hd_t get_histo_data() const {return parent::base_get_data();}
|
||||
hd_t get_histo_data() const {return *this;} //deprecated. Keep it for g4tools.
|
||||
|
||||
bool reset() {
|
||||
parent::base_reset();
|
||||
@@ -68,6 +68,7 @@ public:
|
||||
|
||||
parent::m_all_entries++;
|
||||
if(inRange) {
|
||||
// fast getters :
|
||||
parent::m_in_range_entries++;
|
||||
parent::m_in_range_Sw += aWeight;
|
||||
parent::m_in_range_Sw2 += aWeight*aWeight;
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
bool scale(TW a_factor) {return multiply(a_factor);}
|
||||
|
||||
void copy_from_data(const hd_t& a_from) {parent::base_from_data(a_from);}
|
||||
hd_t get_histo_data() const {return parent::base_get_data();}
|
||||
hd_t get_histo_data() const {return *this;} //deprecated. Keep it for g4tools.
|
||||
|
||||
bool reset() {
|
||||
parent::base_reset();
|
||||
@@ -70,6 +70,9 @@ public:
|
||||
|
||||
parent::m_all_entries++;
|
||||
if(inRange) {
|
||||
parent::m_in_range_plane_Sxyw[0] += aX * aY * aWeight;
|
||||
|
||||
// fast getters :
|
||||
parent::m_in_range_entries++;
|
||||
parent::m_in_range_Sw += aWeight;
|
||||
parent::m_in_range_Sw2 += aWeight*aWeight;
|
||||
@@ -121,6 +124,8 @@ public:
|
||||
|
||||
parent::m_all_entries += a_entries;
|
||||
if(inRange) {
|
||||
//parent::m_in_range_plane_Sxyw[0] ??? ill-defined.
|
||||
|
||||
parent::m_in_range_entries += a_entries;
|
||||
parent::m_in_range_Sw += a_Sw;
|
||||
parent::m_in_range_Sw2 += a_Sw2;
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
bool scale(TW a_factor) {return multiply(a_factor);}
|
||||
|
||||
void copy_from_data(const hd_t& a_from) {parent::base_from_data(a_from);}
|
||||
hd_t get_histo_data() const {return parent::base_get_data();}
|
||||
hd_t get_histo_data() const {return *this;} //deprecated. Keep it for g4tools.
|
||||
|
||||
bool reset() {
|
||||
parent::base_reset();
|
||||
@@ -79,6 +79,11 @@ public:
|
||||
|
||||
parent::m_all_entries++;
|
||||
if(inRange) {
|
||||
parent::m_in_range_plane_Sxyw[0] += aX * aY * aWeight;
|
||||
parent::m_in_range_plane_Sxyw[1] += aY * aZ * aWeight;
|
||||
parent::m_in_range_plane_Sxyw[2] += aZ * aX * aWeight;
|
||||
|
||||
// fast getters :
|
||||
parent::m_in_range_entries++;
|
||||
parent::m_in_range_Sw += aWeight;
|
||||
parent::m_in_range_Sw2 += aWeight*aWeight;
|
||||
@@ -140,6 +145,8 @@ public:
|
||||
|
||||
parent::m_all_entries += a_entries;
|
||||
if(inRange) {
|
||||
//parent::m_in_range_plane_Sxyw[0,1,2] ??? ill-defined.
|
||||
|
||||
parent::m_in_range_entries += a_entries;
|
||||
parent::m_in_range_Sw += a_Sw;
|
||||
parent::m_in_range_Sw2 += a_Sw2;
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_histo_hd2mpi
|
||||
#define tools_histo_hd2mpi
|
||||
|
||||
// code to MPI_Pack, MPI_Unpack histos without having to include mpi.h.
|
||||
|
||||
#include "../impi"
|
||||
|
||||
#include "histo_data"
|
||||
|
||||
#include "../forit"
|
||||
|
||||
namespace tools {
|
||||
namespace histo {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// hist_data to mpi ////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool axis_dui_pack(impi& a_mpi,const axis<double,unsigned int>& a_axis) {
|
||||
//typedef double TC;
|
||||
//typedef unsigned int TO;
|
||||
//typedef unsigned int bn_t;
|
||||
if(!a_mpi.pack(a_axis.m_offset)) return false; //TO
|
||||
if(!a_mpi.pack(a_axis.m_number_of_bins)) return false; //bn_t
|
||||
if(!a_mpi.pack(a_axis.m_minimum_value)) return false; //TC
|
||||
if(!a_mpi.pack(a_axis.m_maximum_value)) return false; //TC
|
||||
if(!a_mpi.bpack(a_axis.m_fixed)) return false;
|
||||
if(!a_mpi.pack(a_axis.m_bin_width)) return false; //TC
|
||||
if(!a_mpi.vpack(a_axis.m_edges)) return false; //TC
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool histo_data_duiuid_pack(impi& a_mpi,const histo_data<double,unsigned int,unsigned int,double>& a_hd) {
|
||||
//typedef double TC;
|
||||
//typedef unsigned int TO;
|
||||
//typedef unsigned int TN;
|
||||
//typedef double TW;
|
||||
//typedef unsigned int dim_t;
|
||||
typedef unsigned int num_t;
|
||||
|
||||
if(!a_mpi.spack(a_hd.m_title)) return false;
|
||||
if(!a_mpi.pack(a_hd.m_dimension)) return false; //dim_t
|
||||
if(!a_mpi.pack(a_hd.m_bin_number)) return false; //TO
|
||||
if(!a_mpi.vpack(a_hd.m_bin_entries)) return false; //TN
|
||||
if(!a_mpi.vpack(a_hd.m_bin_Sw)) return false; //TW
|
||||
if(!a_mpi.vpack(a_hd.m_bin_Sw2)) return false; //TW
|
||||
|
||||
{for(unsigned int ibin=0;ibin<a_hd.m_bin_number;ibin++) {
|
||||
if(!a_mpi.vpack(a_hd.m_bin_Sxw[ibin])) return false;
|
||||
}}
|
||||
{for(unsigned int ibin=0;ibin<a_hd.m_bin_number;ibin++) {
|
||||
if(!a_mpi.vpack(a_hd.m_bin_Sx2w[ibin])) return false;
|
||||
}}
|
||||
|
||||
// Axes :
|
||||
{for(unsigned int iaxis=0;iaxis<a_hd.m_dimension;iaxis++) {
|
||||
if(!axis_dui_pack(a_mpi,a_hd.m_axes[iaxis])) return false;
|
||||
}}
|
||||
|
||||
// etc :
|
||||
if(!a_mpi.vpack(a_hd.m_in_range_plane_Sxyw)) return false; //TC
|
||||
|
||||
// Annotations :
|
||||
{if(!a_mpi.pack((num_t)a_hd.m_annotations.size())) return false; //num_t
|
||||
tools_mforcit(std::string,std::string,a_hd.m_annotations,it) {
|
||||
if(!a_mpi.spack((*it).first)) return false;
|
||||
if(!a_mpi.spack((*it).second)) return false;
|
||||
}}
|
||||
|
||||
// fast getters :
|
||||
if(!a_mpi.pack(a_hd.m_all_entries)) return false; //TN
|
||||
if(!a_mpi.pack(a_hd.m_in_range_entries)) return false; //TN
|
||||
if(!a_mpi.pack(a_hd.m_in_range_Sw)) return false; //TW
|
||||
if(!a_mpi.pack(a_hd.m_in_range_Sw2)) return false; //TW
|
||||
if(!a_mpi.vpack(a_hd.m_in_range_Sxw)) return false; //TC
|
||||
if(!a_mpi.vpack(a_hd.m_in_range_Sx2w)) return false; //TC
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// mpi to hist_data ////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool axis_dui_unpack(impi& a_mpi,axis<double,unsigned int>& a_axis) {
|
||||
//typedef double TC;
|
||||
//typedef unsigned int TO;
|
||||
//typedef unsigned int bn_t;
|
||||
|
||||
if(!a_mpi.unpack(a_axis.m_offset)) return false; //TO
|
||||
if(!a_mpi.unpack(a_axis.m_number_of_bins)) return false; //bn_t
|
||||
if(!a_mpi.unpack(a_axis.m_minimum_value)) return false; //TC
|
||||
if(!a_mpi.unpack(a_axis.m_maximum_value)) return false; //TC
|
||||
if(!a_mpi.bunpack(a_axis.m_fixed)) return false;
|
||||
if(!a_mpi.unpack(a_axis.m_bin_width)) return false; //TC
|
||||
if(!a_mpi.vunpack(a_axis.m_edges)) return false; //TC
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool histo_data_duiuid_unpack(impi& a_mpi,histo_data<double,unsigned int,unsigned int,double>& a_hd) {
|
||||
//typedef double TC;
|
||||
//typedef unsigned int TO;
|
||||
//typedef unsigned int TN;
|
||||
//typedef double TW;
|
||||
//typedef unsigned int dim_t;
|
||||
typedef unsigned int num_t;
|
||||
|
||||
if(!a_mpi.sunpack(a_hd.m_title)) return false;
|
||||
if(!a_mpi.unpack(a_hd.m_dimension)) return false; //dim_t
|
||||
if(!a_mpi.unpack(a_hd.m_bin_number)) return false; //TO
|
||||
if(!a_mpi.vunpack(a_hd.m_bin_entries)) return false; //TN
|
||||
if(!a_mpi.vunpack(a_hd.m_bin_Sw)) return false; //TW
|
||||
if(!a_mpi.vunpack(a_hd.m_bin_Sw2)) return false; //TW
|
||||
|
||||
{a_hd.m_bin_Sxw.resize(a_hd.m_bin_number);
|
||||
for(unsigned int ibin=0;ibin<a_hd.m_bin_number;ibin++) {
|
||||
if(!a_mpi.vunpack(a_hd.m_bin_Sxw[ibin])) return false;
|
||||
}}
|
||||
{a_hd.m_bin_Sx2w.resize(a_hd.m_bin_number);
|
||||
for(unsigned int ibin=0;ibin<a_hd.m_bin_number;ibin++) {
|
||||
if(!a_mpi.vunpack(a_hd.m_bin_Sx2w[ibin])) return false;
|
||||
}}
|
||||
|
||||
// Axes :
|
||||
{a_hd.m_axes.resize(a_hd.m_dimension);
|
||||
for(unsigned int iaxis=0;iaxis<a_hd.m_dimension;iaxis++) {
|
||||
if(!axis_dui_unpack(a_mpi,a_hd.m_axes[iaxis])) return false;
|
||||
}}
|
||||
|
||||
// etc :
|
||||
if(!a_mpi.vunpack(a_hd.m_in_range_plane_Sxyw)) return false; //TC
|
||||
|
||||
// Annotations :
|
||||
{a_hd.m_annotations.clear();
|
||||
num_t num;
|
||||
if(!a_mpi.unpack(num)) return false;
|
||||
for(unsigned int index=0;index<num;index++) {
|
||||
std::string k,v;
|
||||
if(!a_mpi.sunpack(k)) return false;
|
||||
if(!a_mpi.sunpack(v)) return false;
|
||||
a_hd.m_annotations[k] = v;
|
||||
}}
|
||||
|
||||
// fast getters :
|
||||
if(!a_mpi.unpack(a_hd.m_all_entries)) return false; //TN
|
||||
if(!a_mpi.unpack(a_hd.m_in_range_entries)) return false; //TN
|
||||
if(!a_mpi.unpack(a_hd.m_in_range_Sw)) return false; //TW
|
||||
if(!a_mpi.unpack(a_hd.m_in_range_Sw2)) return false; //TW
|
||||
if(!a_mpi.vunpack(a_hd.m_in_range_Sxw)) return false; //TC
|
||||
if(!a_mpi.vunpack(a_hd.m_in_range_Sx2w)) return false; //TC
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#include "profile_data"
|
||||
|
||||
namespace tools {
|
||||
namespace histo {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// profile_data to C struct ////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool profile_data_duiuidd_pack(impi& a_mpi,const profile_data<double,unsigned int,unsigned int,double,double>& a_pd) {
|
||||
|
||||
if(!histo_data_duiuid_pack(a_mpi,a_pd)) return false;
|
||||
|
||||
//typedef double TV;
|
||||
|
||||
if(!a_mpi.bpack(a_pd.m_is_profile)) return false;
|
||||
if(!a_mpi.vpack(a_pd.m_bin_Svw)) return false; //TV
|
||||
if(!a_mpi.vpack(a_pd.m_bin_Sv2w)) return false; //TV
|
||||
if(!a_mpi.bpack(a_pd.m_cut_v)) return false;
|
||||
if(!a_mpi.pack(a_pd.m_min_v)) return false; //TV
|
||||
if(!a_mpi.pack(a_pd.m_max_v)) return false; //TV
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// mpi to profile_data /////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool profile_data_duiuidd_unpack(impi& a_mpi,profile_data<double,unsigned int,unsigned int,double,double>& a_pd) {
|
||||
|
||||
if(!histo_data_duiuid_unpack(a_mpi,a_pd)) return false;
|
||||
|
||||
//typedef double TV;
|
||||
|
||||
if(!a_mpi.bunpack(a_pd.m_is_profile)) return false;
|
||||
if(!a_mpi.vunpack(a_pd.m_bin_Svw)) return false; //TV
|
||||
if(!a_mpi.vunpack(a_pd.m_bin_Sv2w)) return false; //TV
|
||||
if(!a_mpi.bunpack(a_pd.m_cut_v)) return false;
|
||||
if(!a_mpi.unpack(a_pd.m_min_v)) return false; //TV
|
||||
if(!a_mpi.unpack(a_pd.m_max_v)) return false; //TV
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,17 @@
|
||||
namespace tools {
|
||||
namespace histo {
|
||||
|
||||
inline unsigned int dim_planes(unsigned int a_dim) {
|
||||
// m_dim = 1 -> 0
|
||||
// m_dim = 2 -> 0+1=1
|
||||
// m_dim = 3 -> 0+1+2=3
|
||||
// m_dim = 4 -> 0+1+2+3=6
|
||||
typedef unsigned int dim_t;
|
||||
dim_t n = 0;
|
||||
for(dim_t i=0;i<a_dim;i++) n += i;
|
||||
return n;
|
||||
}
|
||||
|
||||
//TC is for a coordinate.
|
||||
//TO is for an offset used to identify a bin.
|
||||
//TN is for a number of entries.
|
||||
@@ -22,6 +33,7 @@ class histo_data {
|
||||
public:
|
||||
typedef axis<TC,TO> axis_t;
|
||||
typedef unsigned int dim_t;
|
||||
typedef std::map<std::string,std::string> annotations_t;
|
||||
public:
|
||||
histo_data()
|
||||
:m_dimension(0)
|
||||
@@ -42,6 +54,7 @@ public:
|
||||
,m_bin_Sxw(a_from.m_bin_Sxw)
|
||||
,m_bin_Sx2w(a_from.m_bin_Sx2w)
|
||||
,m_axes(a_from.m_axes)
|
||||
,m_in_range_plane_Sxyw(a_from.m_in_range_plane_Sxyw)
|
||||
,m_annotations(a_from.m_annotations)
|
||||
,m_all_entries(a_from.m_all_entries)
|
||||
,m_in_range_entries(a_from.m_in_range_entries)
|
||||
@@ -62,6 +75,7 @@ public:
|
||||
m_bin_Sxw = a_from.m_bin_Sxw;
|
||||
m_bin_Sx2w = a_from.m_bin_Sx2w;
|
||||
m_axes = a_from.m_axes;
|
||||
m_in_range_plane_Sxyw = a_from.m_in_range_plane_Sxyw;
|
||||
m_annotations = a_from.m_annotations;
|
||||
m_all_entries = a_from.m_all_entries;
|
||||
m_in_range_entries = a_from.m_in_range_entries;
|
||||
@@ -73,85 +87,15 @@ public:
|
||||
}
|
||||
|
||||
virtual ~histo_data(){}
|
||||
|
||||
public:
|
||||
|
||||
// for inlib/rroot/streamers :
|
||||
TW get_Sw() const {
|
||||
TW sw = 0;
|
||||
for(TO ibin=0;ibin<m_bin_number;ibin++) {
|
||||
if(!histo::is_out(m_axes,ibin)) {
|
||||
sw += m_bin_Sw[ibin];
|
||||
}
|
||||
}
|
||||
return sw;
|
||||
}
|
||||
/*
|
||||
TW get_all_Sw() const {
|
||||
TW sw = 0;
|
||||
for(TO ibin=0;ibin<m_bin_number;ibin++) sw += m_bin_Sw[ibin];
|
||||
return sw;
|
||||
}
|
||||
TN get_all_entries() const {
|
||||
TN number = 0;
|
||||
for(TO ibin=0;ibin<m_bin_number;ibin++) {
|
||||
number += m_bin_entries[ibin];
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
// for inlib/wroot/streamers :
|
||||
TN get_entries() const {
|
||||
TN number = 0;
|
||||
for(TO ibin=0;ibin<m_bin_number;ibin++) {
|
||||
if(!histo::is_out(m_axes,ibin)) {
|
||||
number += m_bin_entries[ibin];
|
||||
}
|
||||
}
|
||||
return number;
|
||||
}
|
||||
*/
|
||||
|
||||
TW get_Sw2() const {
|
||||
TW sw2 = 0;
|
||||
for(TO ibin=0;ibin<m_bin_number;ibin++) {
|
||||
if(!histo::is_out(m_axes,ibin)) {
|
||||
sw2 += m_bin_Sw2[ibin];
|
||||
}
|
||||
}
|
||||
return sw2;
|
||||
}
|
||||
|
||||
bool get_ith_axis_Sxw(dim_t a_axis,TC& a_value) const {
|
||||
a_value = 0;
|
||||
if(a_axis>=m_dimension) return false;
|
||||
for(TO ibin=0;ibin<m_bin_number;ibin++) {
|
||||
if(!histo::is_out(m_axes,ibin)) {
|
||||
a_value += m_bin_Sxw[ibin][a_axis];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_ith_axis_Sx2w(dim_t a_axis,TC& a_value) const {
|
||||
a_value = 0;
|
||||
if(a_axis>=m_dimension) return false;
|
||||
for(TO ibin=0;ibin<m_bin_number;ibin++) {
|
||||
if(!histo::is_out(m_axes,ibin)) {
|
||||
a_value += m_bin_Sx2w[ibin][a_axis];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void reset_fast_getters(){
|
||||
//m_in_range_plane_Sxyw is not a fast getter.
|
||||
m_all_entries = 0;
|
||||
m_in_range_entries = 0;
|
||||
m_in_range_Sw = 0;
|
||||
m_in_range_Sw2 = 0;
|
||||
m_in_range_Sxw.resize(m_dimension,0);
|
||||
m_in_range_Sx2w.resize(m_dimension,0);
|
||||
m_in_range_Sxw.assign(m_dimension,0);
|
||||
m_in_range_Sx2w.assign(m_dimension,0);
|
||||
}
|
||||
public:
|
||||
void update_fast_getters() {
|
||||
@@ -184,6 +128,7 @@ public:
|
||||
// Axes :
|
||||
std::vector<axis_t> m_axes;
|
||||
// etc :
|
||||
std::vector<TC> m_in_range_plane_Sxyw; // ill-defined relative to slicing, sub, div, mult operations. Handled because of CERN-ROOT.
|
||||
std::map<std::string,std::string> m_annotations;
|
||||
// fast getters :
|
||||
TN m_all_entries; //used if reading from a ROOT file.
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_histo_histos
|
||||
#define tools_histo_histos
|
||||
|
||||
#include "h1d"
|
||||
#include "h2d"
|
||||
#include "h3d"
|
||||
#include "p1d"
|
||||
#include "p2d"
|
||||
|
||||
#include "../forit"
|
||||
|
||||
namespace tools {
|
||||
namespace histo {
|
||||
|
||||
inline void delete_histos(std::vector< std::pair<std::string,void*> >& a_hists) {
|
||||
typedef std::pair<std::string,void*> class_pointer;
|
||||
|
||||
tools_vforit(class_pointer,a_hists,it) {
|
||||
const std::string& scls = (*it).first;
|
||||
if(scls==h1d::s_class()) {
|
||||
h1d* h = (h1d*)(*it).second;
|
||||
delete h;
|
||||
|
||||
} else if(scls==h2d::s_class()) {
|
||||
h2d* h = (h2d*)(*it).second;
|
||||
delete h;
|
||||
|
||||
} else if(scls==h3d::s_class()) {
|
||||
h3d* h = (h3d*)(*it).second;
|
||||
delete h;
|
||||
|
||||
} else if(scls==p1d::s_class()) {
|
||||
p1d* h = (p1d*)(*it).second;
|
||||
delete h;
|
||||
|
||||
} else if(scls==p2d::s_class()) {
|
||||
p2d* h = (p2d*)(*it).second;
|
||||
delete h;
|
||||
}
|
||||
}
|
||||
a_hists.clear();
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_histo_hmpi
|
||||
#define tools_histo_hmpi
|
||||
|
||||
namespace tools {
|
||||
namespace histo {
|
||||
class h1d;
|
||||
class h2d;
|
||||
class h3d;
|
||||
class p1d;
|
||||
class p2d;
|
||||
}}
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace tools {
|
||||
namespace histo {
|
||||
|
||||
class hmpi {
|
||||
public:
|
||||
virtual ~hmpi(){}
|
||||
public:
|
||||
virtual bool pack(const h1d&) = 0;
|
||||
virtual bool pack(const h2d&) = 0;
|
||||
virtual bool pack(const h3d&) = 0;
|
||||
virtual bool pack(const p1d&) = 0;
|
||||
virtual bool pack(const p2d&) = 0;
|
||||
|
||||
virtual bool beg_send(unsigned int /*a_nhist*/) = 0;
|
||||
virtual bool send(int /*a_dest*/) = 0;
|
||||
|
||||
virtual bool wait_histos(int /*a_src*/,std::vector< std::pair<std::string,void*> >& /*a_hists*/) = 0;
|
||||
|
||||
virtual int rank() const = 0;
|
||||
virtual bool comm_rank(int&) const = 0;
|
||||
virtual bool comm_size(int&) const = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@ namespace histo {
|
||||
|
||||
//TC is for a coordinate.
|
||||
//TO is for an offset/index to identify/find a bind.
|
||||
//TN is for a number of entries.
|
||||
//TW is for a weight.
|
||||
//TH is for a height. Should be the same as TV.
|
||||
//TV is for a value (in general same as TC).
|
||||
@@ -96,7 +97,7 @@ public:
|
||||
m_max_v = a_from.m_max_v;
|
||||
}
|
||||
pd_t get_histo_data() const {
|
||||
pd_t hd(parent::base_get_data());
|
||||
pd_t hd(parent::dac());
|
||||
hd.m_is_profile = true;
|
||||
hd.m_bin_Svw = m_bin_Svw;
|
||||
hd.m_bin_Sv2w = m_bin_Sv2w;
|
||||
@@ -134,6 +135,7 @@ public:
|
||||
|
||||
parent::m_all_entries++;
|
||||
if(inRange) {
|
||||
// fast getters :
|
||||
parent::m_in_range_entries++;
|
||||
parent::m_in_range_Sw += aWeight;
|
||||
parent::m_in_range_Sw2 += aWeight*aWeight;
|
||||
@@ -319,6 +321,8 @@ public:
|
||||
public:
|
||||
bool configure(bn_t aXnumber,TC aXmin,TC aXmax){
|
||||
if(!parent::configure(aXnumber,aXmin,aXmax)) return false;
|
||||
m_bin_Svw.clear();
|
||||
m_bin_Sv2w.clear();
|
||||
m_bin_Svw.resize(parent::m_bin_number,0);
|
||||
m_bin_Sv2w.resize(parent::m_bin_number,0);
|
||||
m_cut_v = false;
|
||||
@@ -328,6 +332,8 @@ public:
|
||||
}
|
||||
bool configure(const std::vector<TC>& aEdges) {
|
||||
if(!parent::configure(aEdges)) return false;
|
||||
m_bin_Svw.clear();
|
||||
m_bin_Sv2w.clear();
|
||||
m_bin_Svw.resize(parent::m_bin_number,0);
|
||||
m_bin_Sv2w.resize(parent::m_bin_number,0);
|
||||
m_cut_v = false;
|
||||
@@ -337,6 +343,8 @@ public:
|
||||
}
|
||||
bool configure(bn_t aXnumber,TC aXmin,TC aXmax,TV aVmin,TV aVmax){
|
||||
if(!parent::configure(aXnumber,aXmin,aXmax)) return false;
|
||||
m_bin_Svw.clear();
|
||||
m_bin_Sv2w.clear();
|
||||
m_bin_Svw.resize(parent::m_bin_number,0);
|
||||
m_bin_Sv2w.resize(parent::m_bin_number,0);
|
||||
m_cut_v = true;
|
||||
@@ -346,6 +354,8 @@ public:
|
||||
}
|
||||
bool configure(const std::vector<TC>& aEdges,TV aVmin,TV aVmax) {
|
||||
if(!parent::configure(aEdges)) return false;
|
||||
m_bin_Svw.clear();
|
||||
m_bin_Sv2w.clear();
|
||||
m_bin_Svw.resize(parent::m_bin_number,0);
|
||||
m_bin_Sv2w.resize(parent::m_bin_number,0);
|
||||
m_cut_v = true;
|
||||
|
||||
@@ -22,21 +22,16 @@ public:
|
||||
:parent(a_title,aXnumber,aXmin,aXmax)
|
||||
{}
|
||||
|
||||
p1d(const std::string& a_title,
|
||||
unsigned int aXnumber,double aXmin,double aXmax,
|
||||
double aVmin,double aVmax)
|
||||
: parent(a_title,aXnumber,aXmin,aXmax,aVmin,aVmax)
|
||||
p1d(const std::string& a_title,unsigned int aXnumber,double aXmin,double aXmax,double aVmin,double aVmax)
|
||||
:parent(a_title,aXnumber,aXmin,aXmax,aVmin,aVmax)
|
||||
{}
|
||||
|
||||
p1d(const std::string& a_title,
|
||||
const std::vector<double>& aEdges)
|
||||
: parent(a_title,aEdges)
|
||||
p1d(const std::string& a_title,const std::vector<double>& aEdges)
|
||||
:parent(a_title,aEdges)
|
||||
{}
|
||||
|
||||
p1d(const std::string& a_title,
|
||||
const std::vector<double>& aEdges,
|
||||
double aVmin,double aVmax)
|
||||
: parent(a_title,aEdges,aVmin,aVmax)
|
||||
p1d(const std::string& a_title,const std::vector<double>& aEdges,double aVmin,double aVmax)
|
||||
:parent(a_title,aEdges,aVmin,aVmax)
|
||||
{}
|
||||
|
||||
virtual ~p1d(){}
|
||||
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
m_max_v = a_from.m_max_v;
|
||||
}
|
||||
pd_t get_histo_data() const {
|
||||
pd_t hd(parent::base_get_data());
|
||||
pd_t hd(parent::dac());
|
||||
hd.m_is_profile = true;
|
||||
hd.m_bin_Svw = m_bin_Svw;
|
||||
hd.m_bin_Sv2w = m_bin_Sv2w;
|
||||
@@ -136,6 +136,9 @@ public:
|
||||
|
||||
parent::m_all_entries++;
|
||||
if(inRange) {
|
||||
parent::m_in_range_plane_Sxyw[0] += aX * aY * aWeight;
|
||||
|
||||
// fast getters :
|
||||
parent::m_in_range_entries++;
|
||||
parent::m_in_range_Sw += aWeight;
|
||||
parent::m_in_range_Sw2 += aWeight*aWeight;
|
||||
@@ -260,6 +263,8 @@ public:
|
||||
public:
|
||||
bool configure(bn_t aXnumber,TC aXmin,TC aXmax,bn_t aYnumber,TC aYmin,TC aYmax){
|
||||
if(!parent::configure(aXnumber,aXmin,aXmax,aYnumber,aYmin,aYmax)) return false;
|
||||
m_bin_Svw.clear();
|
||||
m_bin_Sv2w.clear();
|
||||
m_bin_Svw.resize(parent::m_bin_number,0);
|
||||
m_bin_Sv2w.resize(parent::m_bin_number,0);
|
||||
m_cut_v = false;
|
||||
@@ -269,6 +274,8 @@ public:
|
||||
}
|
||||
bool configure(const std::vector<TC>& aEdgesX,const std::vector<TC>& aEdgesY) {
|
||||
if(!parent::configure(aEdgesX,aEdgesY)) return false;
|
||||
m_bin_Svw.clear();
|
||||
m_bin_Sv2w.clear();
|
||||
m_bin_Svw.resize(parent::m_bin_number,0);
|
||||
m_bin_Sv2w.resize(parent::m_bin_number,0);
|
||||
m_cut_v = false;
|
||||
@@ -278,6 +285,8 @@ public:
|
||||
}
|
||||
bool configure(bn_t aXnumber,TC aXmin,TC aXmax,bn_t aYnumber,TC aYmin,TC aYmax,TV aVmin,TV aVmax){
|
||||
if(!parent::configure(aXnumber,aXmin,aXmax,aYnumber,aYmin,aYmax)) return false;
|
||||
m_bin_Svw.clear();
|
||||
m_bin_Sv2w.clear();
|
||||
m_bin_Svw.resize(parent::m_bin_number,0);
|
||||
m_bin_Sv2w.resize(parent::m_bin_number,0);
|
||||
m_cut_v = true;
|
||||
@@ -287,6 +296,8 @@ public:
|
||||
}
|
||||
bool configure(const std::vector<TC>& aEdgesX,const std::vector<TC>& aEdgesY,TV aVmin,TV aVmax) {
|
||||
if(!parent::configure(aEdgesX,aEdgesY)) return false;
|
||||
m_bin_Svw.clear();
|
||||
m_bin_Sv2w.clear();
|
||||
m_bin_Svw.resize(parent::m_bin_number,0);
|
||||
m_bin_Sv2w.resize(parent::m_bin_number,0);
|
||||
m_cut_v = true;
|
||||
|
||||
@@ -21,28 +21,27 @@ public:
|
||||
p2d(const std::string& a_title,
|
||||
unsigned int aXnumber,double aXmin,double aXmax,
|
||||
unsigned int aYnumber,double aYmin,double aYmax)
|
||||
: parent(a_title,aXnumber,aXmin,aXmax,
|
||||
aYnumber,aYmin,aYmax)
|
||||
:parent(a_title,aXnumber,aXmin,aXmax,aYnumber,aYmin,aYmax)
|
||||
{}
|
||||
|
||||
p2d(const std::string& a_title,
|
||||
unsigned int aXnumber,double aXmin,double aXmax,
|
||||
unsigned int aYnumber,double aYmin,double aYmax,
|
||||
double aVmin,double aVmax)
|
||||
: parent(a_title,aXnumber,aXmin,aXmax,aYnumber,aYmin,aYmax,aVmin,aVmax)
|
||||
:parent(a_title,aXnumber,aXmin,aXmax,aYnumber,aYmin,aYmax,aVmin,aVmax)
|
||||
{}
|
||||
|
||||
p2d(const std::string& a_title,
|
||||
const std::vector<double>& aEdgesX,
|
||||
const std::vector<double>& aEdgesY)
|
||||
: parent(a_title,aEdgesX,aEdgesY)
|
||||
:parent(a_title,aEdgesX,aEdgesY)
|
||||
{}
|
||||
|
||||
p2d(const std::string& a_title,
|
||||
const std::vector<double>& aEdgesX,
|
||||
const std::vector<double>& aEdgesY,
|
||||
double aVmin,double aVmax)
|
||||
: parent(a_title,aEdgesX,aEdgesY,aVmin,aVmax)
|
||||
:parent(a_title,aEdgesX,aEdgesY,aVmin,aVmax)
|
||||
{}
|
||||
|
||||
virtual ~p2d(){}
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace histo {
|
||||
template <class TC,class TO,class TN,class TW,class TV>
|
||||
class profile_data : public histo_data<TC,TO,TN,TW> {
|
||||
typedef histo_data<TC,TO,TN,TW> parent;
|
||||
public:
|
||||
typedef std::vector<TV> vs_t;
|
||||
public:
|
||||
profile_data()
|
||||
:parent()
|
||||
|
||||
@@ -4,21 +4,21 @@
|
||||
#ifndef tools_histo_slice
|
||||
#define tools_histo_slice
|
||||
|
||||
#include "h1"
|
||||
#include "h2"
|
||||
#include "h3"
|
||||
#include "axis"
|
||||
|
||||
namespace tools {
|
||||
namespace histo {
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline bool fill_slice_x(const h2<TC,TO,TN,TW,TH>& a_from,
|
||||
int aJbeg,int aJend,
|
||||
h1<TC,TO,TN,TW,TH>& a_to) {
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// h2 -> h1 ////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class H2,class H1>
|
||||
inline bool fill_slice_x(const H2& a_from,int aJbeg,int aJend,H1& a_to) {
|
||||
|
||||
if(!a_from.dimension()) return false;
|
||||
|
||||
typedef typename axis<TC,TO>::bn_t bn_t;
|
||||
typedef typename H2::bn_t bn_t;
|
||||
|
||||
bn_t jbeg;
|
||||
if(!a_from.axis_y().in_range_to_absolute_index(aJbeg,jbeg)) return false;
|
||||
@@ -28,11 +28,16 @@ inline bool fill_slice_x(const h2<TC,TO,TN,TW,TH>& a_from,
|
||||
|
||||
if(a_from.axis_x().bins()!=a_to.axis().bins()) return false;
|
||||
|
||||
histo_data<TC,TO,TN,TW> hdata = a_to.get_histo_data();
|
||||
typedef typename H1::hd_t hd_t;
|
||||
hd_t hdata = a_to.dac();
|
||||
|
||||
bn_t aoffset,offset,jbin;
|
||||
bn_t yoffset = a_from.axis_y().m_offset;
|
||||
|
||||
typedef typename H2::num_entries_t TN;
|
||||
typedef typename H2::weight_t TW;
|
||||
typedef typename H2::coordinate_t TC;
|
||||
|
||||
const std::vector<TN>& af_bin_entries = a_from.bins_entries();
|
||||
const std::vector<TW>& af_bin_Sw = a_from.bins_sum_w();
|
||||
const std::vector<TW>& af_bin_Sw2 = a_from.bins_sum_w2();
|
||||
@@ -56,36 +61,32 @@ inline bool fill_slice_x(const h2<TC,TO,TN,TW,TH>& a_from,
|
||||
hdata.m_bin_Sx2w[aoffset][0] += af_bin_Sx2w[offset][0];
|
||||
}
|
||||
}
|
||||
|
||||
hdata.m_in_range_plane_Sxyw.assign(a_to.number_of_planes(),0); //ill-defined.
|
||||
|
||||
hdata.update_fast_getters();
|
||||
a_to.copy_from_data(hdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline h1<TC,TO,TN,TW,TH>* slice_x(const h2<TC,TO,TN,TW,TH>& a_from,
|
||||
int aJbeg,int aJend,
|
||||
const std::string& a_title) {
|
||||
h1<TC,TO,TN,TW,TH>* slice = new h1<TC,TO,TN,TW,TH>(a_title,
|
||||
a_from.axis_x().bins(),
|
||||
a_from.axis_x().lower_edge(),
|
||||
a_from.axis_x().upper_edge());
|
||||
template <class H2,class H1>
|
||||
inline H1* slice_x(const H2& a_from,int aJbeg,int aJend,const std::string& a_title) {
|
||||
H1* slice = new H1(a_title,a_from.axis_x().bins(),a_from.axis_x().lower_edge(),a_from.axis_x().upper_edge());
|
||||
if(!fill_slice_x(a_from,aJbeg,aJend,*slice)) {delete slice;return 0;}
|
||||
return slice;
|
||||
}
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline h1<TC,TO,TN,TW,TH>* projection_x(const h2<TC,TO,TN,TW,TH>& a_from,const std::string& a_title) {
|
||||
return slice_x(a_from,axis<TC,TO>::UNDERFLOW_BIN,axis<TC,TO>::OVERFLOW_BIN,a_title);
|
||||
template <class H2,class H1>
|
||||
inline H1* projection_x(const H2& a_from,const std::string& a_title) {
|
||||
return slice_x(a_from,axis_UNDERFLOW_BIN,axis_OVERFLOW_BIN,a_title);
|
||||
}
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline bool fill_slice_y(const h2<TC,TO,TN,TW,TH>& a_from,
|
||||
int aIbeg,int aIend,
|
||||
h1<TC,TO,TN,TW,TH>& a_to) {
|
||||
template <class H2,class H1>
|
||||
inline bool fill_slice_y(const H2& a_from,int aIbeg,int aIend,H1& a_to) {
|
||||
|
||||
if(!a_from.dimension()) return false;
|
||||
|
||||
typedef typename axis<TC,TO>::bn_t bn_t;
|
||||
typedef typename H2::bn_t bn_t;
|
||||
|
||||
bn_t ibeg;
|
||||
if(!a_from.axis_x().in_range_to_absolute_index(aIbeg,ibeg)) return false;
|
||||
@@ -95,11 +96,16 @@ inline bool fill_slice_y(const h2<TC,TO,TN,TW,TH>& a_from,
|
||||
|
||||
if(a_from.axis_y().bins()!=a_to.axis().bins()) return false;
|
||||
|
||||
histo_data<TC,TO,TN,TW> hdata = a_to.get_histo_data();
|
||||
typedef typename H1::hd_t hd_t;
|
||||
hd_t hdata = a_to.dac();
|
||||
|
||||
bn_t aibin,aoffset,offset,ibin;
|
||||
bn_t yoffset = a_from.axis_y().m_offset;
|
||||
|
||||
typedef typename H2::num_entries_t TN;
|
||||
typedef typename H2::weight_t TW;
|
||||
typedef typename H2::coordinate_t TC;
|
||||
|
||||
const std::vector<TN>& af_bin_entries = a_from.bins_entries();
|
||||
const std::vector<TW>& af_bin_Sw = a_from.bins_sum_w();
|
||||
const std::vector<TW>& af_bin_Sw2 = a_from.bins_sum_w2();
|
||||
@@ -123,36 +129,158 @@ inline bool fill_slice_y(const h2<TC,TO,TN,TW,TH>& a_from,
|
||||
hdata.m_bin_Sx2w[aoffset][0] += af_bin_Sx2w[offset][1];
|
||||
}
|
||||
}
|
||||
|
||||
hdata.m_in_range_plane_Sxyw.assign(a_to.number_of_planes(),0); //ill-defined.
|
||||
|
||||
hdata.update_fast_getters();
|
||||
a_to.copy_from_data(hdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline h1<TC,TO,TN,TW,TH>* slice_y(const h2<TC,TO,TN,TW,TH>& a_from,
|
||||
int aIbeg,int aIend,
|
||||
const std::string& a_title) {
|
||||
h1<TC,TO,TN,TW,TH>* slice = new h1<TC,TO,TN,TW,TH>(a_title,
|
||||
a_from.axis_y().bins(),
|
||||
a_from.axis_y().lower_edge(),
|
||||
a_from.axis_y().upper_edge());
|
||||
template <class H2,class H1>
|
||||
inline H1* slice_y(const H2& a_from,int aIbeg,int aIend,const std::string& a_title) {
|
||||
H1* slice = new H1(a_title,a_from.axis_y().bins(),a_from.axis_y().lower_edge(),a_from.axis_y().upper_edge());
|
||||
if(!fill_slice_y(a_from,aIbeg,aIend,*slice)) {delete slice;return 0;}
|
||||
return slice;
|
||||
}
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline h1<TC,TO,TN,TW,TH>* projection_y(const h2<TC,TO,TN,TW,TH>& a_from,const std::string& a_title) {
|
||||
return slice_y(a_from,axis<TC,TO>::UNDERFLOW_BIN,axis<TC,TO>::OVERFLOW_BIN,a_title);
|
||||
template <class H2,class H1>
|
||||
inline H1* projection_y(const H2& a_from,const std::string& a_title) {
|
||||
return slice_y(a_from,axis_UNDERFLOW_BIN,axis_OVERFLOW_BIN,a_title);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// h2 -> p1 ////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline bool fill_slice_yz(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
int aIbeg,int aIend,h2<TC,TO,TN,TW,TH>& a_to) {
|
||||
template <class H2,class P1>
|
||||
inline bool fill_profile_x(const H2& a_from,int aJbeg,int aJend,P1& a_to) {
|
||||
if(!a_from.dimension()) return false;
|
||||
|
||||
typedef typename H2::bn_t bn_t;
|
||||
|
||||
bn_t jbeg;
|
||||
if(!a_from.axis_y().in_range_to_absolute_index(aJbeg,jbeg)) return false;
|
||||
bn_t jend;
|
||||
if(!a_from.axis_y().in_range_to_absolute_index(aJend,jend)) return false;
|
||||
if(jbeg>jend) return false;
|
||||
|
||||
if(a_from.axis_x().bins()!=a_to.axis().bins()) return false;
|
||||
|
||||
typedef typename P1::pd_t pd_t;
|
||||
pd_t hdata = a_to.get_histo_data();
|
||||
|
||||
bn_t aoffset,offset,jbin;
|
||||
bn_t yoffset = a_from.axis_y().m_offset;
|
||||
|
||||
typedef typename H2::num_entries_t TN;
|
||||
typedef typename H2::weight_t TW;
|
||||
typedef typename H2::coordinate_t TC;
|
||||
|
||||
const std::vector<TN>& af_bin_entries = a_from.bins_entries();
|
||||
const std::vector<TW>& af_bin_Sw = a_from.bins_sum_w();
|
||||
const std::vector<TW>& af_bin_Sw2 = a_from.bins_sum_w2();
|
||||
const std::vector< std::vector<TC> >& af_bin_Sxw = a_from.bins_sum_xw();
|
||||
const std::vector< std::vector<TC> >& af_bin_Sx2w = a_from.bins_sum_x2w();
|
||||
|
||||
// Fill also the outflow.
|
||||
bn_t abins = hdata.m_axes[0].bins()+2;
|
||||
for(bn_t aibin=0;aibin<abins;aibin++) {
|
||||
//offset1D = ibin
|
||||
aoffset = aibin;
|
||||
for(jbin=jbeg;jbin<=jend;jbin++) {
|
||||
//offset2D = ibin + jbin * yoffset
|
||||
// hdata booked with x then :
|
||||
offset = aibin + jbin * yoffset;
|
||||
// Bin :
|
||||
hdata.m_bin_entries[aoffset] += af_bin_entries[offset];
|
||||
hdata.m_bin_Sw[aoffset] += af_bin_Sw[offset];
|
||||
hdata.m_bin_Sw2[aoffset] += af_bin_Sw2[offset];
|
||||
hdata.m_bin_Sxw[aoffset][0] += af_bin_Sxw[offset][0];
|
||||
hdata.m_bin_Sx2w[aoffset][0] += af_bin_Sx2w[offset][0];
|
||||
|
||||
hdata.m_bin_Svw[aoffset] += af_bin_Sxw[offset][1];
|
||||
hdata.m_bin_Sv2w[aoffset] += af_bin_Sx2w[offset][1];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
hdata.m_in_range_plane_Sxyw.assign(a_to.number_of_planes(),0); //ill-defined.
|
||||
|
||||
hdata.update_fast_getters();
|
||||
a_to.copy_from_data(hdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class H2,class P1>
|
||||
inline bool fill_profile_y(const H2& a_from,int aIbeg,int aIend,P1& a_to) {
|
||||
|
||||
if(!a_from.dimension()) return false;
|
||||
|
||||
typedef typename axis<TC,TO>::bn_t bn_t;
|
||||
typedef typename H2::bn_t bn_t;
|
||||
|
||||
bn_t ibeg;
|
||||
if(!a_from.axis_x().in_range_to_absolute_index(aIbeg,ibeg)) return false;
|
||||
bn_t iend;
|
||||
if(!a_from.axis_x().in_range_to_absolute_index(aIend,iend)) return false;
|
||||
if(ibeg>iend) return false;
|
||||
|
||||
if(a_from.axis_y().bins()!=a_to.axis().bins()) return false;
|
||||
|
||||
typedef typename P1::pd_t pd_t;
|
||||
pd_t hdata = a_to.get_histo_data();
|
||||
|
||||
bn_t aibin,aoffset,offset,ibin;
|
||||
bn_t yoffset = a_from.axis_y().m_offset;
|
||||
|
||||
typedef typename H2::num_entries_t TN;
|
||||
typedef typename H2::weight_t TW;
|
||||
typedef typename H2::coordinate_t TC;
|
||||
|
||||
const std::vector<TN>& af_bin_entries = a_from.bins_entries();
|
||||
const std::vector<TW>& af_bin_Sw = a_from.bins_sum_w();
|
||||
const std::vector<TW>& af_bin_Sw2 = a_from.bins_sum_w2();
|
||||
const std::vector< std::vector<TC> >& af_bin_Sxw = a_from.bins_sum_xw();
|
||||
const std::vector< std::vector<TC> >& af_bin_Sx2w = a_from.bins_sum_x2w();
|
||||
|
||||
// Fill also the outflow.
|
||||
bn_t abins = hdata.m_axes[0].bins()+2;
|
||||
for(aibin=0;aibin<abins;aibin++) {
|
||||
//offset1D = ibin
|
||||
aoffset = aibin;
|
||||
for(ibin=ibeg;ibin<=iend;ibin++) {
|
||||
//offset2D = ibin + jbin * yoffset
|
||||
// hdata booked with y then :
|
||||
offset = ibin + aibin * yoffset;
|
||||
// Bin :
|
||||
hdata.m_bin_entries[aoffset] += af_bin_entries[offset];
|
||||
hdata.m_bin_Sw[aoffset] += af_bin_Sw[offset];
|
||||
hdata.m_bin_Sw2[aoffset] += af_bin_Sw2[offset];
|
||||
hdata.m_bin_Sxw[aoffset][0] += af_bin_Sxw[offset][1];
|
||||
hdata.m_bin_Sx2w[aoffset][0] += af_bin_Sx2w[offset][1];
|
||||
|
||||
hdata.m_bin_Svw[aoffset] += af_bin_Sxw[offset][0];
|
||||
hdata.m_bin_Sv2w[aoffset] += af_bin_Sx2w[offset][0];
|
||||
}
|
||||
}
|
||||
|
||||
hdata.m_in_range_plane_Sxyw.assign(a_to.number_of_planes(),0); //ill-defined.
|
||||
|
||||
hdata.update_fast_getters();
|
||||
a_to.copy_from_data(hdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// h3 -> h2 ////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class H3,class H2>
|
||||
inline bool fill_slice_yz(const H3& a_from,int aIbeg,int aIend,H2& a_to) {
|
||||
|
||||
if(!a_from.dimension()) return false;
|
||||
|
||||
typedef typename H3::bn_t bn_t;
|
||||
|
||||
bn_t ibeg;
|
||||
if(!a_from.axis_x().in_range_to_absolute_index(aIbeg,ibeg)) return false;
|
||||
@@ -163,7 +291,8 @@ inline bool fill_slice_yz(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
if(a_from.axis_y().bins()!=a_to.axis_x().bins()) return false;
|
||||
if(a_from.axis_z().bins()!=a_to.axis_y().bins()) return false;
|
||||
|
||||
histo_data<TC,TO,TN,TW> hdata = a_to.get_histo_data();
|
||||
typedef typename H2::hd_t hd_t;
|
||||
hd_t hdata = a_to.dac();
|
||||
|
||||
bn_t aibin,ajbin,aoffset,offset,ibin;
|
||||
|
||||
@@ -174,6 +303,10 @@ inline bool fill_slice_yz(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
bn_t axbins = hdata.m_axes[0].bins()+2;
|
||||
bn_t aybins = hdata.m_axes[1].bins()+2;
|
||||
|
||||
typedef typename H3::num_entries_t TN;
|
||||
typedef typename H3::weight_t TW;
|
||||
typedef typename H3::coordinate_t TC;
|
||||
|
||||
const std::vector<TN>& af_bin_entries = a_from.bins_entries();
|
||||
const std::vector<TW>& af_bin_Sw = a_from.bins_sum_w();
|
||||
const std::vector<TW>& af_bin_Sw2 = a_from.bins_sum_w2();
|
||||
@@ -201,18 +334,20 @@ inline bool fill_slice_yz(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hdata.m_in_range_plane_Sxyw.assign(a_to.number_of_planes(),0); //ill-defined.
|
||||
|
||||
hdata.update_fast_getters();
|
||||
a_to.copy_from_data(hdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline bool fill_slice_xy(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
int aKbeg,int aKend,h2<TC,TO,TN,TW,TH>& a_to) {
|
||||
template <class H3,class H2>
|
||||
inline bool fill_slice_xy(const H3& a_from,int aKbeg,int aKend,H2& a_to) {
|
||||
|
||||
if(!a_from.dimension()) return false;
|
||||
|
||||
typedef typename axis<TC,TO>::bn_t bn_t;
|
||||
typedef typename H3::bn_t bn_t;
|
||||
|
||||
bn_t kbeg;
|
||||
if(!a_from.axis_z().in_range_to_absolute_index(aKbeg,kbeg)) return false;
|
||||
@@ -223,7 +358,8 @@ inline bool fill_slice_xy(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
if(a_from.axis_x().bins()!=a_to.axis_x().bins()) return false;
|
||||
if(a_from.axis_y().bins()!=a_to.axis_y().bins()) return false;
|
||||
|
||||
histo_data<TC,TO,TN,TW> hdata = a_to.get_histo_data();
|
||||
typedef typename H2::hd_t hd_t;
|
||||
hd_t hdata = a_to.dac();
|
||||
|
||||
bn_t kbin;
|
||||
bn_t aibin,ajbin,aoffset,offset;
|
||||
@@ -235,6 +371,10 @@ inline bool fill_slice_xy(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
bn_t axbins = hdata.m_axes[0].bins()+2;
|
||||
bn_t aybins = hdata.m_axes[1].bins()+2;
|
||||
|
||||
typedef typename H3::num_entries_t TN;
|
||||
typedef typename H3::weight_t TW;
|
||||
typedef typename H3::coordinate_t TC;
|
||||
|
||||
const std::vector<TN>& af_bin_entries = a_from.bins_entries();
|
||||
const std::vector<TW>& af_bin_Sw = a_from.bins_sum_w();
|
||||
const std::vector<TW>& af_bin_Sw2 = a_from.bins_sum_w2();
|
||||
@@ -262,18 +402,20 @@ inline bool fill_slice_xy(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hdata.m_in_range_plane_Sxyw.assign(a_to.number_of_planes(),0); //ill-defined.
|
||||
|
||||
hdata.update_fast_getters();
|
||||
a_to.copy_from_data(hdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline bool fill_slice_xz(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
int aJbeg,int aJend,h2<TC,TO,TN,TW,TH>& a_to) {
|
||||
template <class H3,class H2>
|
||||
inline bool fill_slice_xz(const H3& a_from,int aJbeg,int aJend,H2& a_to) {
|
||||
|
||||
if(!a_from.dimension()) return false;
|
||||
|
||||
typedef typename axis<TC,TO>::bn_t bn_t;
|
||||
typedef typename H3::bn_t bn_t;
|
||||
|
||||
bn_t jbeg;
|
||||
if(!a_from.axis_y().in_range_to_absolute_index(aJbeg,jbeg)) return false;
|
||||
@@ -284,7 +426,8 @@ inline bool fill_slice_xz(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
if(a_from.axis_x().bins()!=a_to.axis_x().bins()) return false;
|
||||
if(a_from.axis_z().bins()!=a_to.axis_y().bins()) return false;
|
||||
|
||||
histo_data<TC,TO,TN,TW> hdata = a_to.get_histo_data();
|
||||
typedef typename H2::hd_t hd_t;
|
||||
hd_t hdata = a_to.dac();
|
||||
|
||||
bn_t aibin,ajbin,aoffset,offset,jbin;
|
||||
|
||||
@@ -295,6 +438,10 @@ inline bool fill_slice_xz(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
bn_t axbins = hdata.m_axes[0].bins()+2;
|
||||
bn_t aybins = hdata.m_axes[1].bins()+2;
|
||||
|
||||
typedef typename H3::num_entries_t TN;
|
||||
typedef typename H3::weight_t TW;
|
||||
typedef typename H3::coordinate_t TC;
|
||||
|
||||
const std::vector<TN>& af_bin_entries = a_from.bins_entries();
|
||||
const std::vector<TW>& af_bin_Sw = a_from.bins_sum_w();
|
||||
const std::vector<TW>& af_bin_Sw2 = a_from.bins_sum_w2();
|
||||
@@ -323,53 +470,36 @@ inline bool fill_slice_xz(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
}
|
||||
}
|
||||
|
||||
hdata.m_in_range_plane_Sxyw.assign(a_to.number_of_planes(),0); //ill-defined.
|
||||
|
||||
hdata.update_fast_getters();
|
||||
a_to.copy_from_data(hdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline h2<TC,TO,TN,TW,TH>* slice_xy(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
int aKbeg,int aKend,
|
||||
const std::string& a_title) {
|
||||
h2<TC,TO,TN,TW,TH>* slice = new h2<TC,TO,TN,TW,TH>(a_title,
|
||||
a_from.axis_x().bins(),
|
||||
a_from.axis_x().lower_edge(),
|
||||
a_from.axis_x().upper_edge(),
|
||||
a_from.axis_y().bins(),
|
||||
a_from.axis_y().lower_edge(),
|
||||
a_from.axis_y().upper_edge());
|
||||
template <class H3,class H2>
|
||||
inline H2* slice_xy(const H3& a_from,int aKbeg,int aKend,const std::string& a_title) {
|
||||
H2* slice = new H2(a_title,
|
||||
a_from.axis_x().bins(),a_from.axis_x().lower_edge(),a_from.axis_x().upper_edge(),
|
||||
a_from.axis_y().bins(),a_from.axis_y().lower_edge(),a_from.axis_y().upper_edge());
|
||||
if(!fill_slice_xy(a_from,aKbeg,aKend,*slice)) {delete slice;return 0;}
|
||||
return slice;
|
||||
}
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline h2<TC,TO,TN,TW,TH>* slice_yz(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
int aIbeg,int aIend,
|
||||
const std::string& a_title) {
|
||||
h2<TC,TO,TN,TW,TH>* slice = new h2<TC,TO,TN,TW,TH>(a_title,
|
||||
a_from.axis_y().bins(),
|
||||
a_from.axis_y().lower_edge(),
|
||||
a_from.axis_y().upper_edge(),
|
||||
a_from.axis_z().bins(),
|
||||
a_from.axis_z().lower_edge(),
|
||||
a_from.axis_z().upper_edge());
|
||||
template <class H3,class H2>
|
||||
inline H2* slice_yz(const H3& a_from,int aIbeg,int aIend,const std::string& a_title) {
|
||||
H2* slice = new H2(a_title,
|
||||
a_from.axis_y().bins(),a_from.axis_y().lower_edge(),a_from.axis_y().upper_edge(),
|
||||
a_from.axis_z().bins(),a_from.axis_z().lower_edge(),a_from.axis_z().upper_edge());
|
||||
if(!fill_slice_yz(a_from,aIbeg,aIend,*slice)) {delete slice;return 0;}
|
||||
return slice;
|
||||
}
|
||||
|
||||
template <class TC,class TO,class TN,class TW,class TH>
|
||||
inline h2<TC,TO,TN,TW,TH>* slice_xz(const h3<TC,TO,TN,TW,TH>& a_from,
|
||||
int aJbeg,int aJend,
|
||||
const std::string& a_title) {
|
||||
h2<TC,TO,TN,TW,TH>* slice = new h2<TC,TO,TN,TW,TH>(a_title,
|
||||
a_from.axis_x().bins(),
|
||||
a_from.axis_x().lower_edge(),
|
||||
a_from.axis_x().upper_edge(),
|
||||
a_from.axis_z().bins(),
|
||||
a_from.axis_z().lower_edge(),
|
||||
a_from.axis_z().upper_edge());
|
||||
template <class H3,class H2>
|
||||
inline H2* slice_xz(const H3& a_from,int aJbeg,int aJend,const std::string& a_title) {
|
||||
H2* slice = new H2(a_title,
|
||||
a_from.axis_x().bins(),a_from.axis_x().lower_edge(),a_from.axis_x().upper_edge(),
|
||||
a_from.axis_z().bins(),a_from.axis_z().lower_edge(),a_from.axis_z().upper_edge());
|
||||
if(!fill_slice_xz(a_from,aJbeg,aJend,*slice)) {delete slice;return 0;}
|
||||
return slice;
|
||||
}
|
||||
|
||||
@@ -7,98 +7,113 @@
|
||||
#include "slice"
|
||||
#include "h1d"
|
||||
#include "h2d"
|
||||
#include "h3d"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// h2 -> h1 ////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace tools {
|
||||
namespace histo {
|
||||
|
||||
inline h1d* slice_x(const h2d& a_from,
|
||||
int aJbeg,int aJend,
|
||||
const std::string& a_title) {
|
||||
inline h1d* slice_x(const h2d& a_from,int aJbeg,int aJend,const std::string& a_title) {
|
||||
h1d* slice_x = new h1d(a_title,
|
||||
a_from.axis_x().bins(),
|
||||
a_from.axis_x().lower_edge(),
|
||||
a_from.axis_x().upper_edge());
|
||||
a_from.axis_x().bins(),a_from.axis_x().lower_edge(),a_from.axis_x().upper_edge());
|
||||
if(!fill_slice_x(a_from,aJbeg,aJend,*slice_x)) {delete slice_x;return 0;}
|
||||
return slice_x;
|
||||
}
|
||||
|
||||
inline h1d* projection_x(const h2d& a_from,const std::string& a_title) {
|
||||
typedef axis<double,unsigned int> axis_t;
|
||||
return slice_x(a_from,axis_t::UNDERFLOW_BIN,axis_t::OVERFLOW_BIN,a_title);
|
||||
return slice_x(a_from,axis_UNDERFLOW_BIN,axis_OVERFLOW_BIN,a_title);
|
||||
}
|
||||
|
||||
inline h1d* slice_y(const h2d& a_from,
|
||||
int aIbeg,int aIend,
|
||||
const std::string& a_title) {
|
||||
inline h1d* slice_y(const h2d& a_from,int aIbeg,int aIend,const std::string& a_title) {
|
||||
h1d* slice_y = new h1d(a_title,
|
||||
a_from.axis_y().bins(),
|
||||
a_from.axis_y().lower_edge(),
|
||||
a_from.axis_y().upper_edge());
|
||||
a_from.axis_y().bins(),a_from.axis_y().lower_edge(),a_from.axis_y().upper_edge());
|
||||
if(!fill_slice_y(a_from,aIbeg,aIend,*slice_y)) {delete slice_y;return 0;}
|
||||
return slice_y;
|
||||
}
|
||||
|
||||
inline h1d* projection_y(const h2d& a_from,const std::string& a_title) {
|
||||
typedef axis<double,unsigned int> axis_t;
|
||||
return slice_y(a_from,axis_t::UNDERFLOW_BIN,axis_t::OVERFLOW_BIN,a_title);
|
||||
return slice_y(a_from,axis_UNDERFLOW_BIN,axis_OVERFLOW_BIN,a_title);
|
||||
}
|
||||
|
||||
inline h2d* slice_xy(const h3d& a_from,
|
||||
int aKbeg,int aKend,
|
||||
const std::string& a_title) {
|
||||
}}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// h2 -> p1 ////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#include "p1d"
|
||||
|
||||
namespace tools {
|
||||
namespace histo {
|
||||
|
||||
inline p1d* profile_x(const h2d& a_from,int aJbeg,int aJend,const std::string& a_title) {
|
||||
p1d* slice_x = new p1d(a_title,
|
||||
a_from.axis_x().bins(),a_from.axis_x().lower_edge(),a_from.axis_x().upper_edge());
|
||||
if(!fill_profile_x(a_from,aJbeg,aJend,*slice_x)) {delete slice_x;return 0;}
|
||||
return slice_x;
|
||||
}
|
||||
|
||||
inline p1d* profile_x(const h2d& a_from,const std::string& a_title) {
|
||||
return profile_x(a_from,axis_UNDERFLOW_BIN,axis_OVERFLOW_BIN,a_title);
|
||||
}
|
||||
|
||||
inline p1d* profile_y(const h2d& a_from,int aIbeg,int aIend,const std::string& a_title) {
|
||||
p1d* slice_y = new p1d(a_title,
|
||||
a_from.axis_y().bins(),a_from.axis_y().lower_edge(),a_from.axis_y().upper_edge());
|
||||
if(!fill_profile_y(a_from,aIbeg,aIend,*slice_y)) {delete slice_y;return 0;}
|
||||
return slice_y;
|
||||
}
|
||||
|
||||
inline p1d* profile_y(const h2d& a_from,const std::string& a_title) {
|
||||
return profile_y(a_from,axis_UNDERFLOW_BIN,axis_OVERFLOW_BIN,a_title);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// h3 -> h2 ////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "h3d"
|
||||
|
||||
namespace tools {
|
||||
namespace histo {
|
||||
|
||||
inline h2d* slice_xy(const h3d& a_from,int aKbeg,int aKend,const std::string& a_title) {
|
||||
h2d* slice = new h2d(a_title,
|
||||
a_from.axis_x().bins(),
|
||||
a_from.axis_x().lower_edge(),
|
||||
a_from.axis_x().upper_edge(),
|
||||
a_from.axis_y().bins(),
|
||||
a_from.axis_y().lower_edge(),
|
||||
a_from.axis_y().upper_edge());
|
||||
a_from.axis_x().bins(),a_from.axis_x().lower_edge(),a_from.axis_x().upper_edge(),
|
||||
a_from.axis_y().bins(),a_from.axis_y().lower_edge(),a_from.axis_y().upper_edge());
|
||||
if(!fill_slice_xy(a_from,aKbeg,aKend,*slice)) {delete slice;return 0;}
|
||||
return slice;
|
||||
}
|
||||
|
||||
inline h2d* projection_xy(const h3d& a_from,const std::string& a_title) {
|
||||
typedef axis<double,unsigned int> axis_t;
|
||||
return slice_xy(a_from,axis_t::UNDERFLOW_BIN,axis_t::OVERFLOW_BIN,a_title);
|
||||
return slice_xy(a_from,axis_UNDERFLOW_BIN,axis_OVERFLOW_BIN,a_title);
|
||||
}
|
||||
|
||||
inline h2d* slice_yz(const h3d& a_from,
|
||||
int aIbeg,int aIend,
|
||||
const std::string& a_title) {
|
||||
inline h2d* slice_yz(const h3d& a_from,int aIbeg,int aIend,const std::string& a_title) {
|
||||
h2d* slice = new h2d(a_title,
|
||||
a_from.axis_y().bins(),
|
||||
a_from.axis_y().lower_edge(),
|
||||
a_from.axis_y().upper_edge(),
|
||||
a_from.axis_z().bins(),
|
||||
a_from.axis_z().lower_edge(),
|
||||
a_from.axis_z().upper_edge());
|
||||
a_from.axis_y().bins(),a_from.axis_y().lower_edge(),a_from.axis_y().upper_edge(),
|
||||
a_from.axis_z().bins(),a_from.axis_z().lower_edge(),a_from.axis_z().upper_edge());
|
||||
if(!fill_slice_yz(a_from,aIbeg,aIend,*slice)) {delete slice;return 0;}
|
||||
return slice;
|
||||
}
|
||||
|
||||
inline h2d* projection_yz(const h3d& a_from,const std::string& a_title) {
|
||||
typedef axis<double,unsigned int> axis_t;
|
||||
return slice_yz(a_from,axis_t::UNDERFLOW_BIN,axis_t::OVERFLOW_BIN,a_title);
|
||||
return slice_yz(a_from,axis_UNDERFLOW_BIN,axis_OVERFLOW_BIN,a_title);
|
||||
}
|
||||
|
||||
inline h2d* slice_xz(const h3d& a_from,
|
||||
int aJbeg,int aJend,
|
||||
const std::string& a_title) {
|
||||
inline h2d* slice_xz(const h3d& a_from,int aJbeg,int aJend,const std::string& a_title) {
|
||||
h2d* slice = new h2d(a_title,
|
||||
a_from.axis_x().bins(),
|
||||
a_from.axis_x().lower_edge(),
|
||||
a_from.axis_x().upper_edge(),
|
||||
a_from.axis_z().bins(),
|
||||
a_from.axis_z().lower_edge(),
|
||||
a_from.axis_z().upper_edge());
|
||||
a_from.axis_x().bins(),a_from.axis_x().lower_edge(),a_from.axis_x().upper_edge(),
|
||||
a_from.axis_z().bins(),a_from.axis_z().lower_edge(),a_from.axis_z().upper_edge());
|
||||
if(!fill_slice_xz(a_from,aJbeg,aJend,*slice)) {delete slice;return 0;}
|
||||
return slice;
|
||||
}
|
||||
|
||||
inline h2d* projection_xz(const h3d& a_from,const std::string& a_title) {
|
||||
typedef axis<double,unsigned int> axis_t;
|
||||
return slice_xz(a_from,axis_t::UNDERFLOW_BIN,axis_t::OVERFLOW_BIN,a_title);
|
||||
return slice_xz(a_from,axis_UNDERFLOW_BIN,axis_OVERFLOW_BIN,a_title);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_hls
|
||||
#define tools_hls
|
||||
|
||||
namespace tools {
|
||||
|
||||
//T is float or double.
|
||||
|
||||
template <class T>
|
||||
inline T hls_to_rgb2(T rn1,T rn2,T huei) {
|
||||
// taken from CERN-ROOT/TColor.
|
||||
T hue = huei;
|
||||
if (hue > 360) hue = hue - 360;
|
||||
if (hue < 0) hue = hue + 360;
|
||||
if (hue < 60 ) return rn1 + (rn2-rn1)*hue/60;
|
||||
if (hue < 180) return rn2;
|
||||
if (hue < 240) return rn1 + (rn2-rn1)*(240-hue)/60;
|
||||
return rn1;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void hls_to_rgb(T hue,T light,T satur,T& a_r,T& a_g,T& a_b){
|
||||
// taken from CERN-ROOT/TColor.
|
||||
// Static method to compute RGB from HLS. The l and s are between [0,1]
|
||||
// and h is between [0,360]. The returned r,g,b triplet is between [0,1].
|
||||
|
||||
T rh, rl, rs, rm1, rm2;
|
||||
rh = rl = rs = 0;
|
||||
if (hue > 0) rh = hue; if (rh > 360) rh = 360;
|
||||
if (light > 0) rl = light; if (rl > 1) rl = 1;
|
||||
if (satur > 0) rs = satur; if (rs > 1) rs = 1;
|
||||
|
||||
if (rl <= T(0.5)) {
|
||||
rm2 = rl*(1 + rs);
|
||||
} else {
|
||||
rm2 = rl + rs - rl*rs;
|
||||
}
|
||||
rm1 = 2*rl - rm2;
|
||||
|
||||
if (!rs) { a_r = rl; a_g = rl; a_b = rl; return; }
|
||||
a_r = hls_to_rgb2(rm1, rm2, rh+120);
|
||||
a_g = hls_to_rgb2(rm1, rm2, rh);
|
||||
a_b = hls_to_rgb2(rm1, rm2, rh-120);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void rgb_to_hls(T rr,T gg,T bb,T& hue,T& light,T& satur) {
|
||||
// The r,g,b triplet is between
|
||||
// [0,1], hue is between [0,360], light and satur are [0,1].
|
||||
|
||||
T rnorm, gnorm, bnorm, minval, maxval, msum, mdiff, cr, cg, cb;
|
||||
minval = maxval = 0;
|
||||
cr = cg = cb = 0;
|
||||
if (rr > 0) cr = rr; if (cr > 1) cr = 1;
|
||||
if (gg > 0) cg = gg; if (cg > 1) cg = 1;
|
||||
if (bb > 0) cb = bb; if (cb > 1) cb = 1;
|
||||
|
||||
minval = cr;
|
||||
if (cg < minval) minval = cg;
|
||||
if (cb < minval) minval = cb;
|
||||
maxval = cr;
|
||||
if (cg > maxval) maxval = cg;
|
||||
if (cb > maxval) maxval = cb;
|
||||
|
||||
rnorm = gnorm = bnorm = 0;
|
||||
mdiff = maxval - minval;
|
||||
msum = maxval + minval;
|
||||
light = T(0.5) * msum;
|
||||
if (maxval != minval) {
|
||||
rnorm = (maxval - cr)/mdiff;
|
||||
gnorm = (maxval - cg)/mdiff;
|
||||
bnorm = (maxval - cb)/mdiff;
|
||||
} else {
|
||||
satur = hue = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (light < T(0.5))
|
||||
satur = mdiff/msum;
|
||||
else
|
||||
satur = mdiff/(2 - msum);
|
||||
|
||||
if (cr == maxval)
|
||||
hue = 60 * (6 + bnorm - gnorm);
|
||||
else if (cg == maxval)
|
||||
hue = 60 * (2 + rnorm - bnorm);
|
||||
else
|
||||
hue = 60 * (4 + gnorm - rnorm);
|
||||
|
||||
if (hue > 360)
|
||||
hue = hue - 360;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,835 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_img
|
||||
#define tools_img
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include "mem"
|
||||
#endif
|
||||
|
||||
#include <string> //memcpy
|
||||
#include <cstring> //memcpy
|
||||
#include "mnmx"
|
||||
#include "S_STRING"
|
||||
|
||||
#include <vector> //concatenate
|
||||
|
||||
namespace tools {
|
||||
|
||||
template <class T>
|
||||
class img {
|
||||
public:
|
||||
TOOLS_T_SCLASS(T,tools::img)
|
||||
public:
|
||||
img()
|
||||
:m_w(0),m_h(0),m_n(0)
|
||||
,m_buffer(0)
|
||||
,m_owner(false)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
img(unsigned int a_w,unsigned int a_h,unsigned int a_n,T* a_buffer,bool a_owner)
|
||||
:m_w(a_w),m_h(a_h),m_n(a_n)
|
||||
,m_buffer(a_buffer)
|
||||
,m_owner(a_owner)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
virtual ~img() {
|
||||
if(m_owner) delete [] m_buffer;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
public:
|
||||
img(const img& a_from)
|
||||
:m_w(a_from.m_w),m_h(a_from.m_h),m_n(a_from.m_n)
|
||||
,m_buffer(0)
|
||||
,m_owner(a_from.m_owner)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_class().c_str());
|
||||
#endif
|
||||
if(m_owner) {
|
||||
unsigned int sz = m_w*m_h*m_n;
|
||||
if(!sz) return;
|
||||
m_buffer = new T[sz];
|
||||
if(!m_buffer) {
|
||||
m_w = 0;m_h = 0;m_n = 0;m_owner = false;
|
||||
return; //throw
|
||||
}
|
||||
::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
|
||||
} else {
|
||||
m_buffer = a_from.m_buffer;
|
||||
}
|
||||
}
|
||||
img& operator=(const img& a_from){
|
||||
if(&a_from==this) return *this;
|
||||
if(m_owner) delete [] m_buffer;
|
||||
m_buffer = 0;
|
||||
m_w = a_from.m_w;
|
||||
m_h = a_from.m_h;
|
||||
m_n = a_from.m_n;
|
||||
m_owner = a_from.m_owner;
|
||||
if(m_owner) {
|
||||
unsigned int sz = m_w*m_h*m_n;
|
||||
if(!sz) return *this;
|
||||
m_buffer = new T[sz];
|
||||
if(!m_buffer) {
|
||||
m_w = 0;m_h = 0;m_n = 0;m_owner = false;
|
||||
return *this; //throw
|
||||
}
|
||||
::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
|
||||
} else {
|
||||
m_buffer = a_from.m_buffer;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
bool operator==(const img& a_from) const {return equal(a_from);}
|
||||
bool operator!=(const img& a_from) const {return !operator==(a_from);}
|
||||
public:
|
||||
void transfer(img& a_from) {
|
||||
if(m_owner) delete [] m_buffer;
|
||||
m_w = a_from.m_w;
|
||||
m_h = a_from.m_h;
|
||||
m_n = a_from.m_n;
|
||||
m_buffer = a_from.m_buffer;
|
||||
m_owner = a_from.m_owner;
|
||||
// empty a_from :
|
||||
a_from.m_w = 0;
|
||||
a_from.m_h = 0;
|
||||
a_from.m_buffer = 0;
|
||||
a_from.m_owner = false;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if(m_owner) delete [] m_buffer;
|
||||
m_w = 0;
|
||||
m_h = 0;
|
||||
m_n = 0;
|
||||
m_buffer = 0;
|
||||
m_owner = false;
|
||||
}
|
||||
void set(unsigned int a_w,unsigned int a_h,unsigned int a_n,T* a_buffer,bool a_owner) {
|
||||
if(m_owner) delete [] m_buffer;
|
||||
m_w = a_w;
|
||||
m_h = a_h;
|
||||
m_n = a_n;
|
||||
m_buffer = a_buffer;
|
||||
m_owner = a_owner;
|
||||
}
|
||||
bool copy(unsigned int a_w,unsigned int a_h,unsigned int a_n,T* a_buffer) {
|
||||
if(m_owner) delete [] m_buffer;
|
||||
m_buffer = 0;
|
||||
m_w = a_w;
|
||||
m_h = a_h;
|
||||
m_n = a_n;
|
||||
unsigned int sz = m_w*m_h*m_n;
|
||||
if(!sz) {
|
||||
m_w = 0;m_h = 0;m_n = 0;m_owner = false;
|
||||
return false;
|
||||
}
|
||||
m_buffer = new T[sz];
|
||||
if(!m_buffer) {
|
||||
m_w = 0;m_h = 0;m_n = 0;m_owner = false;
|
||||
return false;
|
||||
}
|
||||
::memcpy(m_buffer,a_buffer,sz*sizeof(T));
|
||||
m_owner = true;
|
||||
return true;
|
||||
}
|
||||
bool copy(const img& a_from){
|
||||
if(m_owner) delete [] m_buffer;
|
||||
m_buffer = 0;
|
||||
m_w = a_from.m_w;
|
||||
m_h = a_from.m_h;
|
||||
m_n = a_from.m_n;
|
||||
unsigned int sz = m_w*m_h*m_n;
|
||||
if(!sz) {
|
||||
m_w = 0;m_h = 0;m_n = 0;m_owner = false;
|
||||
return false;
|
||||
}
|
||||
m_buffer = new T[sz];
|
||||
if(!m_buffer) {
|
||||
m_w = 0;m_h = 0;m_n = 0;m_owner = false;
|
||||
return false;
|
||||
}
|
||||
::memcpy(m_buffer,a_from.m_buffer,sz*sizeof(T));
|
||||
m_owner = true;
|
||||
return true;
|
||||
}
|
||||
bool allocate(unsigned int a_w,unsigned int a_h,unsigned int a_n){
|
||||
if(m_owner) delete [] m_buffer;
|
||||
m_buffer = 0;
|
||||
unsigned int sz = a_w*a_h*a_n;
|
||||
if(!sz) {
|
||||
m_w = 0;m_h = 0;m_n = 0;m_owner = false;
|
||||
return false;
|
||||
}
|
||||
m_w = a_w;
|
||||
m_h = a_h;
|
||||
m_n = a_n;
|
||||
m_buffer = new T[sz];
|
||||
if(!m_buffer) {
|
||||
m_w = 0;m_h = 0;m_n = 0;m_owner = false;
|
||||
return false;
|
||||
}
|
||||
m_owner = true;
|
||||
return true;
|
||||
}
|
||||
void make_empty(bool a_delete = true) {
|
||||
if(m_owner && a_delete) delete [] m_buffer;
|
||||
m_w = 0;
|
||||
m_h = 0;
|
||||
m_n = 0;
|
||||
m_buffer = 0;
|
||||
m_owner = false;
|
||||
}
|
||||
bool is_empty() const {
|
||||
if(!m_w) return true;
|
||||
if(!m_h) return true;
|
||||
if(!m_n) return true;
|
||||
if(!m_buffer) return true;
|
||||
return false;
|
||||
}
|
||||
bool equal(const img& a_from) const {
|
||||
if(m_w!=a_from.m_w) return false;
|
||||
if(m_h!=a_from.m_h) return false;
|
||||
if(m_n!=a_from.m_n) return false;
|
||||
//don't test ownership.
|
||||
unsigned int sz = m_w*m_h*m_n;
|
||||
T* pos = m_buffer;
|
||||
T* fpos = a_from.m_buffer;
|
||||
for(unsigned int index=0;index<sz;index++,pos++,fpos++) {
|
||||
if((*pos)!=(*fpos)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
unsigned int width() const {return m_w;}
|
||||
unsigned int height() const {return m_h;}
|
||||
unsigned int bytes_per_pixel() const {return m_n;}
|
||||
unsigned int bpp() const {return m_n;}
|
||||
T* buffer() const {return m_buffer;}
|
||||
bool owner() const {return m_owner;}
|
||||
unsigned int size() const {return m_w*m_h*m_n*sizeof(T);} //bytes.
|
||||
public:
|
||||
bool pixel(unsigned int a_i,unsigned a_j,std::vector<T>& a_pixel) const {
|
||||
if((!m_w)||(!m_h)||(a_i>=m_w)||(a_j>=m_h)) {
|
||||
a_pixel.clear();
|
||||
return false;
|
||||
}
|
||||
a_pixel.resize(m_n);
|
||||
T* pos = m_buffer + a_j * (m_w * m_n) + a_i*m_n;
|
||||
for(unsigned int ipix=0;ipix<m_n;ipix++) {
|
||||
a_pixel[ipix] = *(pos+ipix);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool expand(unsigned int a_factor,img<T>& a_res,bool a_res_force_owner = true) const {
|
||||
if(a_factor==1) {
|
||||
if(a_res_force_owner) {
|
||||
a_res.copy(m_w,m_h,m_n,m_buffer);
|
||||
} else {
|
||||
a_res.set(m_w,m_h,m_n,m_buffer,false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int nw = m_w*a_factor;
|
||||
unsigned int nh = m_h*a_factor;
|
||||
unsigned int sz = nh*nw*m_n;
|
||||
if(!sz) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
T* nb = new T[sz];
|
||||
if(!nb) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
for(unsigned int j=0;j<m_h;j++) {
|
||||
for(unsigned int i=0;i<m_w;i++) {
|
||||
//position in the original image.
|
||||
T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
|
||||
|
||||
for(unsigned int fr=0;fr<a_factor;fr++) {
|
||||
for(unsigned int fc=0;fc<a_factor;fc++) {
|
||||
//position in the new image.
|
||||
T* npos = nb + (j*a_factor+fr) * (nw * m_n) + (i*a_factor+fc)*m_n;
|
||||
for(unsigned int ipix=0;ipix<m_n;ipix++) {
|
||||
*(npos+ipix) = *(pos+ipix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
a_res.set(nw,nh,m_n,nb,true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool contract(unsigned int a_factor,img<T>& a_res,bool a_force_res_owner = true) const {
|
||||
// a_factor pixels are contracted in one.
|
||||
if(a_factor==1) {
|
||||
if(a_force_res_owner) {
|
||||
a_res.copy(m_w,m_h,m_n,m_buffer);
|
||||
} else {
|
||||
a_res.set(m_w,m_h,m_n,m_buffer,false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if(!a_factor) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int nw = m_w/a_factor;
|
||||
unsigned int nh = m_h/a_factor;
|
||||
unsigned int sz = nh*nw*m_n;
|
||||
if(!sz) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
T* nb = new T[sz];
|
||||
if(!nb) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
//T* npos = nb;
|
||||
//for(unsigned int ipix=0;ipix<sz;ipix++) {*npos = 125;npos++;}
|
||||
|
||||
double* pixels = new double[m_n]; //for mean value.
|
||||
if(!pixels) {
|
||||
delete [] nb;
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
unsigned int nfac = a_factor*a_factor;
|
||||
|
||||
for(unsigned int j=0;j<nh;j++) {
|
||||
for(unsigned int i=0;i<nw;i++) {
|
||||
|
||||
// take mean value of a_factor*a_factor pixels :
|
||||
for(unsigned int ipix=0;ipix<m_n;ipix++) pixels[ipix] = 0;
|
||||
|
||||
for(unsigned int fr=0;fr<a_factor;fr++) {
|
||||
for(unsigned int fc=0;fc<a_factor;fc++) {
|
||||
T* pos = m_buffer + (j*a_factor+fr)*(m_w*m_n) +(i*a_factor+fc)*m_n;
|
||||
for(unsigned int ipix=0;ipix<m_n;ipix++) {
|
||||
pixels[ipix] += double(*pos);pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(unsigned int ipix=0;ipix<m_n;ipix++) {
|
||||
pixels[ipix] /= double(nfac);
|
||||
}
|
||||
|
||||
//position in the result image.
|
||||
T* npos = nb + j * (nw * m_n) + i*m_n;
|
||||
for(unsigned int ipix=0;ipix<m_n;ipix++) {
|
||||
*npos = T(pixels[ipix]);npos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete [] pixels;
|
||||
|
||||
a_res.set(nw,nh,m_n,nb,true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool contract(unsigned int a_w,unsigned int a_h,img<T>& a_res,bool a_force_res_owner = true) const {
|
||||
if((a_w==m_w)&&(a_h==m_h)) {
|
||||
if(a_force_res_owner) {
|
||||
a_res.copy(m_w,m_h,m_n,m_buffer);
|
||||
} else {
|
||||
a_res.set(m_w,m_h,m_n,m_buffer,false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int sz = a_h*a_w*m_n;
|
||||
if(!sz) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
T* rb = new T[sz];
|
||||
if(!rb) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
double* pixels = new double[m_n]; //for mean value.
|
||||
if(!pixels) {
|
||||
delete [] rb;
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int wfac = double(m_w)/double(a_w);
|
||||
unsigned int hfac = double(m_h)/double(a_h);
|
||||
if(!wfac) wfac = 1;
|
||||
if(!hfac) hfac = 1;
|
||||
|
||||
unsigned int wfac_hfac = wfac*hfac;
|
||||
|
||||
T* hpos;T* pos;
|
||||
for(unsigned int j=0;j<a_h;j++) {
|
||||
for(unsigned int i=0;i<a_w;i++) {
|
||||
|
||||
// take mean value of wfac*hfac pixels :
|
||||
{for(unsigned int ipix=0;ipix<m_n;ipix++) pixels[ipix] = 0;}
|
||||
|
||||
for(unsigned int fr=0;fr<hfac;fr++) {
|
||||
hpos = m_buffer + (j*hfac+fr)*(m_w*m_n);
|
||||
for(unsigned int fc=0;fc<wfac;fc++) {
|
||||
pos = hpos + (i*wfac+fc)*m_n;
|
||||
for(unsigned int ipix=0;ipix<m_n;ipix++) {
|
||||
pixels[ipix] += double(*pos)/double(wfac_hfac);pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//position in the result image.
|
||||
T* rpos = rb + j * (a_w * m_n) + i*m_n;
|
||||
{for(unsigned int ipix=0;ipix<m_n;ipix++) {*rpos = T(pixels[ipix]);rpos++;}}
|
||||
}
|
||||
}
|
||||
|
||||
delete [] pixels;
|
||||
|
||||
a_res.set(a_w,a_h,m_n,rb,true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_part(unsigned int a_sx,unsigned int a_sy,unsigned int a_sw,unsigned int a_sh,img<T>& a_res) const {
|
||||
|
||||
if((a_sx>=m_w)||(a_sy>=m_h)){
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 012345
|
||||
unsigned int rw = tools::mn<unsigned int>(m_w-a_sx,a_sw);
|
||||
unsigned int rh = tools::mn<unsigned int>(m_h-a_sy,a_sh);
|
||||
unsigned int sz = rh*rw*m_n;
|
||||
if(!sz) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
T* rb = new T[sz];
|
||||
if(!rb) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int rstride = rw * m_n;
|
||||
T* rpos = rb;
|
||||
|
||||
unsigned int stride = m_w * m_n;
|
||||
T* pos = m_buffer+a_sy*stride+a_sx*m_n;
|
||||
|
||||
//T* mx = m_buffer+size();
|
||||
//T* rmx = rb+sz*sizeof(T);
|
||||
|
||||
for(unsigned int j=0;j<rh;j++,rpos+=rstride,pos+=stride) {//j=0 -> bottom.
|
||||
/*
|
||||
if((pos+rstride*sizeof(T))>mx) {
|
||||
::printf("debug : get_part : buffer overflow\n");
|
||||
delete [] rb;
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
if((rpos+rstride*sizeof(T))>rmx) {
|
||||
::printf("debug : get_part : result buffer overflow\n");
|
||||
delete [] rb;
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
::memcpy(rpos,pos,rstride*sizeof(T));
|
||||
}
|
||||
|
||||
a_res.set(rw,rh,m_n,rb,true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool to_texture(bool a_expand,
|
||||
const T a_pixel[], //size shoulde be a_img.m_n.
|
||||
img<T>& a_res,bool a_res_force_owner = true) const {
|
||||
|
||||
//NOTE : pixels of the original image are not expanded or shrinked.
|
||||
|
||||
if((!m_w)||(!m_h)) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
// in case (m_w==1)||(m_h==1), expand the pixel
|
||||
// up to the closest power of 2 ?
|
||||
|
||||
if((m_w==1)||(m_h==1)||a_expand) {
|
||||
// find closest power of two upper than m_w, m_h :
|
||||
unsigned int rw = 2;
|
||||
while(true) {if(rw>=m_w) break;rw *=2;}
|
||||
unsigned int rh = 2;
|
||||
while(true) {if(rh>=m_h) break;rh *=2;}
|
||||
|
||||
if((rw==m_w)&&(rh==m_h)) { //exact match.
|
||||
if(a_res_force_owner) {
|
||||
a_res.copy(m_w,m_h,m_n,m_buffer);
|
||||
} else {
|
||||
a_res.set(m_w,m_h,m_n,m_buffer,false); //WARNING owner=false.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// we expand the image and fill new spaces with a_pixel.
|
||||
|
||||
T* rb = 0;
|
||||
bool res_set = true;
|
||||
if(a_res.owner()&&(a_res.size()==(rh*rw*m_n))) {
|
||||
// a_res has already the right allocation.
|
||||
rb = a_res.buffer();
|
||||
res_set = false;
|
||||
} else {
|
||||
rb = new T[rh*rw*m_n];
|
||||
if(!rb) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int num = rw*m_n;
|
||||
|
||||
// initialize with given color :
|
||||
{T* pos = rb;
|
||||
for(unsigned int i=0;i<rw;i++,pos+=m_n) {
|
||||
::memcpy(pos,a_pixel,m_n*sizeof(T));
|
||||
}
|
||||
unsigned int sz = num*sizeof(T);
|
||||
for(unsigned int j=1;j<rh;j++,pos+=num) { //j=0 -> bottom.
|
||||
::memcpy(pos,rb,sz);
|
||||
}}
|
||||
|
||||
// center :
|
||||
unsigned int col = (rw-m_w)/2;
|
||||
unsigned int row = (rh-m_h)/2;
|
||||
|
||||
unsigned int mnum = m_w*m_n;
|
||||
|
||||
// copy original image in a centered part of the new one :
|
||||
{T* pos = m_buffer;
|
||||
T* rpos = rb+row*num+col*m_n;
|
||||
unsigned int sz = mnum*sizeof(T);
|
||||
for(unsigned int j=0;j<m_h;j++,pos+=mnum,rpos+=num) {
|
||||
::memcpy(rpos,pos,sz);
|
||||
}}
|
||||
|
||||
if(res_set) a_res.set(rw,rh,m_n,rb,true);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
// then m_w>=2 and m_h>=2
|
||||
|
||||
// find closest power of two lower than m_w, m_h :
|
||||
unsigned int sw = 2;
|
||||
while(true) {if((sw*2)>m_w) break;sw *=2;}
|
||||
unsigned int sh = 2;
|
||||
while(true) {if((sh*2)>m_h) break;sh *=2;}
|
||||
|
||||
if((sw==m_w)&&(sh==m_h)) { //exact match.
|
||||
if(a_res_force_owner) {
|
||||
a_res.copy(m_w,m_h,m_n,m_buffer);
|
||||
} else {
|
||||
a_res.set(m_w,m_h,m_n,m_buffer,false); //WARNING owner=false.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int sx = (m_w-sw)/2;
|
||||
unsigned int sy = (m_h-sh)/2;
|
||||
|
||||
return get_part(sx,sy,sw,sh,a_res);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool check_gl_limit(unsigned int a_GL_MAX_TEXTURE_SIZE,img<T>& a_res) const {
|
||||
// if ret true and a_res.is_empty(), "this" does not exceeds the limit.
|
||||
// if ret true and !a_res.is_empty(), "this" exceeds the limit and a new fitting image is returned in a_res.
|
||||
// if ret false, "this" exceeds the limit but something went wrong in building a_res.
|
||||
unsigned int tw = m_w;
|
||||
unsigned int th = m_h;
|
||||
if((tw<=a_GL_MAX_TEXTURE_SIZE)&&(th<=a_GL_MAX_TEXTURE_SIZE)) {
|
||||
a_res.make_empty();
|
||||
return true;
|
||||
}
|
||||
unsigned int fac = 2;
|
||||
while(true) {
|
||||
unsigned int pw = tw/fac;
|
||||
unsigned int ph = th/fac;
|
||||
if((pw<=a_GL_MAX_TEXTURE_SIZE)&&(ph<=a_GL_MAX_TEXTURE_SIZE)) {
|
||||
//unsigned int sx = (tw-pw)/2;
|
||||
//unsigned int sy = (th-ph)/2;
|
||||
//if(!get_part(sx,sy,pw,ph,a_res)) {
|
||||
if(!contract(fac,a_res)) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
fac *= 2;
|
||||
}
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bw2x(unsigned int a_n,img<T>& a_res) const {
|
||||
//expect a bw img.
|
||||
if(m_n!=1) return false;
|
||||
|
||||
a_res.make_empty();
|
||||
if(a_n<m_n) return false;
|
||||
unsigned int sz = m_w*m_h*a_n;
|
||||
if(!sz) return false;
|
||||
|
||||
a_res.m_buffer = new T[sz];
|
||||
if(!a_res.m_buffer) return false;
|
||||
a_res.m_owner = true;
|
||||
a_res.m_w = m_w;
|
||||
a_res.m_h = m_h;
|
||||
a_res.m_n = a_n;
|
||||
|
||||
for(unsigned int j=0;j<m_h;j++) {
|
||||
for(unsigned int i=0;i<m_w;i++) {
|
||||
//position in the original image.
|
||||
T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
|
||||
|
||||
T* rpos = a_res.m_buffer + j * (m_w * a_n) + i*a_n;
|
||||
|
||||
for(unsigned int ipix=0;ipix<a_n;ipix++) {
|
||||
*(rpos+ipix) = *pos;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool yswap(img<T>& a_res) const {
|
||||
a_res.make_empty();
|
||||
|
||||
a_res.m_buffer = new T[size()];
|
||||
if(!a_res.m_buffer) return false;
|
||||
a_res.m_owner = true;
|
||||
a_res.m_w = m_w;
|
||||
a_res.m_h = m_h;
|
||||
a_res.m_n = m_n;
|
||||
|
||||
unsigned int stride = m_w * m_n;
|
||||
|
||||
for(unsigned int j=0;j<m_h;j++) {
|
||||
T* pos = m_buffer + j * stride;
|
||||
T* rpos = a_res.m_buffer + (m_h-j-1) * stride;
|
||||
::memcpy(rpos,pos,stride*sizeof(T));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rgba2rgb(img<T>& a_res) const {
|
||||
if(m_n!=4) return false;
|
||||
|
||||
unsigned int a_n = 3;
|
||||
|
||||
a_res.make_empty();
|
||||
unsigned int sz = m_w*m_h*a_n;
|
||||
if(!sz) return false;
|
||||
|
||||
a_res.m_buffer = new T[sz];
|
||||
if(!a_res.m_buffer) return false;
|
||||
a_res.m_owner = true;
|
||||
a_res.m_w = m_w;
|
||||
a_res.m_h = m_h;
|
||||
a_res.m_n = a_n;
|
||||
|
||||
for(unsigned int j=0;j<m_h;j++) {
|
||||
for(unsigned int i=0;i<m_w;i++) {
|
||||
//position in the original image.
|
||||
T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
|
||||
|
||||
T* rpos = a_res.m_buffer + j * (m_w * a_n) + i*a_n;
|
||||
|
||||
for(unsigned int ipix=0;ipix<a_n;ipix++) {
|
||||
*(rpos+ipix) = *(pos+ipix);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rgb2rgba(img<T>& a_res,const T& a_pixel) const {
|
||||
if(m_n!=3) return false;
|
||||
|
||||
unsigned int a_n = 4;
|
||||
|
||||
a_res.make_empty();
|
||||
unsigned int sz = m_w*m_h*a_n;
|
||||
if(!sz) return false;
|
||||
|
||||
a_res.m_buffer = new T[sz];
|
||||
if(!a_res.m_buffer) return false;
|
||||
a_res.m_owner = true;
|
||||
a_res.m_w = m_w;
|
||||
a_res.m_h = m_h;
|
||||
a_res.m_n = a_n;
|
||||
|
||||
for(unsigned int j=0;j<m_h;j++) {
|
||||
for(unsigned int i=0;i<m_w;i++) {
|
||||
//position in the original image.
|
||||
T* pos = m_buffer + j * (m_w * m_n) + i*m_n;
|
||||
|
||||
T* rpos = a_res.m_buffer + j * (m_w * a_n) + i*a_n;
|
||||
|
||||
for(unsigned int ipix=0;ipix<m_n;ipix++) {
|
||||
*(rpos+ipix) = *(pos+ipix);
|
||||
}
|
||||
*(rpos+3) = a_pixel;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
static bool concatenate(const std::vector< img<T> >& a_imgs,
|
||||
unsigned int a_cols,unsigned int a_rows,
|
||||
unsigned int a_bw,unsigned int a_bh,
|
||||
T a_bc, //border grey level.
|
||||
img<T>& a_res){
|
||||
// We assume that a_imgs.size() is a_cols*a_rows and that all images have same (w,h,bpp).
|
||||
|
||||
unsigned int num = a_cols*a_rows;
|
||||
if(!num) {a_res.make_empty();return false;}
|
||||
|
||||
unsigned int aw = a_imgs[0].m_w;
|
||||
unsigned int ah = a_imgs[0].m_h;
|
||||
unsigned int an = a_imgs[0].m_n;
|
||||
|
||||
for(unsigned int index=1;index<num;index++) {
|
||||
if(a_imgs[index].m_n!=an) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
if(a_imgs[index].m_w!=aw) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
if(a_imgs[index].m_h!=ah) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int wbw = aw + 2*a_bw;
|
||||
unsigned int hbh = ah + 2*a_bh;
|
||||
|
||||
unsigned int rw = wbw * a_cols;
|
||||
unsigned int rh = hbh * a_rows;
|
||||
unsigned int rn = an;
|
||||
|
||||
//printf("debug : %d %d\n",rw,rh);
|
||||
|
||||
// on big concatenated image the below may fail :
|
||||
unsigned int rsz = rh*rw*rn;
|
||||
T* rb = new T[rsz];
|
||||
if(!rb) {
|
||||
a_res.make_empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
//unsigned int wbwn = wbw*an;
|
||||
unsigned int awn = aw*an;
|
||||
unsigned int rwn = rw*an;
|
||||
|
||||
bool has_border = a_bw||a_bh?true:false;
|
||||
if(has_border) {
|
||||
::memset(rb,a_bc,rsz*sizeof(T));
|
||||
}
|
||||
|
||||
//copy tiles :
|
||||
unsigned int index = 0;
|
||||
for(unsigned int j=0;j<a_rows;j++) {
|
||||
for(unsigned int i=0;i<a_cols;i++) {
|
||||
T* tile = a_imgs[index].buffer();
|
||||
|
||||
/*
|
||||
if(has_border) {
|
||||
for(unsigned int r=0;r<hbh;r++) {
|
||||
T* pos = rb + (j*hbh+r)*rwn + i*wbwn;
|
||||
::memset(pos,a_bc,wbwn*sizeof(T));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
{for(unsigned int r=0;r<ah;r++) {
|
||||
T* pos = rb + (j*hbh+r+a_bh)*rwn + (i*wbw+a_bw)*rn;
|
||||
T* ptile = tile+r*awn;
|
||||
for(unsigned int c=0;c<awn;c++) *pos++ = *ptile++;
|
||||
}}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
a_res.set(rw,rh,rn,rb,true);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
unsigned int m_w;
|
||||
unsigned int m_h;
|
||||
unsigned int m_n;
|
||||
T* m_buffer;
|
||||
bool m_owner;
|
||||
|
||||
private: static void check_instantiation() {img<float> dummy;}
|
||||
};
|
||||
|
||||
|
||||
typedef img<unsigned char> img_byte;
|
||||
|
||||
// NOTE : img_byte is ready for OpenGL glTexImage2D UNSIGNED_BYTE RGB.
|
||||
// For glTexImage2D, first row in m_buffer is bottom of image.
|
||||
|
||||
inline void tex_expand_size(unsigned int a_w,unsigned int& a_h,
|
||||
unsigned int& a_ew,unsigned int& a_eh){
|
||||
// find closest power of two upper than a_w, a_h :
|
||||
a_ew = 2;
|
||||
while(true) {if(a_ew>=a_w) break;a_ew *=2;}
|
||||
a_eh = 2;
|
||||
while(true) {if(a_eh>=a_h) break;a_eh *=2;}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_impi
|
||||
#define tools_impi
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace tools {
|
||||
|
||||
class impi {
|
||||
public:
|
||||
virtual ~impi(){}
|
||||
public:
|
||||
virtual bool pack(unsigned int) = 0;
|
||||
virtual bool pack(double) = 0;
|
||||
virtual bool bpack(bool) = 0;
|
||||
virtual bool spack(const std::string&) = 0;
|
||||
virtual bool vpack(const std::vector<unsigned int>&) = 0;
|
||||
virtual bool vpack(const std::vector<double>&) = 0;
|
||||
|
||||
virtual bool unpack(unsigned int&) = 0;
|
||||
virtual bool unpack(double&) = 0;
|
||||
virtual bool bunpack(bool&) = 0;
|
||||
virtual bool sunpack(std::string&) = 0;
|
||||
virtual bool vunpack(std::vector<unsigned int>&) = 0;
|
||||
virtual bool vunpack(std::vector<double>&) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_impi_world
|
||||
#define tools_impi_world
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace tools {
|
||||
|
||||
class impi_world {
|
||||
public:
|
||||
virtual ~impi_world(){}
|
||||
public:
|
||||
virtual bool init(int*,char***) = 0;
|
||||
virtual bool rank(int& a_rank) const = 0;
|
||||
virtual bool size(int& a_size) const = 0;
|
||||
virtual bool processor_name(std::string&) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_io_irbuf
|
||||
#define tools_io_irbuf
|
||||
|
||||
#include "../typedefs"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include "../mem"
|
||||
#endif
|
||||
|
||||
namespace tools {
|
||||
namespace io {
|
||||
|
||||
class irbuf {
|
||||
public:
|
||||
virtual ~irbuf() {}
|
||||
public:
|
||||
virtual bool read(uchar&) = 0;
|
||||
virtual bool read(char&) = 0;
|
||||
virtual bool read(uint16&) = 0;
|
||||
virtual bool read(int16&) = 0;
|
||||
virtual bool read(uint32&) = 0;
|
||||
virtual bool read(int32&) = 0;
|
||||
virtual bool read(uint64&) = 0;
|
||||
virtual bool read(int64&) = 0;
|
||||
virtual bool read(float&) = 0;
|
||||
virtual bool read(double&) = 0;
|
||||
virtual bool read(bool&) = 0;
|
||||
|
||||
virtual bool read_vec(uint32&,uchar*&) = 0;
|
||||
virtual bool read_vec(uint32&,char*&) = 0;
|
||||
virtual bool read_vec(uint32&,uint16*&) = 0;
|
||||
virtual bool read_vec(uint32&,int16*&) = 0;
|
||||
virtual bool read_vec(uint32&,uint32*&) = 0;
|
||||
virtual bool read_vec(uint32&,int32*&) = 0;
|
||||
virtual bool read_vec(uint32&,uint64*&) = 0;
|
||||
virtual bool read_vec(uint32&,int64*&) = 0;
|
||||
virtual bool read_vec(uint32&,float*&) = 0;
|
||||
virtual bool read_vec(uint32&,double*&) = 0;
|
||||
virtual bool read_vec(uint32&,bool*&) = 0;
|
||||
|
||||
virtual bool read_vec(std::vector<std::string>&) = 0;
|
||||
|
||||
virtual bool read_cstr(char*&) = 0;
|
||||
virtual bool read_img(uint32&,uint32&,uint32&,uchar*&) = 0;
|
||||
|
||||
typedef std::vector< std::vector<unsigned int> > std_vec_vec_uint_t;
|
||||
virtual bool read_std_vec_vec(std_vec_vec_uint_t&) = 0;
|
||||
|
||||
typedef std::vector< std::vector<float> > std_vec_vec_float_t;
|
||||
virtual bool read_std_vec_vec(std_vec_vec_float_t&) = 0;
|
||||
|
||||
typedef std::vector< std::vector<double> > std_vec_vec_double_t;
|
||||
virtual bool read_std_vec_vec(std_vec_vec_double_t&) = 0;
|
||||
|
||||
typedef std::vector< std::vector<std::string> > std_vec_vec_string_t;
|
||||
virtual bool read_std_vec_vec(std_vec_vec_string_t&) = 0;
|
||||
public: //helpers
|
||||
template <class T>
|
||||
bool read_std_vec(std::vector<T>& a_x) {
|
||||
uint32 n;
|
||||
T* v;
|
||||
if(!read_vec(n,v)) return false;
|
||||
a_x.resize(n);
|
||||
for(uint32 index=0;index<n;index++) a_x[index] = v[index];
|
||||
delete [] v;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::decrement(s_new().c_str());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_io_iwbuf
|
||||
#define tools_io_iwbuf
|
||||
|
||||
#include "../typedefs"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace tools {
|
||||
namespace io {
|
||||
|
||||
class iwbuf {
|
||||
public:
|
||||
virtual ~iwbuf() {}
|
||||
public:
|
||||
virtual bool write(uchar) = 0;
|
||||
virtual bool write(char) = 0;
|
||||
virtual bool write(uint16) = 0;
|
||||
virtual bool write(int16) = 0;
|
||||
virtual bool write(uint32) = 0;
|
||||
virtual bool write(int32) = 0;
|
||||
virtual bool write(uint64) = 0;
|
||||
virtual bool write(int64) = 0;
|
||||
virtual bool write(float) = 0;
|
||||
virtual bool write(double) = 0;
|
||||
virtual bool write(bool) = 0;
|
||||
|
||||
virtual bool write_vec(uint32,const uchar*) = 0;
|
||||
virtual bool write_vec(uint32,const char*) = 0;
|
||||
virtual bool write_vec(uint32,const uint16*) = 0;
|
||||
virtual bool write_vec(uint32,const int16*) = 0;
|
||||
virtual bool write_vec(uint32,const uint32*) = 0;
|
||||
virtual bool write_vec(uint32,const int32*) = 0;
|
||||
virtual bool write_vec(uint32,const uint64*) = 0;
|
||||
virtual bool write_vec(uint32,const int64*) = 0;
|
||||
virtual bool write_vec(uint32,const float*) = 0;
|
||||
virtual bool write_vec(uint32,const double*) = 0;
|
||||
virtual bool write_vec(uint32,const bool*) = 0;
|
||||
|
||||
virtual bool write_vec(const std::vector<std::string>&) = 0;
|
||||
|
||||
virtual bool write_cstr(const char* a_cstr) = 0;
|
||||
|
||||
virtual bool write_img(uint32,uint32,uint32,const uchar*) = 0;
|
||||
|
||||
typedef std::vector< std::vector<unsigned int> > std_vec_vec_uint_t;
|
||||
virtual bool write_std_vec_vec(const std_vec_vec_uint_t&) = 0;
|
||||
|
||||
typedef std::vector< std::vector<float> > std_vec_vec_float_t;
|
||||
virtual bool write_std_vec_vec(const std_vec_vec_float_t&) = 0;
|
||||
|
||||
typedef std::vector< std::vector<double> > std_vec_vec_double_t;
|
||||
virtual bool write_std_vec_vec(const std_vec_vec_double_t&) = 0;
|
||||
|
||||
typedef std::vector< std::vector<std::string> > std_vec_vec_string_t;
|
||||
virtual bool write_std_vec_vec(const std_vec_vec_string_t&) = 0;
|
||||
public:
|
||||
virtual const char* buf() const = 0;
|
||||
virtual uint32 length() const = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,657 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_MATCOM
|
||||
#define tools_MATCOM
|
||||
|
||||
/* NOTE : bof, no big improvement.
|
||||
#include <cstring> //memcpy
|
||||
inline void vec_copy(double* a_to,const double* a_from,unsigned int a_number) {
|
||||
::memcpy(a_to,a_from,a_number*sizeof(double));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void vec_copy(T* a_to,const T* a_from,unsigned int a_number) {
|
||||
T* pto = (T*)a_to;
|
||||
T* pfm = (T*)a_from;
|
||||
for(unsigned int i=0;i<a_number;i++,pto++,pfm++) *pto = *pfm;
|
||||
}
|
||||
*/
|
||||
|
||||
/*NOTE : bof, no big improvement.
|
||||
#include <Accelerate/Accelerate.h>
|
||||
|
||||
inline void vec_add(const float* a_1,const float* a_2,float* a_res,unsigned int a_number) {
|
||||
::vDSP_vadd(a_1,1,a_2,1,a_res,1,a_number);
|
||||
}
|
||||
inline void vec_sub(const float* a_1,const float* a_2,float* a_res,unsigned int a_number) {
|
||||
::vDSP_vsub(a_1,1,a_2,1,a_res,1,a_number);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
template <class T>
|
||||
inline void vec_add(const T* a_1,const T* a_2,T* a_res,unsigned int a_number) {
|
||||
T* p1 = (T*)a_1;
|
||||
T* p2 = (T*)a_2;
|
||||
T* pr = (T*)a_res;
|
||||
for(unsigned int i=0;i<a_number;i++,p1++,p2++,pr++) *pr = *p1+*p2;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void vec_sub(const T* a_1,const T* a_2,T* a_res,unsigned int a_number) {
|
||||
T* p1 = (T*)a_1;
|
||||
T* p2 = (T*)a_2;
|
||||
T* pr = (T*)a_res;
|
||||
for(unsigned int i=0;i<a_number;i++,p1++,p2++,pr++) *pr = *p1-*p2;
|
||||
}
|
||||
*/
|
||||
|
||||
// common code to class mat and nmat.
|
||||
|
||||
#define TOOLS_MATCOM \
|
||||
protected:\
|
||||
static T zero() {return T();}\
|
||||
static T one() {return T(1);}\
|
||||
static T minus_one() {return T(-1);}\
|
||||
static T two() {return T(2);}\
|
||||
public:\
|
||||
typedef T elem_t;\
|
||||
typedef unsigned int size_type;\
|
||||
public:\
|
||||
unsigned int rows() const {return dimension();}\
|
||||
unsigned int cols() const {return dimension();}\
|
||||
\
|
||||
void set_value(unsigned int aR,unsigned int aC,const T& a_value) { \
|
||||
m_vec[aR + aC * dimension()] = a_value;\
|
||||
}\
|
||||
\
|
||||
const T& value(unsigned int aR,unsigned int aC) const { \
|
||||
return m_vec[aR + aC * dimension()];\
|
||||
}\
|
||||
\
|
||||
T value(unsigned int aR,unsigned int aC) { \
|
||||
return m_vec[aR + aC * dimension()];\
|
||||
}\
|
||||
\
|
||||
void set_matrix(const TOOLS_MAT_CLASS& a_m){ /*optimization.*/\
|
||||
_copy(a_m.m_vec);\
|
||||
}\
|
||||
\
|
||||
void set_constant(const T& a_v){\
|
||||
for(unsigned int i=0;i<dim2();i++) m_vec[i] = a_v;\
|
||||
}\
|
||||
void set_zero(){\
|
||||
set_constant(zero());\
|
||||
}\
|
||||
void set_identity() {\
|
||||
set_zero();\
|
||||
for(unsigned int i=0;i<dimension();i++) m_vec[i+i*dimension()] = one();\
|
||||
}\
|
||||
void set_diagonal(const T& a_s) {\
|
||||
set_zero();\
|
||||
for(unsigned int i=0;i<dimension();i++) m_vec[i+i*dimension()] = a_s;\
|
||||
}\
|
||||
typedef T (*func)(const T&);\
|
||||
void apply_func(func a_func) {\
|
||||
T* pos = m_vec;\
|
||||
for(unsigned int i=0;i<dim2();i++,pos++) *pos = a_func(*pos);\
|
||||
}\
|
||||
template <class RANDOM>\
|
||||
void set_random(RANDOM& a_random) {\
|
||||
for(unsigned int i=0;i<dim2();i++) m_vec[i] = a_random.shoot();\
|
||||
}\
|
||||
public:\
|
||||
template <class VEC>\
|
||||
bool mul_vec(VEC& a_vec,T a_tmp[]) const {\
|
||||
/* a_vec = this *= a_vec */\
|
||||
unsigned int _dim = dimension();\
|
||||
if(a_vec.dimension()!=_dim) return false;\
|
||||
T* pos = a_tmp;\
|
||||
for(unsigned int r=0;r<_dim;r++,pos++) {\
|
||||
*pos = T();\
|
||||
for(unsigned int c=0;c<_dim;c++) *pos += m_vec[r+c*_dim]*a_vec[c];\
|
||||
}\
|
||||
{for(unsigned int i=0;i<_dim;i++) a_vec[i] = a_tmp[i];}\
|
||||
return true;\
|
||||
}\
|
||||
template <class VEC>\
|
||||
bool mul_vec(VEC& a_vec) const {\
|
||||
T* res = new T[dimension()];\
|
||||
bool status = mul_vec(a_vec,res);\
|
||||
delete [] res;\
|
||||
return status;\
|
||||
}\
|
||||
void mul_mtx(const TOOLS_MAT_CLASS& a_m) {\
|
||||
_mul_mtx(a_m.m_vec);\
|
||||
}\
|
||||
void mul_mtx(const TOOLS_MAT_CLASS& a_m,T a_tmp[]) {\
|
||||
_mul_mtx(a_m.m_vec,a_tmp);\
|
||||
}\
|
||||
void left_mul_mtx(const TOOLS_MAT_CLASS& a_m) { \
|
||||
/* this = a_m * this :*/\
|
||||
_left_mul_mtx(a_m.m_vec);\
|
||||
}\
|
||||
bool equal(const TOOLS_MAT_CLASS& a_m) const {\
|
||||
if(&a_m==this) return true;\
|
||||
for(unsigned int i=0;i<dim2();i++) {\
|
||||
if(m_vec[i]!=a_m.m_vec[i]) return false;\
|
||||
}\
|
||||
return true;\
|
||||
}\
|
||||
\
|
||||
bool equal(const TOOLS_MAT_CLASS& a_m,const T& a_prec) const {\
|
||||
if(&a_m==this) return true;\
|
||||
T* tp = (T*)m_vec;\
|
||||
T* mp = (T*)a_m.m_vec;\
|
||||
for(unsigned int i=0;i<dim2();i++,tp++,mp++) {\
|
||||
T diff = (*tp) - (*mp);\
|
||||
if(diff<zero()) diff *= minus_one();\
|
||||
if(diff>=a_prec) return false;\
|
||||
}\
|
||||
return true;\
|
||||
}\
|
||||
\
|
||||
void mx_diff(const TOOLS_MAT_CLASS& a_m,T& a_mx_diff) const {\
|
||||
T* tp = (T*)m_vec;\
|
||||
T* mp = (T*)a_m.m_vec;\
|
||||
a_mx_diff = (*tp) - (*mp);\
|
||||
if(a_mx_diff<zero()) a_mx_diff *= minus_one();\
|
||||
for(unsigned int i=0;i<dim2();i++,tp++,mp++) {\
|
||||
T diff = (*tp) - (*mp);\
|
||||
if(diff<zero()) diff *= minus_one();\
|
||||
a_mx_diff = (diff>a_mx_diff?diff:a_mx_diff);\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
bool is_proportional(const TOOLS_MAT_CLASS& a_m,const T& a_prec,T& a_factor) const {\
|
||||
if(&a_m==this) {a_factor=one();return true;}\
|
||||
/* If true, then : a_m = a_factor * this.*/\
|
||||
a_factor = zero();\
|
||||
T* tp = (T*)m_vec;\
|
||||
T* mp = (T*)a_m.m_vec;\
|
||||
bool first = true;\
|
||||
for(unsigned int i=0;i<dim2();i++,tp++,mp++) {\
|
||||
if( ((*tp)==zero()) && ((*mp)==zero())) {\
|
||||
continue;\
|
||||
} else if( ((*tp)!=zero()) && ((*mp)==zero())) {\
|
||||
return false;\
|
||||
} else if( ((*tp)==zero()) && ((*mp)!=zero())) {\
|
||||
return false;\
|
||||
} else {\
|
||||
if(first) {\
|
||||
a_factor = (*mp)/(*tp);\
|
||||
first = false;\
|
||||
} else {\
|
||||
T diff = (*tp)*a_factor - (*mp);\
|
||||
if(diff<zero()) diff *= minus_one();\
|
||||
if(diff>=a_prec) return false;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
return true;\
|
||||
}\
|
||||
\
|
||||
const T* data() const {return m_vec;}\
|
||||
unsigned int size() const {return dim2();}\
|
||||
unsigned int data_size() const {return dim2();} /*for mathz*/\
|
||||
\
|
||||
T trace() const {\
|
||||
T _value = zero();\
|
||||
unsigned int _D = dimension();\
|
||||
for(unsigned int c=0;c<_D;c++) _value += m_vec[c+c*_D];\
|
||||
return _value;\
|
||||
}\
|
||||
\
|
||||
void transpose() {\
|
||||
unsigned int _D = dimension();\
|
||||
for(unsigned int r=0;r<_D;r++) {\
|
||||
for(unsigned int c=(r+1);c<_D;c++) {\
|
||||
T vrc = value(r,c);\
|
||||
T vcr = value(c,r);\
|
||||
set_value(r,c,vcr);\
|
||||
set_value(c,r,vrc);\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
void multiply(const T& a_T) {\
|
||||
for(unsigned int i=0;i<dim2();i++) m_vec[i] *= a_T;\
|
||||
}\
|
||||
\
|
||||
bool is_symmetric() const {\
|
||||
unsigned int _D = dimension();\
|
||||
for(unsigned int r=0;r<_D;r++) {\
|
||||
for(unsigned int c=(r+1);c<_D;c++) {\
|
||||
if(value(r,c)!=value(c,r)) return false;\
|
||||
}\
|
||||
}\
|
||||
return true;\
|
||||
}\
|
||||
\
|
||||
bool is_antisymmetric() const {\
|
||||
unsigned int _D = dimension();\
|
||||
{for(unsigned int r=0;r<_D;r++) {\
|
||||
if(value(r,r)!=zero()) return false;\
|
||||
}}\
|
||||
for(unsigned int r=0;r<_D;r++) {\
|
||||
for(unsigned int c=(r+1);c<_D;c++) {\
|
||||
if(value(r,c)!=minus_one()*value(c,r)) return false;\
|
||||
}\
|
||||
}\
|
||||
return true;\
|
||||
}\
|
||||
\
|
||||
void symmetric_part(TOOLS_MAT_CLASS& a_res) const {\
|
||||
a_res = *this;\
|
||||
a_res.transpose();\
|
||||
a_res += *this;\
|
||||
a_res.multiply(one()/two());\
|
||||
}\
|
||||
\
|
||||
void antisymmetric_part(TOOLS_MAT_CLASS& a_res) const {\
|
||||
a_res = *this;\
|
||||
a_res.transpose();\
|
||||
a_res.multiply(minus_one());\
|
||||
a_res += *this;\
|
||||
a_res.multiply(one()/two());\
|
||||
}\
|
||||
\
|
||||
T determinant(unsigned int a_tmp_rs[],unsigned int a_tmp_cs[]) const { /*[rord=dim-1]*/ \
|
||||
unsigned int ord = dimension();\
|
||||
if(ord==0) {\
|
||||
return zero();\
|
||||
} else if(ord==1) {\
|
||||
return *m_vec;\
|
||||
} else if(ord==2) {\
|
||||
T v00 = *m_vec;\
|
||||
T v01 = *(m_vec+ord);\
|
||||
T v10 = *(m_vec+1);\
|
||||
T v11 = *(m_vec+1+ord);\
|
||||
return (v00 * v11 - v10 * v01);\
|
||||
} else if(ord==3) {\
|
||||
/* 00 01 02 \
|
||||
10 11 12 \
|
||||
20 21 22 \
|
||||
*/\
|
||||
T v01 = *(m_vec+ord);\
|
||||
T v02 = *(m_vec+2*ord);\
|
||||
T v11 = *(m_vec+1+ord);\
|
||||
T v12 = *(m_vec+1+2*ord);\
|
||||
T v21 = *(m_vec+2+ord);\
|
||||
T v22 = *(m_vec+2+2*ord);\
|
||||
T cof_00 = v11 * v22 - v21 * v12;\
|
||||
T cof_10 = v01 * v22 - v21 * v02;\
|
||||
T cof_20 = v01 * v12 - v11 * v02;\
|
||||
T v00 = *m_vec;\
|
||||
T v10 = *(m_vec+1);\
|
||||
T v20 = *(m_vec+2);\
|
||||
return (v00*cof_00-v10*cof_10+v20*cof_20);\
|
||||
}\
|
||||
\
|
||||
unsigned int rord = ord-1;\
|
||||
\
|
||||
T v_rc;\
|
||||
\
|
||||
T det = zero();\
|
||||
{for(unsigned int i=0;i<rord;i++) {a_tmp_cs[i] = i+1;}}\
|
||||
unsigned int c = 0;\
|
||||
\
|
||||
{for(unsigned int i=0;i<rord;i++) {a_tmp_rs[i] = i+1;}}\
|
||||
bool sg = true; /*c=0+r=0*/\
|
||||
for(unsigned int r=0;r<ord;r++) {\
|
||||
if(r>=1) a_tmp_rs[r-1] = r-1;\
|
||||
v_rc = value(r,c);\
|
||||
if(v_rc!=zero()) {\
|
||||
T subdet = sub_determinant(rord,a_tmp_rs,a_tmp_cs);\
|
||||
if(sg) \
|
||||
det += v_rc * subdet;\
|
||||
else\
|
||||
det -= v_rc * subdet;\
|
||||
}\
|
||||
sg = sg?false:true;\
|
||||
}\
|
||||
\
|
||||
return det;\
|
||||
}\
|
||||
\
|
||||
T determinant() const {\
|
||||
unsigned int ord = dimension();\
|
||||
if(ord==0) {\
|
||||
return zero();\
|
||||
} else if(ord==1) {\
|
||||
return *m_vec;\
|
||||
} else if(ord==2) {\
|
||||
T v00 = *m_vec;\
|
||||
T v01 = *(m_vec+ord);\
|
||||
T v10 = *(m_vec+1);\
|
||||
T v11 = *(m_vec+1+ord);\
|
||||
return (v00 * v11 - v10 * v01);\
|
||||
} else if(ord==3) {\
|
||||
T v01 = *(m_vec+ord);\
|
||||
T v02 = *(m_vec+2*ord);\
|
||||
T v11 = *(m_vec+1+ord);\
|
||||
T v12 = *(m_vec+1+2*ord);\
|
||||
T v21 = *(m_vec+2+ord);\
|
||||
T v22 = *(m_vec+2+2*ord);\
|
||||
T cof_00 = v11 * v22 - v21 * v12;\
|
||||
T cof_10 = v01 * v22 - v21 * v02;\
|
||||
T cof_20 = v01 * v12 - v11 * v02;\
|
||||
T v00 = *m_vec;\
|
||||
T v10 = *(m_vec+1);\
|
||||
T v20 = *(m_vec+2);\
|
||||
return (v00*cof_00-v10*cof_10+v20*cof_20);\
|
||||
}\
|
||||
unsigned int rord = ord-1;\
|
||||
unsigned int* rs = new unsigned int[rord];\
|
||||
unsigned int* cs = new unsigned int[rord];\
|
||||
T det = determinant(rs,cs);\
|
||||
delete [] rs;\
|
||||
delete [] cs;\
|
||||
return det;\
|
||||
}\
|
||||
\
|
||||
bool invert(TOOLS_MAT_CLASS& a_res) const {\
|
||||
/*Generic invertion method.*/\
|
||||
unsigned int ord = dimension();\
|
||||
if(ord==0) return true;\
|
||||
\
|
||||
if(ord==1) {\
|
||||
T v = value(0,0);\
|
||||
if(v==zero()) return false;\
|
||||
a_res.set_value(0,0,one()/v);\
|
||||
return true;\
|
||||
}\
|
||||
\
|
||||
unsigned int rord = ord-1;\
|
||||
unsigned int* cs = new unsigned int[rord];\
|
||||
unsigned int* rs = new unsigned int[rord];\
|
||||
\
|
||||
/* Get det with r = 0;*/\
|
||||
T det = zero();\
|
||||
{\
|
||||
{for(unsigned int i=0;i<rord;i++) {rs[i] = i+1;}}\
|
||||
unsigned int r = 0;\
|
||||
/*if(r>=1) rs[r-1] = r-1;*/\
|
||||
\
|
||||
{for(unsigned int i=0;i<rord;i++) {cs[i] = i+1;}}\
|
||||
bool sg = true; /*r=0+c=0*/\
|
||||
for(unsigned int c=0;c<ord;c++) {\
|
||||
if(c>=1) cs[c-1] = c-1;\
|
||||
T subdet = sub_determinant(rord,rs,cs);\
|
||||
T sgn = sg ? one() : minus_one();\
|
||||
det += value(r,c) * subdet * sgn;\
|
||||
T _value = subdet * sgn;\
|
||||
a_res.set_value(c,r,_value);\
|
||||
sg = sg?false:true;\
|
||||
}}\
|
||||
\
|
||||
if(det==zero()) {\
|
||||
delete [] cs;\
|
||||
delete [] rs;\
|
||||
return false;\
|
||||
} \
|
||||
\
|
||||
{for(unsigned int c=0;c<ord;c++) {\
|
||||
a_res.set_value(c,0,a_res.value(c,0)/det);\
|
||||
}}\
|
||||
\
|
||||
{for(unsigned int i=0;i<rord;i++) {rs[i] = i+1;}}\
|
||||
bool sgr = false; /*r=1+c=0*/\
|
||||
for(unsigned int r=1;r<ord;r++) {\
|
||||
if(r>=1) rs[r-1] = r-1;\
|
||||
{for(unsigned int i=0;i<rord;i++) {cs[i] = i+1;}}\
|
||||
bool sg = sgr;\
|
||||
for(unsigned int c=0;c<ord;c++) {\
|
||||
if(c>=1) cs[c-1] = c-1;\
|
||||
T subdet = sub_determinant(rord,rs,cs);\
|
||||
T sgn = sg ? one() : minus_one();\
|
||||
T _value = (subdet * sgn)/det;\
|
||||
a_res.set_value(c,r,_value);\
|
||||
sg = sg?false:true;\
|
||||
}\
|
||||
sgr = sgr?false:true;\
|
||||
}\
|
||||
\
|
||||
delete [] cs;\
|
||||
delete [] rs;\
|
||||
\
|
||||
return true;\
|
||||
}\
|
||||
\
|
||||
void power(unsigned int a_n,TOOLS_MAT_CLASS& a_res) const {\
|
||||
a_res.set_identity();\
|
||||
for(unsigned int i=0;i<a_n;i++) {\
|
||||
a_res._mul_mtx(m_vec);\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
void exp(unsigned int a_le,TOOLS_MAT_CLASS& a_res) const {\
|
||||
/* result = I + M + M**2/2! + M**3/3! + .... */\
|
||||
a_res.set_identity();\
|
||||
TOOLS_MAT_CLASS tmp(*this);\
|
||||
tmp.set_identity();\
|
||||
for(unsigned int i=1;i<=a_le;i++) {\
|
||||
tmp._mul_mtx(m_vec);\
|
||||
tmp.multiply(one()/T(i)); \
|
||||
a_res += tmp;\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
void log(unsigned int a_le,TOOLS_MAT_CLASS& a_res) const {\
|
||||
/* result = (M-I) - (M-I)**2/2 + (M-I)**3/3 +... */\
|
||||
/* WARNING : touchy, it may not converge ! */\
|
||||
a_res.set_zero();\
|
||||
\
|
||||
TOOLS_MAT_CLASS M_I;\
|
||||
M_I.set_identity();\
|
||||
M_I.multiply(minus_one());\
|
||||
M_I._add_mtx(m_vec);\
|
||||
\
|
||||
TOOLS_MAT_CLASS M_Ip(M_I);\
|
||||
T fact = -1;\
|
||||
\
|
||||
TOOLS_MAT_CLASS tmp;\
|
||||
\
|
||||
for(unsigned int i=0;i<=a_le;i++) {\
|
||||
fact *= minus_one(); \
|
||||
tmp = M_Ip;\
|
||||
tmp.multiply(fact/T(i+1)); \
|
||||
a_res += tmp;\
|
||||
M_Ip._mul_mtx(M_I.m_vec);\
|
||||
}\
|
||||
}\
|
||||
template <class MAT>\
|
||||
bool copy(const MAT& a_from) {\
|
||||
/*for exa from a double matrix to a symbol matrix*/\
|
||||
unsigned int _D = dimension();\
|
||||
if(a_from.dimension()!=_D) return false;\
|
||||
for(unsigned int r=0;r<_D;r++) {\
|
||||
for(unsigned int c=0;c<_D;c++) {\
|
||||
set_value(r,c,a_from.value(r,c));\
|
||||
}\
|
||||
}\
|
||||
return true;\
|
||||
}\
|
||||
public: /*operators*/\
|
||||
T operator()(unsigned int a_r,unsigned int a_c) const {\
|
||||
/*WARNING : no check on a_r,a_c.*/\
|
||||
return m_vec[a_r + a_c * dimension()];\
|
||||
}\
|
||||
\
|
||||
T& operator[](unsigned int a_index) { /*for inlib/sg/sf_vec*/\
|
||||
/*WARNING : no check on a_index.*/\
|
||||
return m_vec[a_index];\
|
||||
}\
|
||||
const T& operator[](unsigned int a_index) const {\
|
||||
/*WARNING : no check on a_index.*/\
|
||||
return m_vec[a_index];\
|
||||
}\
|
||||
bool operator==(const TOOLS_MAT_CLASS& a_array) const {\
|
||||
return equal(a_array);\
|
||||
}\
|
||||
bool operator!=(const TOOLS_MAT_CLASS& a_array) const {\
|
||||
return !operator==(a_array);\
|
||||
}\
|
||||
TOOLS_MAT_CLASS& operator*=(const TOOLS_MAT_CLASS& a_m) {\
|
||||
_mul_mtx(a_m.m_vec);\
|
||||
return *this;\
|
||||
}\
|
||||
TOOLS_MAT_CLASS& operator+=(const TOOLS_MAT_CLASS& a_m) {\
|
||||
_add_mtx(a_m.m_vec);\
|
||||
return *this;\
|
||||
}\
|
||||
TOOLS_MAT_CLASS& operator-=(const TOOLS_MAT_CLASS& a_m) {\
|
||||
_sub_mtx(a_m.m_vec);\
|
||||
return *this;\
|
||||
}\
|
||||
TOOLS_MAT_CLASS& operator*=(const T& a_fac) {\
|
||||
for(unsigned int i=0;i<dim2();i++) m_vec[i] *= a_fac;\
|
||||
return *this;\
|
||||
}\
|
||||
\
|
||||
TOOLS_MAT_CLASS operator*(const T& a_fac) {\
|
||||
TOOLS_MAT_CLASS res;\
|
||||
res.operator*=(a_fac);\
|
||||
return res;\
|
||||
}\
|
||||
protected:\
|
||||
void _copy(const T a_m[]) {\
|
||||
{T* tp = (T*)m_vec;T* ap = (T*)a_m;\
|
||||
for(unsigned int i=0;i<dim2();i++,tp++,ap++) *tp = *ap;}\
|
||||
/*{for(unsigned int i=0;i<dim2();i++) m_vec[i] = a_m[i];}*/\
|
||||
/* memcpy does not work with std::complex<> and mat<symbol,4> see inlib/tests/symbolic.cpp */\
|
||||
/*vec_copy(m_vec,a_m,dim2());*/\
|
||||
}\
|
||||
\
|
||||
void _add_mtx(const T a_m[]) { /* this = this + a_m, */\
|
||||
{T* tp = (T*)m_vec;T* ap = (T*)a_m;\
|
||||
for(unsigned int i=0;i<dim2();i++,tp++,ap++) *tp += *ap;}\
|
||||
/*for(unsigned int i=0;i<dim2();i++) m_vec[i] += a_m[i];*/\
|
||||
/*vec_add(m_vec,a_m,m_vec,dim2());*/\
|
||||
}\
|
||||
void _sub_mtx(const T a_m[]) { /* this = this - a_m, */\
|
||||
{T* tp = (T*)m_vec;T* ap = (T*)a_m;\
|
||||
for(unsigned int i=0;i<dim2();i++,tp++,ap++) *tp -= *ap;}\
|
||||
/*for(unsigned int i=0;i<dim2();i++) m_vec[i] -= a_m[i];*/\
|
||||
/*vec_sub(m_vec,a_m,m_vec,dim2());*/\
|
||||
}\
|
||||
\
|
||||
/*\
|
||||
void _mul_mtx(const T a_m[],T a_tmp[]) {\
|
||||
unsigned int ord = dimension();\
|
||||
for(unsigned int r=0;r<ord;r++) {\
|
||||
for(unsigned int c=0;c<ord;c++) {\
|
||||
T _value = zero();\
|
||||
for(unsigned int i=0;i<ord;i++) {\
|
||||
_value += (*(m_vec+r+i*ord)) * (*(a_m+i+c*ord)); //optimize.\
|
||||
}\
|
||||
*(a_tmp+r+c*ord) = _value;\
|
||||
}\
|
||||
}\
|
||||
_copy(a_tmp);\
|
||||
}\
|
||||
*/\
|
||||
void _mul_mtx(const T a_m[],T a_tmp[]) { /*OPTIMIZATION*/\
|
||||
/* this = this * a_m */\
|
||||
typedef T* Tp;\
|
||||
Tp tpos,ttpos,rpos,apos,mpos,aapos;\
|
||||
T _value;\
|
||||
unsigned int r,c,i;\
|
||||
\
|
||||
unsigned int _D = dimension();\
|
||||
\
|
||||
tpos = a_tmp;\
|
||||
for(r=0;r<_D;r++,tpos++) {\
|
||||
ttpos = tpos;\
|
||||
rpos = m_vec+r;\
|
||||
apos = (T*)a_m;\
|
||||
for(c=0;c<_D;c++,ttpos+=_D,apos+=_D) {\
|
||||
_value = zero();\
|
||||
mpos = rpos;\
|
||||
aapos = apos;\
|
||||
for(i=0;i<_D;i++,mpos+=_D,aapos++) _value += (*mpos) * (*aapos);\
|
||||
*ttpos = _value;\
|
||||
}\
|
||||
}\
|
||||
_copy(a_tmp);\
|
||||
}\
|
||||
\
|
||||
void _mul_mtx(const T a_m[]) {\
|
||||
T* res = new T[dim2()];\
|
||||
_mul_mtx(a_m,res);\
|
||||
delete [] res;\
|
||||
}\
|
||||
\
|
||||
void _left_mul_mtx(const T a_m[]) {\
|
||||
/* this = a_m * this */\
|
||||
unsigned int _D = dimension();\
|
||||
T* res = new T[dim2()];\
|
||||
for(unsigned int r=0;r<_D;r++) {\
|
||||
for(unsigned int c=0;c<_D;c++) {\
|
||||
T _value = zero();\
|
||||
for(unsigned int i=0;i<_D;i++) {\
|
||||
_value += (*(a_m+r+i*_D)) * (*(m_vec+i+c*_D)); /*optimize.*/\
|
||||
}\
|
||||
*(res+r+c*_D) = _value;\
|
||||
}\
|
||||
}\
|
||||
_copy(res);\
|
||||
delete [] res;\
|
||||
}\
|
||||
\
|
||||
T sub_determinant(unsigned int a_ord,unsigned int aRs[],unsigned int aCs[]) const {\
|
||||
/*WARNING : to optimize, we do not check the content of aRs, aCs.*/\
|
||||
unsigned int ord = a_ord;\
|
||||
if(ord==0) return zero();\
|
||||
else if(ord==1) return value(aRs[0],aCs[0]);\
|
||||
else if(ord==2) {\
|
||||
/*return (value(aRs[0],aCs[0]) * value(aRs[1],aCs[1]) -\
|
||||
value(aRs[1],aCs[0]) * value(aRs[0],aCs[1])); \
|
||||
Optimize the upper :*/\
|
||||
\
|
||||
unsigned int r_0 = aRs[0];\
|
||||
unsigned int r_1 = aRs[1];\
|
||||
unsigned int c_0 = aCs[0];\
|
||||
unsigned int c_1 = aCs[1];\
|
||||
\
|
||||
unsigned int _ord = dimension();\
|
||||
const T* p = m_vec;\
|
||||
\
|
||||
return ( (*(p+r_0+c_0*_ord)) * (*(p+r_1+c_1*_ord)) -\
|
||||
(*(p+r_1+c_0*_ord)) * (*(p+r_0+c_1*_ord)) );\
|
||||
}\
|
||||
\
|
||||
unsigned int rord = ord-1;\
|
||||
unsigned int* cs = new unsigned int[rord];\
|
||||
unsigned int* rs = new unsigned int[rord];\
|
||||
\
|
||||
T v_rc;\
|
||||
\
|
||||
T det = zero();\
|
||||
{for(unsigned int i=0;i<rord;i++) {cs[i] = aCs[i+1];}}\
|
||||
unsigned int c = 0;\
|
||||
/*if(c>=1) cs[c-1] = c-1;*/\
|
||||
\
|
||||
{for(unsigned int i=0;i<rord;i++) {rs[i] = aRs[i+1];}}\
|
||||
bool sg = true; /*c=0+r=0*/\
|
||||
for(unsigned int r=0;r<ord;r++) {\
|
||||
if(r>=1) rs[r-1] = aRs[r-1];\
|
||||
v_rc = value(aRs[r],aCs[c]);\
|
||||
if(v_rc!=zero()) {\
|
||||
T subdet = sub_determinant(rord,rs,cs);\
|
||||
if(sg)\
|
||||
det += v_rc * subdet;\
|
||||
else\
|
||||
det -= v_rc * subdet;\
|
||||
}\
|
||||
sg = sg?false:true;\
|
||||
}\
|
||||
\
|
||||
delete [] cs;\
|
||||
delete [] rs;\
|
||||
\
|
||||
return det;\
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,145 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_box3
|
||||
#define tools_box3
|
||||
|
||||
#include "../mnmx"
|
||||
|
||||
//#include <limits>
|
||||
#include <ostream>
|
||||
|
||||
namespace tools {
|
||||
|
||||
template <class VEC3>
|
||||
class box3 {
|
||||
protected:
|
||||
typedef typename VEC3::elem_t T_t;
|
||||
//static T_t num_max() {return std::numeric_limits<T_t>::max();} //max is a forever pain on Windows.
|
||||
protected:
|
||||
box3(){
|
||||
//make_empty();
|
||||
}
|
||||
public:
|
||||
virtual ~box3() {}
|
||||
public:
|
||||
box3(const box3& a_from)
|
||||
:m_min(a_from.m_min)
|
||||
,m_max(a_from.m_max)
|
||||
{}
|
||||
box3& operator=(const box3& a_from){
|
||||
m_min = a_from.m_min;
|
||||
m_max = a_from.m_max;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
bool center(VEC3& a_center) const {
|
||||
if(is_empty()) {a_center.set_value(0,0,0);return false;} //??
|
||||
a_center.set_value((m_max[0] + m_min[0])/T_t(2),
|
||||
(m_max[1] + m_min[1])/T_t(2),
|
||||
(m_max[2] + m_min[2])/T_t(2));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_bounds(const VEC3& a_mn,const VEC3& a_mx){
|
||||
if( a_mn[0]>a_mx[0] || a_mn[1]>a_mx[1] || a_mn[2]>a_mx[2]) return false;
|
||||
m_min = a_mn;
|
||||
m_max = a_mx;
|
||||
return true;
|
||||
}
|
||||
bool set_bounds(T_t a_mn_x,T_t a_mn_y,T_t a_mn_z,
|
||||
T_t a_mx_x,T_t a_mx_y,T_t a_mx_z){
|
||||
if( a_mn_x>a_mx_x || a_mn_y>a_mx_y || a_mn_z>a_mx_z ) return false;
|
||||
m_min.set_value(a_mn_x,a_mn_y,a_mn_z);
|
||||
m_max.set_value(a_mx_x,a_mx_y,a_mx_z);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_size(T_t& a_dx,T_t& a_dy,T_t& a_dz) const {
|
||||
if(is_empty()) {a_dx = 0;a_dy = 0;a_dz = 0;return false;}
|
||||
a_dx = m_max[0] - m_min[0];
|
||||
a_dy = m_max[1] - m_min[1];
|
||||
a_dz = m_max[2] - m_min[2];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_empty() const {return m_max[0] < m_min[0];}
|
||||
|
||||
const VEC3& mn() const {return m_min;}
|
||||
const VEC3& mx() const {return m_max;}
|
||||
|
||||
bool back(VEC3& a_min,VEC3& a_min_y,VEC3& a_min_xy,VEC3& a_min_x) const {
|
||||
T_t dx,dy,dz;
|
||||
if(!get_size(dx,dy,dz)) return false; //WARNING : a_vecs not touched.
|
||||
// back (from m_min, clockwise order looking toward +z) :
|
||||
a_min = m_min;
|
||||
a_min_y.set_value (m_min.x() ,m_min.y()+dy,m_min.z());
|
||||
a_min_xy.set_value(m_min.x()+dx,m_min.y()+dy,m_min.z());
|
||||
a_min_x.set_value (m_min.x()+dx,m_min.y() ,m_min.z());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool front(VEC3& a_max,VEC3& a_max_x,VEC3& a_max_xy,VEC3& a_max_y) const {
|
||||
T_t dx,dy,dz;
|
||||
if(!get_size(dx,dy,dz)) return false; //WARNING : a_vecs not touched.
|
||||
// front (from m_max, clockwise order looking toward -z) :
|
||||
a_max = m_max;
|
||||
a_max_x.set_value (m_max.x()-dx,m_max.y() ,m_max.z());
|
||||
a_max_xy.set_value(m_max.x()-dx,m_max.y()-dy,m_max.z());
|
||||
a_max_y.set_value (m_max.x() ,m_max.y()-dy,m_max.z());
|
||||
return true;
|
||||
}
|
||||
|
||||
void extend_by(const VEC3& a_point) {
|
||||
// Extend the boundaries of the box by the given point, i.e. make the
|
||||
// point fit inside the box if it isn't already so.
|
||||
if(is_empty()) {
|
||||
set_bounds(a_point,a_point);
|
||||
} else {
|
||||
m_min.set_value(tools::mn<T_t>(a_point[0],m_min[0]),
|
||||
tools::mn<T_t>(a_point[1],m_min[1]),
|
||||
tools::mn<T_t>(a_point[2],m_min[2]));
|
||||
m_max.set_value(tools::mx<T_t>(a_point[0],m_max[0]),
|
||||
tools::mx<T_t>(a_point[1],m_max[1]),
|
||||
tools::mx<T_t>(a_point[2],m_max[2]));
|
||||
}
|
||||
}
|
||||
|
||||
void extend_by(T_t a_x,T_t a_y,T_t a_z) {
|
||||
// Extend the boundaries of the box by the given point, i.e. make the
|
||||
// point fit inside the box if it isn't already so.
|
||||
if(is_empty()) {
|
||||
set_bounds(a_x,a_y,a_z,a_x,a_y,a_z);
|
||||
} else {
|
||||
m_min.set_value(tools::mn<T_t>(a_x,m_min[0]),
|
||||
tools::mn<T_t>(a_y,m_min[1]),
|
||||
tools::mn<T_t>(a_z,m_min[2]));
|
||||
m_max.set_value(tools::mx<T_t>(a_x,m_max[0]),
|
||||
tools::mx<T_t>(a_y,m_max[1]),
|
||||
tools::mx<T_t>(a_z,m_max[2]));
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE : print is a Python keyword.
|
||||
void dump(std::ostream& a_out) {
|
||||
T_t dx,dy,dz;
|
||||
if(!get_size(dx,dy,dz)) {
|
||||
a_out << "box is empty." << std::endl;
|
||||
} else {
|
||||
a_out << " size " << dx << " " << dy << " " << dz << std::endl;
|
||||
}
|
||||
a_out << " min " << m_min[0] << " " << m_min[1] << " " << m_min[2] << std::endl;
|
||||
a_out << " max " << m_max[0] << " " << m_max[1] << " " << m_max[2] << std::endl;
|
||||
VEC3 c;
|
||||
center(c);
|
||||
a_out << " center " << c[0] << " " << c[1] << " " << c[2] << std::endl;
|
||||
}
|
||||
|
||||
protected:
|
||||
VEC3 m_min;
|
||||
VEC3 m_max;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_box3f
|
||||
#define tools_box3f
|
||||
|
||||
#include "box3"
|
||||
#include "vec3f"
|
||||
#include <cfloat> //FLT_MAX
|
||||
|
||||
namespace tools {
|
||||
|
||||
class box3f : public box3<vec3f> {
|
||||
typedef box3<vec3f> parent;
|
||||
static float num_max() {return FLT_MAX;}
|
||||
public:
|
||||
box3f():parent(){make_empty();}
|
||||
virtual ~box3f() {}
|
||||
public:
|
||||
box3f(const box3f& a_from):parent(a_from){}
|
||||
box3f& operator=(const box3f& a_from){
|
||||
parent::operator=(a_from);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
void make_empty(){
|
||||
m_min.set_value( num_max(), num_max(), num_max());
|
||||
m_max.set_value(-num_max(), -num_max(), -num_max());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_box_3f
|
||||
#define tools_box_3f
|
||||
|
||||
#include "../mnmx"
|
||||
|
||||
#include <cfloat> // FLT_MAX
|
||||
|
||||
namespace tools {
|
||||
|
||||
// optimization (used in exlib/sg/text_hershey) :
|
||||
|
||||
inline void box_3f_make_empty(float& a_mn_x,float& a_mn_y,float& a_mn_z,
|
||||
float& a_mx_x,float& a_mx_y,float& a_mx_z){
|
||||
a_mn_x = FLT_MAX;
|
||||
a_mn_y = FLT_MAX;
|
||||
a_mn_z = FLT_MAX;
|
||||
a_mx_x = -FLT_MAX;
|
||||
a_mx_y = -FLT_MAX;
|
||||
a_mx_z = -FLT_MAX;
|
||||
}
|
||||
inline void box_3f_extend_by(float& a_mn_x,float& a_mn_y,float& a_mn_z,
|
||||
float& a_mx_x,float& a_mx_y,float& a_mx_z,
|
||||
float a_x,float a_y,float a_z){
|
||||
if(a_mx_x<a_mn_x){ //is empty.
|
||||
a_mn_x = a_x;
|
||||
a_mn_y = a_y;
|
||||
a_mn_z = a_z;
|
||||
|
||||
a_mx_x = a_x;
|
||||
a_mx_y = a_y;
|
||||
a_mx_z = a_z;
|
||||
} else {
|
||||
a_mn_x = mn<float>(a_x,a_mn_x);
|
||||
a_mn_y = mn<float>(a_y,a_mn_y);
|
||||
a_mn_z = mn<float>(a_z,a_mn_z);
|
||||
|
||||
a_mx_x = mx<float>(a_x,a_mx_x);
|
||||
a_mx_y = mx<float>(a_y,a_mx_y);
|
||||
a_mx_z = mx<float>(a_z,a_mx_z);
|
||||
}
|
||||
}
|
||||
inline bool box_3f_is_empty(float a_mn_x,float a_mx_x) {
|
||||
return a_mx_x < a_mn_x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,191 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_geom3
|
||||
#define tools_geom3
|
||||
|
||||
#include "line"
|
||||
#include "plane"
|
||||
|
||||
namespace tools {
|
||||
|
||||
template <class T>
|
||||
class cubic {
|
||||
public:
|
||||
cubic(const vec3<T>& a_p0,const vec3<T>& a_v0,
|
||||
const vec3<T>& a_p1,const vec3<T>& a_v1) {
|
||||
// Construct a cubic given 2 points and their tangents.
|
||||
initialize(a_p0.x(),a_p0.y(),a_p0.z(),
|
||||
a_v0.x(),a_v0.y(),a_v0.z(),
|
||||
a_p1.x(),a_p1.y(),a_p1.z(),
|
||||
a_v1.x(),a_v1.y(),a_v1.z());
|
||||
}
|
||||
cubic(const T& a_p0_x,const T& a_p0_y,const T& a_p0_z,
|
||||
const T& a_v0_x,const T& a_v0_y,const T& a_v0_z,
|
||||
const T& a_p1_x,const T& a_p1_y,const T& a_p1_z,
|
||||
const T& a_v1_x,const T& a_v1_y,const T& a_v1_z){
|
||||
initialize(a_p0_x,a_p0_y,a_p0_z,
|
||||
a_v0_x,a_v0_y,a_v0_z,
|
||||
a_p1_x,a_p1_y,a_p1_z,
|
||||
a_v1_x,a_v1_y,a_v1_z);
|
||||
}
|
||||
|
||||
virtual ~cubic() {}
|
||||
public:
|
||||
cubic(const cubic& a_from)
|
||||
:m_a(a_from.m_a)
|
||||
,m_b(a_from.m_b)
|
||||
,m_c(a_from.m_c)
|
||||
,m_d(a_from.m_d)
|
||||
{}
|
||||
cubic& operator=(const cubic& a_from) {
|
||||
m_a = a_from.m_a;
|
||||
m_b = a_from.m_b;
|
||||
m_c = a_from.m_c;
|
||||
m_d = a_from.m_d;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
void get_point(unsigned int a_index,unsigned int a_num,vec3<T>& a_p){
|
||||
//a_index = 0 is a_p0
|
||||
//a_index = a_num-1 is a_p1
|
||||
T s = T(a_index)/T(a_num-1);
|
||||
T s2 = s*s;
|
||||
T s3 = s2*s;
|
||||
a_p = m_a*s3 + m_b*s2 + m_c*s + m_d;
|
||||
}
|
||||
void get_point(unsigned int a_index,unsigned int a_num,T& a_x,T& a_y,T& a_z){
|
||||
//a_index = 0 is a_p0
|
||||
//a_index = a_num-1 is a_p1
|
||||
T s = T(a_index)/T(a_num-1);
|
||||
T s2 = s*s;
|
||||
T s3 = s2*s;
|
||||
a_x = m_a.x()*s3 + m_b.x()*s2 + m_c.x()*s + m_d.x();
|
||||
a_y = m_a.y()*s3 + m_b.y()*s2 + m_c.y()*s + m_d.y();
|
||||
a_z = m_a.z()*s3 + m_b.z()*s2 + m_c.z()*s + m_d.z();
|
||||
}
|
||||
protected:
|
||||
void initialize(const T& a_p0_x,const T& a_p0_y,const T& a_p0_z,
|
||||
const T& a_v0_x,const T& a_v0_y,const T& a_v0_z,
|
||||
const T& a_p1_x,const T& a_p1_y,const T& a_p1_z,
|
||||
const T& a_v1_x,const T& a_v1_y,const T& a_v1_z){
|
||||
// Construct a cubic given 2 points and their tangents.
|
||||
|
||||
// f(s) = a s**3 + b s**2 + c s + d
|
||||
// f'(s) = 3 a s**2 + 2 b s + c
|
||||
|
||||
// f(0) = d = p0
|
||||
// f'(0) = c = v0
|
||||
|
||||
// f(1) = a + b + v0 + p0 = p1
|
||||
// f'(1) = 3 a + 2 b + v0 = v1
|
||||
|
||||
// f(1) = a + b = p1 - v0 - p0
|
||||
// f'(1) = 3 a + 2 b = v1 - v0
|
||||
|
||||
// b = 3(p1-v0-p0)-(v1-v0)
|
||||
// a = p1-v0-p0 - b = p1-v0-p0-3(p1-v0-p0)+(v1-v0)
|
||||
// a = -2p1 + v0 + 2p0 + v1
|
||||
|
||||
T a_x = -2*a_p1_x + a_v0_x + 2*a_p0_x + a_v1_x;
|
||||
T a_y = -2*a_p1_y + a_v0_y + 2*a_p0_y + a_v1_y;
|
||||
T a_z = -2*a_p1_z + a_v0_z + 2*a_p0_z + a_v1_z;
|
||||
m_a.set_value(a_x,a_y,a_z);
|
||||
|
||||
T b_x = 3*(a_p1_x - a_v0_x - a_p0_x) - (a_v1_x - a_v0_x);
|
||||
T b_y = 3*(a_p1_y - a_v0_y - a_p0_y) - (a_v1_y - a_v0_y);
|
||||
T b_z = 3*(a_p1_z - a_v0_z - a_p0_z) - (a_v1_z - a_v0_z);
|
||||
m_b.set_value(b_x,b_y,b_z);
|
||||
|
||||
m_c.set_value(a_v0_x,a_v0_y,a_v0_z);
|
||||
m_d.set_value(a_p0_x,a_p0_y,a_p0_z);
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
vec3<T> m_a;
|
||||
vec3<T> m_b;
|
||||
vec3<T> m_c;
|
||||
vec3<T> m_d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace tools {
|
||||
|
||||
// not tested yet.
|
||||
template <class T>
|
||||
class clip {
|
||||
public:
|
||||
clip():m_cur(0){}
|
||||
virtual ~clip() {}
|
||||
private:
|
||||
clip(const clip&):m_cur(0){}
|
||||
clip& operator=(const clip&){return *this;}
|
||||
public:
|
||||
void reset() {
|
||||
m_data[0].clear();
|
||||
m_data[1].clear();
|
||||
m_cur = 0;
|
||||
}
|
||||
|
||||
void add(const vec3<T>& a_point) {m_data[m_cur].push_back(a_point);}
|
||||
|
||||
void execute(const plane<T>& plane) {
|
||||
//Clip polygon against plane. This might change the number of
|
||||
//vertices in the polygon.
|
||||
|
||||
unsigned int n = m_data[m_cur].size();
|
||||
if (n == 0) return;
|
||||
|
||||
// create a loop :
|
||||
vec3<T> dummy = m_data[m_cur][0];
|
||||
m_data[m_cur].push_back(dummy);
|
||||
|
||||
const vec3<T>& planeN = plane.normal();
|
||||
|
||||
for(unsigned int i = 0; i < n; i++) {
|
||||
vec3<T> v0 = m_data[m_cur][i];
|
||||
vec3<T> v1 = m_data[m_cur][i+1];
|
||||
|
||||
T d0 = plane.distance(v0);
|
||||
T d1 = plane.distance(v1);
|
||||
|
||||
if (d0 >= 0.0f && d1 < 0.0f) { // exit plane
|
||||
vec3<T> dir = v1-v0;
|
||||
// we know that v0 != v1 since we got here
|
||||
dir.normalize();
|
||||
T dot = dir.dot(planeN);
|
||||
vec3<T> newvertex = v0 - dir * (d0/dot);
|
||||
out_point(newvertex);
|
||||
} else if (d0 < 0.0f && d1 >= 0.0f) { // enter plane
|
||||
vec3<T> dir = v1-v0;
|
||||
// we know that v0 != v1 since we got here
|
||||
dir.normalize();
|
||||
T dot = dir.dot(planeN);
|
||||
vec3<T> newvertex = v0 - dir * (d0/dot);
|
||||
out_point(newvertex);
|
||||
out_point(v1);
|
||||
} else if (d0 >= 0.0f && d1 >= 0.0f) { // in plane
|
||||
out_point(v1);
|
||||
}
|
||||
}
|
||||
m_data[m_cur].clear();
|
||||
m_cur ^= 1;
|
||||
}
|
||||
|
||||
const std::vector< vec3<T> >& result() const {return m_data[m_cur];}
|
||||
|
||||
protected:
|
||||
void out_point(const vec3<T>& a_p) {m_data[m_cur ^ 1].push_back(a_p);}
|
||||
|
||||
protected:
|
||||
std::vector< vec3<T> > m_data[2];
|
||||
unsigned int m_cur;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,135 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_line
|
||||
#define tools_line
|
||||
|
||||
#include "vec3"
|
||||
|
||||
namespace tools {
|
||||
|
||||
// Parametric description:
|
||||
// l(t) = pos + t * dir
|
||||
|
||||
template <class T>
|
||||
class line {
|
||||
public:
|
||||
line(){}
|
||||
line(const vec3<T>& a_p0,const vec3<T>& a_p1) {
|
||||
// Construct a line from two points lying on the line. If you
|
||||
// want to construct a line from a position and a direction, use
|
||||
// line(p, p + d).
|
||||
// line is directed from p0 to p1.
|
||||
m_pos = a_p0;
|
||||
//m_dir = a_p1-a_p0;
|
||||
m_dir = a_p0;
|
||||
m_dir.multiply(-1);
|
||||
m_dir.add(a_p1);
|
||||
m_dir.normalize();
|
||||
}
|
||||
line(const T& a_0_x,const T& a_0_y,const T& a_0_z,
|
||||
const T& a_1_x,const T& a_1_y,const T& a_1_z) {
|
||||
m_pos.set_value(a_0_x,a_0_y,a_0_z);
|
||||
m_dir.set_value(a_1_x-a_0_x,a_1_y-a_0_y,a_1_z-a_0_z);
|
||||
m_dir.normalize();
|
||||
}
|
||||
virtual ~line() {}
|
||||
public:
|
||||
line(const line& a_from)
|
||||
:m_pos(a_from.m_pos)
|
||||
,m_dir(a_from.m_dir)
|
||||
{}
|
||||
line& operator=(const line& a_from) {
|
||||
m_pos = a_from.m_pos;
|
||||
m_dir = a_from.m_dir;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
void set_value(const vec3<T>& a_p0,const vec3<T>& a_p1) {
|
||||
m_pos = a_p0;
|
||||
m_dir = a_p0;
|
||||
m_dir.multiply(-1);
|
||||
m_dir.add(a_p1);
|
||||
m_dir.normalize();
|
||||
}
|
||||
void set_value(const T& a_0_x,const T& a_0_y,const T& a_0_z,
|
||||
const T& a_1_x,const T& a_1_y,const T& a_1_z) {
|
||||
m_pos.set_value(a_0_x,a_0_y,a_0_z);
|
||||
m_dir.set_value(a_1_x-a_0_x,a_1_y-a_0_y,a_1_z-a_0_z);
|
||||
m_dir.normalize();
|
||||
}
|
||||
|
||||
const vec3<T>& position() const {return m_pos;}
|
||||
const vec3<T>& direction() const {return m_dir;}
|
||||
|
||||
/* not tested :
|
||||
vec3<T> closest_point(const vec3<T>& a_point) const {
|
||||
//from coin3d/SbLine.cpp.
|
||||
|
||||
//
|
||||
// a_out
|
||||
// m_pos x-----x-------> m_dir
|
||||
// \ |
|
||||
// \ |
|
||||
// \ |
|
||||
// \ |
|
||||
// \|
|
||||
// x a_point
|
||||
|
||||
return m_pos + m_dir * ((a_point - m_pos).dot(m_dir));
|
||||
}
|
||||
|
||||
|
||||
bool closest_points(const line<T>& a_line,
|
||||
vec3<T>& a_on_this,vec3<T>& a_on_line) const {
|
||||
//from coin3d/SbLine.cpp.
|
||||
|
||||
//WARNING : if ret false, a_on_this, a_on_line not set.
|
||||
|
||||
// Check if the lines are parallel.
|
||||
// FIXME: should probably use equals() here.
|
||||
if(a_line.m_dir == m_dir) return false;
|
||||
if(a_line.m_dir == T(-1)*m_dir) return false;
|
||||
|
||||
vec3<T> P0 = m_pos;
|
||||
vec3<T> P1 = a_line.m_pos;
|
||||
vec3<T> D0 = m_dir;
|
||||
vec3<T> D1 = a_line.m_dir;
|
||||
vec3<T> D0N = D0;
|
||||
|
||||
T c[3], d[3];
|
||||
|
||||
for(unsigned int i=0;i<3;i++) {
|
||||
d[i] =
|
||||
D1[i] - D0N[i]*(D0[0]*D1[0] + D0[1]*D1[1] + D0[2]*D1[2]);
|
||||
c[i] =
|
||||
P1[i] - P0[i] + D0N[i]*(D0[0]*P0[0] + D0[1]*P0[1] + D0[2]*P0[2]);
|
||||
}
|
||||
|
||||
T den = d[0]*d[0]+d[1]*d[1]+d[2]*d[2];
|
||||
if(den==T()) return false;
|
||||
|
||||
T t = -(c[0]*d[0]+c[1]*d[1]+c[2]*d[2]) / den;
|
||||
|
||||
a_on_line = a_line.m_pos + a_line.m_dir * t;
|
||||
a_on_this = closest_point(a_on_line);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool intersect(const line<T>& a_line,vec3<T>& a_out,const T& a_prec) const {
|
||||
vec3<T> p,q;
|
||||
if(!closest_points(a_line,p,q)) return false;
|
||||
if((q-p).length()>a_prec) return false;
|
||||
a_out = p;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
protected:
|
||||
vec3<T> m_pos;
|
||||
vec3<T> m_dir; //normalized.
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,538 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_mat
|
||||
#define tools_mat
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include "mem"
|
||||
#endif
|
||||
|
||||
#include "MATCOM"
|
||||
|
||||
//#include <cstring> //memcpy
|
||||
|
||||
//#define TOOLS_MAT_NEW
|
||||
namespace tools {
|
||||
|
||||
template <class T,unsigned int D>
|
||||
class mat {
|
||||
static const unsigned int _D2 = D*D;
|
||||
unsigned int dim2() const {return _D2;}
|
||||
#define TOOLS_MAT_CLASS mat
|
||||
TOOLS_MATCOM
|
||||
#undef TOOLS_MAT_CLASS
|
||||
private:
|
||||
#ifdef TOOLS_MEM
|
||||
static const std::string& s_class() {
|
||||
static const std::string s_v("tools::mat");
|
||||
return s_v;
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
mat() {
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_class().c_str());
|
||||
#endif
|
||||
#ifdef TOOLS_MAT_NEW
|
||||
m_vec = new T[D*D];
|
||||
#endif
|
||||
for(unsigned int i=0;i<_D2;i++) m_vec[i] = zero();
|
||||
}
|
||||
virtual ~mat() {
|
||||
#ifdef TOOLS_MAT_NEW
|
||||
delete [] m_vec;
|
||||
#endif
|
||||
#ifdef TOOLS_MEM
|
||||
mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
public:
|
||||
mat(const mat& a_from) {
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_class().c_str());
|
||||
#endif
|
||||
#ifdef TOOLS_MAT_NEW
|
||||
m_vec = new T[D*D];
|
||||
#endif
|
||||
_copy(a_from.m_vec);
|
||||
}
|
||||
mat& operator=(const mat& a_from){
|
||||
if(&a_from==this) return *this;
|
||||
_copy(a_from.m_vec);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
mat(const T a_v[]){
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_class().c_str());
|
||||
#endif
|
||||
#ifdef TOOLS_MAT_NEW
|
||||
m_vec = new T[D*D];
|
||||
#endif
|
||||
_copy(a_v);
|
||||
}
|
||||
public:
|
||||
unsigned int dimension() const {return D;}
|
||||
protected:
|
||||
#ifdef TOOLS_MAT_NEW
|
||||
T* m_vec;
|
||||
#else
|
||||
T m_vec[D*D];
|
||||
#endif
|
||||
|
||||
private:static void check_instantiation() {mat<float,2> dummy;}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class nmat {
|
||||
unsigned int dim2() const {return m_D2;}
|
||||
#define TOOLS_MAT_CLASS nmat
|
||||
TOOLS_MATCOM
|
||||
#undef TOOLS_MAT_CLASS
|
||||
private:
|
||||
#ifdef TOOLS_MEM
|
||||
static const std::string& s_class() {
|
||||
static const std::string s_v("tools::nmat");
|
||||
return s_v;
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
nmat(unsigned int a_D):m_D(a_D),m_D2(a_D*a_D),m_vec(0) {
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_class().c_str());
|
||||
#endif
|
||||
m_vec = new T[m_D2];
|
||||
for(unsigned int i=0;i<m_D2;i++) m_vec[i] = zero();
|
||||
}
|
||||
virtual ~nmat() {
|
||||
delete [] m_vec;
|
||||
#ifdef TOOLS_MEM
|
||||
mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
public:
|
||||
nmat(const nmat& a_from)
|
||||
:m_D(a_from.m_D),m_D2(a_from.m_D2),m_vec(0)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_class().c_str());
|
||||
#endif
|
||||
m_vec = new T[m_D2];
|
||||
_copy(a_from.m_vec);
|
||||
}
|
||||
nmat& operator=(const nmat& a_from){
|
||||
if(&a_from==this) return *this;
|
||||
if(a_from.m_D!=m_D) {
|
||||
m_D = a_from.m_D;
|
||||
m_D2 = a_from.m_D2;
|
||||
delete [] m_vec;
|
||||
m_vec = new T[m_D2];
|
||||
}
|
||||
_copy(a_from.m_vec);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
nmat(unsigned int a_D,const T a_v[])
|
||||
:m_D(a_D),m_D2(a_D*a_D),m_vec(0)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
mem::increment(s_class().c_str());
|
||||
#endif
|
||||
m_vec = new T[m_D2];
|
||||
_copy(a_v);
|
||||
}
|
||||
public:
|
||||
unsigned int dimension() const {return m_D;}
|
||||
protected:
|
||||
unsigned int m_D;
|
||||
unsigned int m_D2;
|
||||
T* m_vec;
|
||||
private:static void check_instantiation() {nmat<float> dummy(2);}
|
||||
};
|
||||
|
||||
template <class T,unsigned int D>
|
||||
inline nmat<T> copy(const mat<T,D>& a_from) {
|
||||
unsigned int D2 = D*D;
|
||||
nmat<T> v(D);
|
||||
for(unsigned int i=0;i<D2;i++) v[i] = a_from[i];
|
||||
return v;
|
||||
}
|
||||
|
||||
template <class MAT>
|
||||
inline void conjugate(MAT& a_m) {
|
||||
typedef typename MAT::elem_t T;
|
||||
T* pos = const_cast<T*>(a_m.data());
|
||||
unsigned int D2 = a_m.dimension()*a_m.dimension();
|
||||
for(unsigned int i=0;i<D2;i++,pos++) {
|
||||
*pos = _conj(*pos); //T = std::complex<>
|
||||
}
|
||||
}
|
||||
|
||||
template <class MAT>
|
||||
inline void dagger(MAT& a_m) {
|
||||
conjugate<MAT>(a_m);
|
||||
a_m.transpose();
|
||||
}
|
||||
|
||||
//for sf, mf :
|
||||
//template <class T,unsigned int D>
|
||||
//inline const T* get_data(const mat<T,D>& a_v) {return a_v.data();}
|
||||
|
||||
template <class MAT>
|
||||
inline MAT commutator(const MAT& a1,const MAT& a2) {
|
||||
return a1*a2-a2*a1;
|
||||
}
|
||||
|
||||
template <class MAT>
|
||||
inline MAT anticommutator(const MAT& a1,const MAT& a2) {
|
||||
return a1*a2+a2*a1;
|
||||
}
|
||||
|
||||
template <class MAT>
|
||||
inline void commutator(const MAT& a1,const MAT& a2,MAT& a_tmp,MAT& a_res) {
|
||||
a_res = a1;
|
||||
a_res *= a2;
|
||||
a_tmp = a2;
|
||||
a_tmp *= a1;
|
||||
a_res -= a_tmp;
|
||||
}
|
||||
|
||||
template <class MAT,class T>
|
||||
inline void commutator(const MAT& a1,const MAT& a2,MAT& a_tmp,T a_vtmp[],MAT& a_res) {
|
||||
a_res = a1;
|
||||
a_res.mul_mtx(a2,a_vtmp);
|
||||
a_tmp = a2;
|
||||
a_tmp.mul_mtx(a1,a_vtmp);
|
||||
a_res -= a_tmp;
|
||||
}
|
||||
|
||||
template <class MAT>
|
||||
inline void anticommutator(const MAT& a1,const MAT& a2,MAT& a_tmp,MAT& a_res) {
|
||||
a_res = a1;
|
||||
a_res *= a2;
|
||||
a_tmp = a2;
|
||||
a_tmp *= a1;
|
||||
a_res += a_tmp;
|
||||
}
|
||||
|
||||
template <class MAT,class T>
|
||||
inline void anticommutator(const MAT& a1,const MAT& a2,MAT& a_tmp,T a_vtmp[],MAT& a_res) {
|
||||
a_res = a1;
|
||||
a_res.mul_mtx(a2,a_vtmp);
|
||||
a_tmp = a2;
|
||||
a_tmp.mul_mtx(a1,a_vtmp);
|
||||
a_res += a_tmp;
|
||||
}
|
||||
|
||||
template <class T,unsigned int D>
|
||||
inline bool commutator_equal(const mat<T,D>& a_1,const mat<T,D>& a_2,const mat<T,D>& a_c,const T& a_prec) {
|
||||
unsigned int order = D;
|
||||
const T* p1 = a_1.data();
|
||||
const T* p2 = a_2.data();
|
||||
const T* pc = a_c.data();
|
||||
for(unsigned int r=0;r<order;r++) {
|
||||
for(unsigned int c=0;c<order;c++) {
|
||||
T _12 = T();
|
||||
{for(unsigned int i=0;i<order;i++) {
|
||||
_12 += (*(p1+r+i*order)) * (*(p2+i+c*order));
|
||||
}}
|
||||
T _21 = T();
|
||||
{for(unsigned int i=0;i<order;i++) {
|
||||
_21 += (*(p2+r+i*order)) * (*(p1+i+c*order));
|
||||
}}
|
||||
T diff = (_12-_21) - *(pc+r+c*order);
|
||||
if(diff<T()) diff *= T(-1);
|
||||
if(diff>=a_prec) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T,unsigned int D>
|
||||
inline bool anticommutator_equal(const mat<T,D>& a_1,const mat<T,D>& a_2,const mat<T,D>& a_c,const T& a_prec) {
|
||||
unsigned int order = D;
|
||||
const T* p1 = a_1.data();
|
||||
const T* p2 = a_2.data();
|
||||
const T* pc = a_c.data();
|
||||
for(unsigned int r=0;r<order;r++) {
|
||||
for(unsigned int c=0;c<order;c++) {
|
||||
T _12 = T();
|
||||
{for(unsigned int i=0;i<order;i++) {
|
||||
_12 += (*(p1+r+i*order)) * (*(p2+i+c*order));
|
||||
}}
|
||||
T _21 = T();
|
||||
{for(unsigned int i=0;i<order;i++) {
|
||||
_21 += (*(p2+r+i*order)) * (*(p1+i+c*order));
|
||||
}}
|
||||
T diff = (_12+_21) - *(pc+r+c*order);
|
||||
if(diff<T()) diff *= T(-1);
|
||||
if(diff>=a_prec) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T,unsigned int D>
|
||||
inline mat<T,D> operator-(const mat<T,D>& a1,const mat<T,D>& a2) {
|
||||
mat<T,D> res(a1);
|
||||
res -= a2;
|
||||
return res;
|
||||
}
|
||||
template <class T,unsigned int D>
|
||||
inline mat<T,D> operator+(const mat<T,D>& a1,const mat<T,D>& a2) {
|
||||
mat<T,D> res(a1);
|
||||
res += a2;
|
||||
return res;
|
||||
}
|
||||
template <class T,unsigned int D>
|
||||
inline mat<T,D> operator*(const mat<T,D>& a1,const mat<T,D>& a2) {
|
||||
mat<T,D> res(a1);
|
||||
res *= a2;
|
||||
return res;
|
||||
}
|
||||
template <class T,unsigned int D>
|
||||
inline mat<T,D> operator*(const T& a_fac,const mat<T,D>& a_m) {
|
||||
mat<T,D> res(a_m);
|
||||
res *= a_fac;
|
||||
return res;
|
||||
}
|
||||
/*
|
||||
template <class T,unsigned int D>
|
||||
inline mat<T,D> operator*(const mat<T,D>& a_m,const T& a_fac) {
|
||||
mat<T,D> res(a_m);
|
||||
res *= a_fac;
|
||||
return res;
|
||||
}
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
inline nmat<T> operator-(const nmat<T>& a1,const nmat<T>& a2) {
|
||||
nmat<T> res(a1);
|
||||
res -= a2;
|
||||
return res;
|
||||
}
|
||||
template <class T>
|
||||
inline nmat<T> operator+(const nmat<T>& a1,const nmat<T>& a2) {
|
||||
nmat<T> res(a1);
|
||||
res += a2;
|
||||
return res;
|
||||
}
|
||||
template <class T>
|
||||
inline nmat<T> operator*(const nmat<T>& a1,const nmat<T>& a2) {
|
||||
nmat<T> res(a1);
|
||||
res *= a2;
|
||||
return res;
|
||||
}
|
||||
template <class T>
|
||||
inline nmat<T> operator*(const T& a_fac,const nmat<T>& a_m) {
|
||||
nmat<T> res(a_m);
|
||||
res *= a_fac;
|
||||
return res;
|
||||
}
|
||||
/*
|
||||
template <class T>
|
||||
inline nmat<T> operator*(const nmat<T>& a_m,const T& a_fac) {
|
||||
nmat<T> res(a_m);
|
||||
res *= a_fac;
|
||||
return res;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
namespace tools {
|
||||
|
||||
////////////////////////////////////////////////
|
||||
/// specific D=2 ///////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
template <class MAT>
|
||||
inline void matrix_set(MAT& a_m
|
||||
,const typename MAT::elem_t& a_00,const typename MAT::elem_t& a_01
|
||||
,const typename MAT::elem_t& a_10,const typename MAT::elem_t& a_11
|
||||
){
|
||||
//a_<R><C>
|
||||
//vec[R + C * 2];
|
||||
typename MAT::elem_t* vec = const_cast<typename MAT::elem_t*>(a_m.data());
|
||||
vec[0] = a_00;vec[2] = a_01;
|
||||
vec[1] = a_10;vec[3] = a_11;
|
||||
}
|
||||
|
||||
template <class MAT>
|
||||
inline void set_epsilon(MAT& a_m) {
|
||||
matrix_set<MAT>(a_m, 0, 1,
|
||||
-1, 0);
|
||||
}
|
||||
|
||||
// Pauli matrices :
|
||||
// P1 P2 P3
|
||||
// 0 1 0 -i 1 0
|
||||
// 1 0 i 0 0 -1
|
||||
template <class MAT>
|
||||
inline void set_P1(MAT& a_m) {
|
||||
matrix_set<MAT>(a_m, 0, 1,
|
||||
1, 0);
|
||||
}
|
||||
|
||||
template <class MAT>
|
||||
inline void set_P2(MAT& a_m) {
|
||||
typedef typename MAT::elem_t T;
|
||||
//T i;set_i(i); //with inlib::symbol
|
||||
T i(0,1);
|
||||
T _i = T(-1)*i;
|
||||
matrix_set<MAT>(a_m, 0, _i,
|
||||
i, 0);
|
||||
}
|
||||
template <class MAT>
|
||||
inline void set_P3(MAT& a_m) {
|
||||
matrix_set<MAT>(a_m, 1, 0,
|
||||
0,-1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
/// specific D=3 ///////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
template <class MAT>
|
||||
inline void matrix_set(MAT& a_m
|
||||
,const typename MAT::elem_t& a_00,const typename MAT::elem_t& a_01,const typename MAT::elem_t& a_02 //1 row
|
||||
,const typename MAT::elem_t& a_10,const typename MAT::elem_t& a_11,const typename MAT::elem_t& a_12 //2 row
|
||||
,const typename MAT::elem_t& a_20,const typename MAT::elem_t& a_21,const typename MAT::elem_t& a_22 //3 row
|
||||
){
|
||||
//a_<R><C>
|
||||
//vec[R + C * 3];
|
||||
typename MAT::elem_t* vec = const_cast<typename MAT::elem_t*>(a_m.data());
|
||||
vec[0] = a_00;vec[3] = a_01;vec[6] = a_02;
|
||||
vec[1] = a_10;vec[4] = a_11;vec[7] = a_12;
|
||||
vec[2] = a_20;vec[5] = a_21;vec[8] = a_22;
|
||||
}
|
||||
|
||||
// Generators of rotation group :
|
||||
// Rk(i,j) = epsilon(k,i,j) i,j,k=1,2,3
|
||||
template <class MAT>
|
||||
inline void set_R1(MAT& a_m) {
|
||||
matrix_set<MAT>(a_m, 0, 0, 0,
|
||||
0, 0, 1,
|
||||
0,-1, 0);
|
||||
}
|
||||
template <class MAT>
|
||||
inline void set_R2(MAT& a_m) {
|
||||
matrix_set<MAT>(a_m, 0, 0,-1,
|
||||
0, 0, 0,
|
||||
1, 0, 0);
|
||||
}
|
||||
template <class MAT>
|
||||
inline void set_R3(MAT& a_m) {
|
||||
matrix_set<MAT>(a_m, 0, 1, 0,
|
||||
-1, 0, 0,
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
/// specific D=4 ///////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
template <class MAT>
|
||||
inline void matrix_set(MAT& a_m
|
||||
,const typename MAT::elem_t& a_00,const typename MAT::elem_t& a_01,const typename MAT::elem_t& a_02,const typename MAT::elem_t& a_03 //1 row
|
||||
,const typename MAT::elem_t& a_10,const typename MAT::elem_t& a_11,const typename MAT::elem_t& a_12,const typename MAT::elem_t& a_13 //2 row
|
||||
,const typename MAT::elem_t& a_20,const typename MAT::elem_t& a_21,const typename MAT::elem_t& a_22,const typename MAT::elem_t& a_23 //3 row
|
||||
,const typename MAT::elem_t& a_30,const typename MAT::elem_t& a_31,const typename MAT::elem_t& a_32,const typename MAT::elem_t& a_33 //4 row
|
||||
){
|
||||
//a_<R><C>
|
||||
//vec[R + C * 4];
|
||||
typename MAT::elem_t* vec = const_cast<typename MAT::elem_t*>(a_m.data());
|
||||
vec[0] = a_00;vec[4] = a_01;vec[ 8] = a_02;vec[12] = a_03;
|
||||
vec[1] = a_10;vec[5] = a_11;vec[ 9] = a_12;vec[13] = a_13;
|
||||
vec[2] = a_20;vec[6] = a_21;vec[10] = a_22;vec[14] = a_23;
|
||||
vec[3] = a_30;vec[7] = a_31;vec[11] = a_32;vec[15] = a_33;
|
||||
}
|
||||
|
||||
template <class MAT,class RANDOM>
|
||||
inline void set_random_antisym(MAT& a_m,RANDOM& a_rd) {
|
||||
typedef typename MAT::elem_t T;
|
||||
T v01 = a_rd.shoot();
|
||||
T v02 = a_rd.shoot();
|
||||
T v03 = a_rd.shoot();
|
||||
T v12 = a_rd.shoot();
|
||||
T v13 = a_rd.shoot();
|
||||
T v23 = a_rd.shoot();
|
||||
matrix_set(a_m,
|
||||
0, v01, v02, v03,
|
||||
-v01, 0, v12, v13,
|
||||
-v02,-v12, 0, v23,
|
||||
-v03,-v13,-v23, 0);
|
||||
}
|
||||
|
||||
template <class MAT>
|
||||
inline void set_eta(MAT& a_m) {
|
||||
a_m.set_zero();
|
||||
a_m.set_value(0,0, 1);
|
||||
a_m.set_value(1,1,-1);
|
||||
a_m.set_value(2,2,-1);
|
||||
a_m.set_value(3,3,-1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
/// specific D=6 ///////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
template <class T>
|
||||
inline void set_matrix(mat<T,6>& a_m
|
||||
,const T& a_00,const T& a_01,const T& a_02,const T& a_03,const T& a_04,const T& a_05 //1 row
|
||||
,const T& a_10,const T& a_11,const T& a_12,const T& a_13,const T& a_14,const T& a_15 //2 row
|
||||
,const T& a_20,const T& a_21,const T& a_22,const T& a_23,const T& a_24,const T& a_25 //3 row
|
||||
,const T& a_30,const T& a_31,const T& a_32,const T& a_33,const T& a_34,const T& a_35 //4 row
|
||||
,const T& a_40,const T& a_41,const T& a_42,const T& a_43,const T& a_44,const T& a_45 //5 row
|
||||
,const T& a_50,const T& a_51,const T& a_52,const T& a_53,const T& a_54,const T& a_55 //6 row
|
||||
){
|
||||
//a_<R><C>
|
||||
//vec[R + C * 6];
|
||||
T* vec = const_cast<T*>(a_m.data());
|
||||
vec[0] = a_00;vec[6] = a_01;vec[12] = a_02;vec[18] = a_03;vec[24] = a_04;vec[30] = a_05;
|
||||
vec[1] = a_10;vec[7] = a_11;vec[13] = a_12;vec[19] = a_13;vec[25] = a_14;vec[31] = a_15;
|
||||
vec[2] = a_20;vec[8] = a_21;vec[14] = a_22;vec[20] = a_23;vec[26] = a_24;vec[32] = a_25;
|
||||
vec[3] = a_30;vec[9] = a_31;vec[15] = a_32;vec[21] = a_33;vec[27] = a_34;vec[33] = a_35;
|
||||
vec[4] = a_40;vec[10] = a_41;vec[16] = a_42;vec[22] = a_43;vec[28] = a_44;vec[34] = a_45;
|
||||
vec[5] = a_50;vec[11] = a_51;vec[17] = a_52;vec[23] = a_53;vec[29] = a_54;vec[35] = a_55;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
#include <ostream>
|
||||
|
||||
namespace tools {
|
||||
|
||||
//NOTE : print is a Python keyword.
|
||||
template <class MAT>
|
||||
inline void dump(std::ostream& a_out,const std::string& aCMT,const MAT& a_matrix) {
|
||||
if(aCMT.size()) a_out << aCMT << std::endl;
|
||||
unsigned int D = a_matrix.dimension();
|
||||
for(unsigned int r=0;r<D;r++) {
|
||||
for(unsigned int c=0;c<D;c++) {
|
||||
a_out << " " << a_matrix.value(r,c);
|
||||
}
|
||||
a_out << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template <class MAT>
|
||||
inline bool check_invert(const MAT& a_matrix,std::ostream& a_out) {
|
||||
MAT I;I.set_identity();
|
||||
MAT tmp;
|
||||
if(!a_matrix.invert(tmp)) return false;
|
||||
tmp.mul_mtx(a_matrix);
|
||||
if(!tmp.equal(I)) {
|
||||
dump(a_out,"problem with inv of :",a_matrix);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,476 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef tools_mat4
|
||||
#define tools_mat4
|
||||
|
||||
#include "mat"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace tools {
|
||||
|
||||
template <class T>
|
||||
class mat4 : public mat<T,4> {
|
||||
typedef mat<T,4> parent;
|
||||
typedef mat<T,4> pr;
|
||||
public:
|
||||
mat4():parent() {}
|
||||
mat4(const mat<T,4>& a_from):parent(a_from){}
|
||||
virtual ~mat4() {}
|
||||
public:
|
||||
mat4(const mat4& a_from):parent(a_from){}
|
||||
mat4& operator=(const mat4& a_from){
|
||||
parent::operator=(a_from);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
mat4(const T& a_00,const T& a_01,const T& a_02,const T& a_03, //first row
|
||||
const T& a_10,const T& a_11,const T& a_12,const T& a_13, //second row
|
||||
const T& a_20,const T& a_21,const T& a_22,const T& a_23, //third row
|
||||
const T& a_30,const T& a_31,const T& a_32,const T& a_33) //fourth row
|
||||
{
|
||||
set_matrix(a_00,a_01,a_02,a_03,
|
||||
a_10,a_11,a_12,a_13,
|
||||
a_20,a_21,a_22,a_23,
|
||||
a_30,a_31,a_32,a_33);
|
||||
}
|
||||
public:
|
||||
void set_matrix(const mat4<T>& a_m){
|
||||
parent::set_matrix(a_m);
|
||||
}
|
||||
void set_matrix(
|
||||
const T& a_00,const T& a_01,const T& a_02,const T& a_03, //1 row
|
||||
const T& a_10,const T& a_11,const T& a_12,const T& a_13, //2 row
|
||||
const T& a_20,const T& a_21,const T& a_22,const T& a_23, //3 row
|
||||
const T& a_30,const T& a_31,const T& a_32,const T& a_33) //4 row
|
||||
{
|
||||
//a_<R><C>
|
||||
//pr::m_vec[R + C * 4];
|
||||
pr::m_vec[0] = a_00;pr::m_vec[4] = a_01;pr::m_vec[ 8] = a_02;pr::m_vec[12] = a_03;
|
||||
pr::m_vec[1] = a_10;pr::m_vec[5] = a_11;pr::m_vec[ 9] = a_12;pr::m_vec[13] = a_13;
|
||||
pr::m_vec[2] = a_20;pr::m_vec[6] = a_21;pr::m_vec[10] = a_22;pr::m_vec[14] = a_23;
|
||||
pr::m_vec[3] = a_30;pr::m_vec[7] = a_31;pr::m_vec[11] = a_32;pr::m_vec[15] = a_33;
|
||||
}
|
||||
|
||||
void set_scale(const T& a_s) {
|
||||
_set_scale(a_s,a_s,a_s,pr::m_vec);
|
||||
}
|
||||
void set_scale(const T& a_1,const T& a_2,const T& a_3) {
|
||||
_set_scale(a_1,a_2,a_3,pr::m_vec);
|
||||
}
|
||||
void set_translate(const T& a_x,const T& a_y,const T& a_z) {
|
||||
_set_translate(a_x,a_y,a_z,pr::m_vec);
|
||||
}
|
||||
void set_rotate(const T& a_x,const T& a_y,const T& a_z,const T& a_angle) {
|
||||
_set_rotate(a_x,a_y,a_z,a_angle,pr::m_vec);
|
||||
}
|
||||
void set_ortho(const T& a_l,const T& a_r, //left,right
|
||||
const T& a_b,const T& a_t, //bottom,top
|
||||
const T& a_n,const T& a_f) { //znear,zfar
|
||||
// from man glOrtho.
|
||||
T tx = -(a_r+a_l)/(a_r-a_l);
|
||||
T ty = -(a_t+a_b)/(a_t-a_b);
|
||||
T tz = -(a_f+a_n)/(a_f-a_n);
|
||||
|
||||
T a_00,a_01,a_02,a_03;
|
||||
T a_10,a_11,a_12,a_13;
|
||||
T a_20,a_21,a_22,a_23;
|
||||
T a_30,a_31,a_32,a_33;
|
||||
a_00 = 2/(a_r-a_l);a_01 = 0;a_02 = 0;a_03 = tx;
|
||||
a_10 = 0;a_11 = 2/(a_t-a_b);a_12 = 0;a_13 = ty;
|
||||
a_20 = 0;a_21 = 0;a_22 = -2/(a_f-a_n);a_23 = tz;
|
||||
a_30 = 0;a_31 = 0;a_32 = 0;a_33 = 1;
|
||||
set_matrix(a_00,a_01,a_02,a_03, //1 row
|
||||
a_10,a_11,a_12,a_13, //2 row
|
||||
a_20,a_21,a_22,a_23, //3 row
|
||||
a_30,a_31,a_32,a_33); //4 row
|
||||
|
||||
//NOTE : Z(x,y, z,1) = -2z/(f-n)+tz = [-2z-f-n]/(f-n)
|
||||
// W(x,y, z,1) = 1 -> Z/W = Z
|
||||
// Z(x,y,-n,1) = -1
|
||||
// Z(x,y,-f,1) = 1
|
||||
|
||||
// Z(x,y,-(f+n)/2,1) = 0
|
||||
|
||||
// X(x,0, z,1) = 2x/(r-l)+tx = [2x-r-l]/(r-l)
|
||||
// X(r,0, z,1) = 1
|
||||
|
||||
// the view direction is then (0,0,1) in the final projection.
|
||||
}
|
||||
void set_frustum(const T& a_l,const T& a_r, //left,right
|
||||
const T& a_b,const T& a_t, //bottom,top
|
||||
const T& a_n,const T& a_f) { //znear,zfar
|
||||
// from man glFrustum.
|
||||
T A = (a_r+a_l)/(a_r-a_l);
|
||||
T B = (a_t+a_b)/(a_t-a_b);
|
||||
T C = -(a_f+a_n)/(a_f-a_n);
|
||||
T D = -(2*a_f*a_n)/(a_f-a_n);
|
||||
|
||||
T a_00,a_01,a_02,a_03;
|
||||
T a_10,a_11,a_12,a_13;
|
||||
T a_20,a_21,a_22,a_23;
|
||||
T a_30,a_31,a_32,a_33;
|
||||
a_00 = (2*a_n)/(a_r-a_l);a_01 = 0;a_02 = A;a_03 = 0;
|
||||
a_10 = 0;a_11 = (2*a_n)/(a_t-a_b);a_12 = B;a_13 = 0;
|
||||
a_20 = 0;a_21 = 0;a_22 = C;a_23 = D;
|
||||
a_30 = 0;a_31 = 0;a_32 = -1;a_33 = 0;
|
||||
set_matrix(a_00,a_01,a_02,a_03, //1 row
|
||||
a_10,a_11,a_12,a_13, //2 row
|
||||
a_20,a_21,a_22,a_23, //3 row
|
||||
a_30,a_31,a_32,a_33); //4 row
|
||||
|
||||
//NOTE : Z(x,y, z,1) = C*z+D = -[(f+n)*z+2*f*n]/(f-n)
|
||||
|
||||
// Z(x,y,-n,1) = -[-fn-nn+2fn]/(f-n) = -[fn-nn]/(f-n) = -n
|
||||
// W(x,y,-n,1) = n
|
||||
// -> Z/W(x,y,-n,1) = -1
|
||||
|
||||
// Z(x,y,-2fn/(f+n),1) = 0
|
||||
// -> Z/W = 0
|
||||
|
||||
// Z(x,y,-f,1) = -[-ff-fn+2fn]/(f-n) = -[fn-ff]/(f-n) = f
|
||||
// W(x,y,-f,1) = f
|
||||
// -> Z/W(x,y,-f,1) = 1
|
||||
|
||||
// X(x,0, z,1) = 2nx/(r-l)+z(r+l)/(r-l) = [2nx+zr+zl]/(r-l)
|
||||
// X(r,0,-n,1) = [nr-nl]/(r-l) = n
|
||||
// W(r,0,-n,1) = n
|
||||
// -> X/W(r,0,-n,1) = 1
|
||||
|
||||
// X(l,0,-n,1) = (2nl-n(r+l))/(r-l) = -n
|
||||
// W(l,0,-n,1) = n
|
||||
// -> X/W(l,0,-n,1) = -1
|
||||
|
||||
// lrbt corners are in plane z=-1 at xy=+/-1.
|
||||
|
||||
// eye ?
|
||||
// eye before ? (0,0,z,1) -> (zA,zB,zC+D,-z) /W -> (-A,-B,-(C+D/z),1)
|
||||
// z=0 -> (0,0,D=-2fn(f-n),0)
|
||||
|
||||
}
|
||||
|
||||
void get_translate(T& a_x,T& a_y,T& a_z) const {
|
||||
a_x = pr::m_vec[12];
|
||||
a_y = pr::m_vec[13];
|
||||
a_z = pr::m_vec[14];
|
||||
}
|
||||
public:
|
||||
void mul_4(T& a_x,T& a_y,T& a_z,T& a_p) const {
|
||||
// a_[x,y,z,p] = this * a_[x,y,z,p]
|
||||
//pr::m_vec[R + C * 4];
|
||||
//pr::m_vec[0]= 00;pr::m_vec[4] = 01;pr::m_vec[ 8] = 02;pr::m_vec[12] = 03;
|
||||
//pr::m_vec[1]= 10;pr::m_vec[5] = 11;pr::m_vec[ 9] = 12;pr::m_vec[13] = 13;
|
||||
//pr::m_vec[2]= 20;pr::m_vec[6] = 21;pr::m_vec[10] = 22;pr::m_vec[14] = 23;
|
||||
//pr::m_vec[3]= 30;pr::m_vec[7] = 31;pr::m_vec[11] = 32;pr::m_vec[15] = 33;
|
||||
T x= pr::m_vec[0]*a_x+pr::m_vec[4]*a_y+pr::m_vec[ 8]*a_z+pr::m_vec[12]*a_p;
|
||||
T y= pr::m_vec[1]*a_x+pr::m_vec[5]*a_y+pr::m_vec[ 9]*a_z+pr::m_vec[13]*a_p;
|
||||
T z= pr::m_vec[2]*a_x+pr::m_vec[6]*a_y+pr::m_vec[10]*a_z+pr::m_vec[14]*a_p;
|
||||
T p= pr::m_vec[3]*a_x+pr::m_vec[7]*a_y+pr::m_vec[11]*a_z+pr::m_vec[15]*a_p;
|
||||
a_x = x;
|
||||
a_y = y;
|
||||
a_z = z;
|
||||
a_p = p;
|
||||
}
|
||||
void mul_3(T& a_x,T& a_y,T& a_z) const {
|
||||
// a_[x,y,z] = this * a_[x,y,z]
|
||||
//pr::m_vec[R + C * 4];
|
||||
//pr::m_vec[0]= 00;pr::m_vec[4] = 01;pr::m_vec[ 8] = 02;pr::m_vec[12] = 03;
|
||||
//pr::m_vec[1]= 10;pr::m_vec[5] = 11;pr::m_vec[ 9] = 12;pr::m_vec[13] = 13;
|
||||
//pr::m_vec[2]= 20;pr::m_vec[6] = 21;pr::m_vec[10] = 22;pr::m_vec[14] = 23;
|
||||
//pr::m_vec[3]= 30;pr::m_vec[7] = 31;pr::m_vec[11] = 32;pr::m_vec[15] = 33;
|
||||
T x = pr::m_vec[0]*a_x+pr::m_vec[4]*a_y+pr::m_vec[ 8]*a_z+pr::m_vec[12];
|
||||
T y = pr::m_vec[1]*a_x+pr::m_vec[5]*a_y+pr::m_vec[ 9]*a_z+pr::m_vec[13];
|
||||
T z = pr::m_vec[2]*a_x+pr::m_vec[6]*a_y+pr::m_vec[10]*a_z+pr::m_vec[14];
|
||||
a_x = x;
|
||||
a_y = y;
|
||||
a_z = z;
|
||||
}
|
||||
void mul_2(T& a_x,T& a_y) const {
|
||||
// a_[x,y] = this * a_[x,y]
|
||||
//pr::m_vec[R + C * 4];
|
||||
//pr::m_vec[0]= 00;pr::m_vec[4] = 01;pr::m_vec[ 8] = 02;pr::m_vec[12] = 03;
|
||||
//pr::m_vec[1]= 10;pr::m_vec[5] = 11;pr::m_vec[ 9] = 12;pr::m_vec[13] = 13;
|
||||
//pr::m_vec[2]= 20;pr::m_vec[6] = 21;pr::m_vec[10] = 22;pr::m_vec[14] = 23;
|
||||
//pr::m_vec[3]= 30;pr::m_vec[7] = 31;pr::m_vec[11] = 32;pr::m_vec[15] = 33;
|
||||
T x = pr::m_vec[0]*a_x+pr::m_vec[4]*a_y+pr::m_vec[12];
|
||||
T y = pr::m_vec[1]*a_x+pr::m_vec[5]*a_y+pr::m_vec[13];
|
||||
a_x = x;
|
||||
a_y = y;
|
||||
}
|
||||
|
||||
void mul_dir_3(T& a_x,T& a_y,T& a_z) const {
|
||||
// used to multiply normals.
|
||||
// a_[x,y,z] = rot_part(this) * a_[x,y,z]
|
||||
|
||||
T x = pr::m_vec[0]*a_x+pr::m_vec[4]*a_y+pr::m_vec[ 8]*a_z;
|
||||
T y = pr::m_vec[1]*a_x+pr::m_vec[5]*a_y+pr::m_vec[ 9]*a_z;
|
||||
T z = pr::m_vec[2]*a_x+pr::m_vec[6]*a_y+pr::m_vec[10]*a_z;
|
||||
a_x = x;
|
||||
a_y = y;
|
||||
a_z = z;
|
||||
}
|
||||
|
||||
template <class VEC>
|
||||
void mul_dir_3(VEC& a_dir) const {
|
||||
mul_dir_3(a_dir[0],a_dir[1],a_dir[2]);
|
||||
}
|
||||
|
||||
void mul_scale(const T& a_sx,const T& a_sy,const T& a_sz) {
|
||||
// this = this * mat4_scale(a_s[x,y,z]
|
||||
//pr::m_vec[R + C * 4];
|
||||
//pr::m_vec[0]= 00;pr::m_vec[4] = 01;pr::m_vec[ 8] = 02;pr::m_vec[12] = 03;
|
||||
//pr::m_vec[1]= 10;pr::m_vec[5] = 11;pr::m_vec[ 9] = 12;pr::m_vec[13] = 13;
|
||||
//pr::m_vec[2]= 20;pr::m_vec[6] = 21;pr::m_vec[10] = 22;pr::m_vec[14] = 23;
|
||||
//pr::m_vec[3]= 30;pr::m_vec[7] = 31;pr::m_vec[11] = 32;pr::m_vec[15] = 33;
|
||||
pr::m_vec[0] *= a_sx;
|
||||
pr::m_vec[1] *= a_sx;
|
||||
pr::m_vec[2] *= a_sx;
|
||||
pr::m_vec[3] *= a_sx;
|
||||
|
||||
pr::m_vec[4] *= a_sy;
|
||||
pr::m_vec[5] *= a_sy;
|
||||
pr::m_vec[6] *= a_sy;
|
||||
pr::m_vec[7] *= a_sy;
|
||||
|
||||
pr::m_vec[ 8] *= a_sz;
|
||||
pr::m_vec[ 9] *= a_sz;
|
||||
pr::m_vec[10] *= a_sz;
|
||||
pr::m_vec[11] *= a_sz;
|
||||
}
|
||||
void mul_scale(const T& a_s) {
|
||||
pr::m_vec[0] *= a_s;
|
||||
pr::m_vec[1] *= a_s;
|
||||
pr::m_vec[2] *= a_s;
|
||||
pr::m_vec[3] *= a_s;
|
||||
|
||||
pr::m_vec[4] *= a_s;
|
||||
pr::m_vec[5] *= a_s;
|
||||
pr::m_vec[6] *= a_s;
|
||||
pr::m_vec[7] *= a_s;
|
||||
|
||||
pr::m_vec[ 8] *= a_s;
|
||||
pr::m_vec[ 9] *= a_s;
|
||||
pr::m_vec[10] *= a_s;
|
||||
pr::m_vec[11] *= a_s;
|
||||
}
|
||||
void mul_translate(const T& a_x,const T& a_y,const T& a_z) {
|
||||
pr::m_vec[12] = pr::m_vec[0]*a_x+pr::m_vec[4]*a_y+pr::m_vec[ 8]*a_z+pr::m_vec[12];
|
||||
pr::m_vec[13] = pr::m_vec[1]*a_x+pr::m_vec[5]*a_y+pr::m_vec[ 9]*a_z+pr::m_vec[13];
|
||||
pr::m_vec[14] = pr::m_vec[2]*a_x+pr::m_vec[6]*a_y+pr::m_vec[10]*a_z+pr::m_vec[14];
|
||||
pr::m_vec[15] = pr::m_vec[3]*a_x+pr::m_vec[7]*a_y+pr::m_vec[11]*a_z+pr::m_vec[15];
|
||||
}
|
||||
|
||||
void mul_rotate(const T& a_x,const T& a_y,const T& a_z,const T& a_angle) {
|
||||
T rot[16];
|
||||
_set_rotate(a_x,a_y,a_z,a_angle,rot);
|
||||
parent::_mul_mtx(rot);
|
||||
}
|
||||
|
||||
void left_mul_rotate(const T& a_x,const T& a_y,const T& a_z,
|
||||
const T& a_angle) {
|
||||
T _m[16];
|
||||
_set_rotate(a_x,a_y,a_z,a_angle,_m);
|
||||
parent::_left_mul_mtx(_m);
|
||||
}
|
||||
|
||||
void left_mul_scale(const T& a_x,const T& a_y,const T& a_z) {
|
||||
T _m[16];
|
||||
_set_scale(a_x,a_y,a_z,_m);
|
||||
parent::_left_mul_mtx(_m);
|
||||
}
|
||||
|
||||
void left_mul_translate(const T& a_x,const T& a_y,const T& a_z) {
|
||||
T _m[16];
|
||||
_set_translate(a_x,a_y,a_z,_m);
|
||||
parent::_left_mul_mtx(_m);
|
||||
}
|
||||
|
||||
void v00(const T& a_value){pr::m_vec[0+0*4] = a_value;}
|
||||
void v10(const T& a_value){pr::m_vec[1+0*4] = a_value;}
|
||||
void v20(const T& a_value){pr::m_vec[2+0*4] = a_value;}
|
||||
void v30(const T& a_value){pr::m_vec[3+0*4] = a_value;}
|
||||
|
||||
void v01(const T& a_value){pr::m_vec[0+1*4] = a_value;}
|
||||
void v11(const T& a_value){pr::m_vec[1+1*4] = a_value;}
|
||||
void v21(const T& a_value){pr::m_vec[2+1*4] = a_value;}
|
||||
void v31(const T& a_value){pr::m_vec[3+1*4] = a_value;}
|
||||
|
||||
void v02(const T& a_value){pr::m_vec[0+2*4] = a_value;}
|
||||
void v12(const T& a_value){pr::m_vec[1+2*4] = a_value;}
|
||||
void v22(const T& a_value){pr::m_vec[2+2*4] = a_value;}
|
||||
void v32(const T& a_value){pr::m_vec[3+2*4] = a_value;}
|
||||
|
||||
void v03(const T& a_value){pr::m_vec[0+3*4] = a_value;}
|
||||
void v13(const T& a_value){pr::m_vec[1+3*4] = a_value;}
|
||||
void v23(const T& a_value){pr::m_vec[2+3*4] = a_value;}
|
||||
void v33(const T& a_value){pr::m_vec[3+3*4] = a_value;}
|
||||
|
||||
const T& v00() const {return pr::m_vec[0+0*4];}
|
||||
const T& v10() const {return pr::m_vec[1+0*4];}
|
||||
const T& v20() const {return pr::m_vec[2+0*4];}
|
||||
const T& v30() const {return pr::m_vec[3+0*4];}
|
||||
|
||||
const T& v01() const {return pr::m_vec[0+1*4];}
|
||||
const T& v11() const {return pr::m_vec[1+1*4];}
|
||||
const T& v21() const {return pr::m_vec[2+1*4];}
|
||||
const T& v31() const {return pr::m_vec[3+1*4];}
|
||||
|
||||
const T& v02() const {return pr::m_vec[0+2*4];}
|
||||
const T& v12() const {return pr::m_vec[1+2*4];}
|
||||
const T& v22() const {return pr::m_vec[2+2*4];}
|
||||
const T& v32() const {return pr::m_vec[3+2*4];}
|
||||
|
||||
const T& v03() const {return pr::m_vec[0+3*4];}
|
||||
const T& v13() const {return pr::m_vec[1+3*4];}
|
||||
const T& v23() const {return pr::m_vec[2+3*4];}
|
||||
const T& v33() const {return pr::m_vec[3+3*4];}
|
||||
|
||||
protected:
|
||||
static void _set_translate(const T& a_x,const T& a_y,const T& a_z,T v[]) {
|
||||
v[0] = T(1);v[4] = 0;v[ 8] = 0;v[12] = a_x;
|
||||
v[1] = 0;v[5] = T(1);v[ 9] = 0;v[13] = a_y;
|
||||
v[2] = 0;v[6] = 0;v[10] = T(1);v[14] = a_z;
|
||||
v[3] = 0;v[7] = 0;v[11] = 0;v[15] = T(1);
|
||||
}
|
||||
|
||||
static void _set_scale(const T& a_1,const T& a_2,const T& a_3,T v[]) {
|
||||
v[0] = a_1;v[4] = 0;v[ 8] = 0;v[12] = 0;
|
||||
v[1] = 0;v[5] = a_2;v[ 9] = 0;v[13] = 0;
|
||||
v[2] = 0;v[6] = 0;v[10] = a_3;v[14] = 0;
|
||||
v[3] = 0;v[7] = 0;v[11] = 0;v[15] = T(1);
|
||||
}
|
||||
static void _set_rotate(const T& a_x,const T& a_y,const T& a_z,
|
||||
const T& a_angle,T v[]) {
|
||||
//WARNING : (a_x,a_y,a_z) must be a normalized vector.
|
||||
T co = (T)::cos(a_angle);
|
||||
T si = (T)::sin(a_angle);
|
||||
T x = a_x;
|
||||
T y = a_y;
|
||||
T z = a_z;
|
||||
T x2 = x*x;
|
||||
T y2 = y*y;
|
||||
T z2 = z*z;
|
||||
T xy = x*y;
|
||||
T xz = x*z;
|
||||
T yz = y*z;
|
||||
v[0] = x2+(1-x2)*co;v[4] = xy*(1-co)-z*si;v[ 8] = xz*(1-co)+y*si;v[12] = 0;
|
||||
v[1] = xy*(1-co)+z*si;v[5] = y2+(1-y2)*co;v[ 9] = yz*(1-co)-x*si;v[13] = 0;
|
||||
v[2] = xz*(1-co)-y*si;v[6] = yz*(1-co)+x*si;v[10] = z2+(1-z2)*co;v[14] = 0;
|
||||
v[3] = 0;v[7] = 0;v[11] = 0;v[15] = 1;
|
||||
|
||||
// If :
|
||||
// n =(x,y,z)
|
||||
// n2 = x2+y2+z2 = 1
|
||||
// n.E = x*E1+y*E2+z*E3
|
||||
// with :
|
||||
// E1 E2 E3
|
||||
// 0 0 0 0 0 -1 0 1 0
|
||||
// 0 0 1 0 0 0 -1 0 0
|
||||
// 0 -1 0 1 0 0 0 0 0
|
||||
//
|
||||
// R(r,c) = cos(theta)*Id(r,c)+(1-cos(theta))*nr*nc-sin(theta)*(n.E)(r,c)
|
||||
//
|
||||
// R = exp(-theta*(n.E))
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
void mul_mtx_rot_root(const T& a_00,const T& a_01,const T& a_02, //1 row
|
||||
const T& a_10,const T& a_11,const T& a_12, //2 row
|
||||
const T& a_20,const T& a_21,const T& a_22) //3 row
|
||||
{
|
||||
T* tv = pr::m_vec;
|
||||
//pr::m_vec[0] = 00;pr::m_vec[4] = 01;pr::m_vec[ 8] = 02;pr::m_vec[12] = 03;
|
||||
//pr::m_vec[1] = 10;pr::m_vec[5] = 11;pr::m_vec[ 9] = 12;pr::m_vec[13] = 13;
|
||||
//pr::m_vec[2] = 20;pr::m_vec[6] = 21;pr::m_vec[10] = 22;pr::m_vec[14] = 23;
|
||||
//pr::m_vec[3] = 30;pr::m_vec[7] = 31;pr::m_vec[11] = 32;pr::m_vec[15] = 33;
|
||||
|
||||
T tv_0 = tv[0];
|
||||
T tv_1 = tv[1];
|
||||
T tv_2 = tv[2];
|
||||
T tv_3 = tv[3];
|
||||
T tv_4 = tv[4];
|
||||
T tv_5 = tv[5];
|
||||
T tv_6 = tv[6];
|
||||
T tv_7 = tv[7];
|
||||
T tv_8 = tv[8];
|
||||
T tv_9 = tv[9];
|
||||
T tv_10 = tv[10];
|
||||
T tv_11 = tv[11];
|
||||
T tv_12 = tv[12];
|
||||
T tv_13 = tv[13];
|
||||
T tv_14 = tv[14];
|
||||
T tv_15 = tv[15];
|
||||
|
||||
T fv_0 = a_00;
|
||||
T fv_1 = a_10;
|
||||
T fv_2 = a_20;
|
||||
//T fv_3 = 0;
|
||||
|
||||
T fv_4 = a_01;
|
||||
T fv_5 = a_11;
|
||||
T fv_6 = a_21;
|
||||
//T fv_7 = 0;
|
||||
|
||||
T fv_8 = a_02;
|
||||
T fv_9 = a_12;
|
||||
T fv_10 = a_22;
|
||||
//T fv_11 = 0;
|
||||
|
||||
//T fv_12 = 0;
|
||||
//T fv_13 = 0;
|
||||
//T fv_14 = 0;
|
||||
//T fv_15 = 1;
|
||||
|
||||
tv[0] = tv_0*fv_0+tv_4*fv_1+ tv_8*fv_2;
|
||||
tv[1] = tv_1*fv_0+tv_5*fv_1+ tv_9*fv_2;
|
||||
tv[2] = tv_2*fv_0+tv_6*fv_1+tv_10*fv_2;
|
||||
tv[3] = tv_3*fv_0+tv_7*fv_1+tv_11*fv_2;
|
||||
|
||||
tv[4] = tv_0*fv_4+tv_4*fv_5+ tv_8*fv_6;
|
||||
tv[5] = tv_1*fv_4+tv_5*fv_5+ tv_9*fv_6;
|
||||
tv[6] = tv_2*fv_4+tv_6*fv_5+tv_10*fv_6;
|
||||
tv[7] = tv_3*fv_4+tv_7*fv_5+tv_11*fv_6;
|
||||
|
||||
tv[8] = tv_0*fv_8+tv_4*fv_9+ tv_8*fv_10;
|
||||
tv[9] = tv_1*fv_8+tv_5*fv_9+ tv_9*fv_10;
|
||||
tv[10] = tv_2*fv_8+tv_6*fv_9+tv_10*fv_10;
|
||||
tv[11] = tv_3*fv_8+tv_7*fv_9+tv_11*fv_10;
|
||||
|
||||
tv[12] = tv_12;
|
||||
tv[13] = tv_13;
|
||||
tv[14] = tv_14;
|
||||
tv[15] = tv_15;
|
||||
}
|
||||
|
||||
private:static void check_instantiation() {mat4<float> dummy;}
|
||||
};
|
||||
|
||||
//for sf, mf :
|
||||
template <class T>
|
||||
inline const T* get_data(const mat4<T>& a_v) {return a_v.data();}
|
||||
|
||||
}
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace tools {
|
||||
|
||||
template <class T>
|
||||
inline std::ostream& operator<<(std::ostream& a_out,const mat4<T>& a_mtx){
|
||||
const T* v = a_mtx.data();
|
||||
a_out << v[0] << "," << v[4] << "," << v[ 8] << "," << v[12]
|
||||
<< std::endl
|
||||
<< v[1] << "," << v[5] << "," << v[ 9] << "," << v[13]
|
||||
<< std::endl
|
||||
<< v[2] << "," << v[6] << "," << v[10] << "," << v[14]
|
||||
<< std::endl
|
||||
<< v[3] << "," << v[7] << "," << v[11] << "," << v[15]
|
||||
<< std::endl;
|
||||
return a_out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user