Import Geant4 10.2.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-10 14:11:04 +02:00
parent c9b32a6c0a
commit d4af681f38
4886 changed files with 420149 additions and 1023309 deletions
+21 -1
View File
@@ -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()
+3 -3
View File
@@ -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
View File
@@ -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
+210
View File
@@ -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
+27 -110
View File
@@ -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 -23
View File
@@ -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
+1 -2
View File
@@ -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
+69 -232
View File
@@ -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();
+30 -60
View File
@@ -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() )
+9 -10
View File
@@ -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() )
+59 -771
View File
@@ -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;
}
+1 -1
View File
@@ -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;
}
+3 -1
View File
@@ -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
+28 -51
View File
@@ -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");
}
}
}
+4 -2
View File
@@ -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();}
+161
View File
@@ -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
+43
View File
@@ -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
+24 -10
View File
@@ -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;
+3 -1
View File
@@ -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
+3 -14
View File
@@ -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") {
+219
View File
@@ -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
+101 -76
View File
@@ -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
+20 -25
View File
@@ -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
+11 -1
View File
@@ -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(){}
+12 -1
View File
@@ -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()
+216 -86
View File
@@ -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);
}
}}
+99
View File
@@ -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
+835
View File
@@ -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