├── .gitignore ├── COPYRIGHT ├── Makefile ├── README.md ├── makeConstants ├── samples ├── ballA.off └── ballB.off ├── src ├── accel │ └── aabvh.h ├── cork.cpp ├── cork.h ├── file_formats │ ├── files.cpp │ ├── files.h │ ├── ifs.cpp │ └── off.cpp ├── isct │ ├── absext4.h │ ├── empty3d.cpp │ ├── empty3d.h │ ├── ext4.h │ ├── fixext4.h │ ├── fixint.h │ ├── gmpext4.h │ ├── quantization.cpp │ ├── quantization.h │ ├── triangle.c │ ├── triangle.h │ └── unsafeRayTriIsct.h ├── main.cpp ├── math │ ├── bbox.h │ ├── ray.h │ └── vec.h ├── mesh │ ├── mesh.bool.tpp │ ├── mesh.decl.h │ ├── mesh.h │ ├── mesh.isct.tpp │ ├── mesh.remesh.tpp │ ├── mesh.topoCache.tpp │ └── mesh.tpp ├── off2obj.cpp ├── rawmesh │ ├── rawMesh.h │ └── rawMesh.tpp └── util │ ├── iterPool.h │ ├── log.cpp │ ├── memPool.h │ ├── prelude.h │ ├── shortVec.h │ ├── timer.cpp │ └── unionFind.h └── win └── wincork ├── wincork.sln ├── wincork.vcxproj └── wincork.vcxproj.filters /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | bin/ 3 | depend/ 4 | include/ 5 | lib/ 6 | obj/ 7 | 8 | error_log.txt 9 | 10 | win/wincork/Debug 11 | win/wincork/Release 12 | win/wincork/*.suo 13 | win/wincork/*.vcxproj.user 14 | win/wincork/*.sdf 15 | win/wincork/*.opensdf 16 | 17 | # in case you're on mac 18 | .DS_Store 19 | 20 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | 2 | Cork is 3 | Copyright Gilbert Bernstein 2013 4 | and made available through the GNU LGPL (see below w/ template exception) 5 | Please contact the author at 6 | gilbert@gilbertbernstein.com 7 | if you would like to discuss licensing under other terms. 8 | 9 | Triangle (used by Franky) is Copyright Jonathan Shewchuk according to the terms spelled out in the comments of triangle.c 10 | 11 | 12 | GNU LESSER GENERAL PUBLIC LICENSE 13 | Version 3, 29 June 2007 14 | 15 | Copyright (C) 2007 Free Software Foundation, Inc. 16 | Everyone is permitted to copy and distribute verbatim copies 17 | of this license document, but changing it is not allowed. 18 | 19 | 20 | This version of the GNU Lesser General Public License incorporates 21 | the terms and conditions of version 3 of the GNU General Public 22 | License, supplemented by the additional permissions listed below. 23 | 24 | 0. Additional Definitions. 25 | 26 | As used herein, "this License" refers to version 3 of the GNU Lesser 27 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 28 | General Public License. 29 | 30 | "The Library" refers to a covered work governed by this License, 31 | other than an Application or a Combined Work as defined below. 32 | 33 | An "Application" is any work that makes use of an interface provided 34 | by the Library, but which is not otherwise based on the Library. 35 | Defining a subclass of a class defined by the Library is deemed a mode 36 | of using an interface provided by the Library. 37 | 38 | A "Combined Work" is a work produced by combining or linking an 39 | Application with the Library. The particular version of the Library 40 | with which the Combined Work was made is also called the "Linked 41 | Version". 42 | 43 | The "Minimal Corresponding Source" for a Combined Work means the 44 | Corresponding Source for the Combined Work, excluding any source code 45 | for portions of the Combined Work that, considered in isolation, are 46 | based on the Application, and not on the Linked Version. 47 | 48 | The "Corresponding Application Code" for a Combined Work means the 49 | object code and/or source code for the Application, including any data 50 | and utility programs needed for reproducing the Combined Work from the 51 | Application, but excluding the System Libraries of the Combined Work. 52 | 53 | 1. Exception to Section 3 of the GNU GPL. 54 | 55 | You may convey a covered work under sections 3 and 4 of this License 56 | without being bound by section 3 of the GNU GPL. 57 | 58 | 2. Conveying Modified Versions. 59 | 60 | If you modify a copy of the Library, and, in your modifications, a 61 | facility refers to a function or data to be supplied by an Application 62 | that uses the facility (other than as an argument passed when the 63 | facility is invoked), then you may convey a copy of the modified 64 | version: 65 | 66 | a) under this License, provided that you make a good faith effort to 67 | ensure that, in the event an Application does not supply the 68 | function or data, the facility still operates, and performs 69 | whatever part of its purpose remains meaningful, or 70 | 71 | b) under the GNU GPL, with none of the additional permissions of 72 | this License applicable to that copy. 73 | 74 | 3. Object Code Incorporating Material from Library Header Files. 75 | 76 | The object code form of an Application may incorporate material from 77 | a header file that is part of the Library. You may convey such object 78 | code under terms of your choice, provided that, if the incorporated 79 | material is not limited to numerical parameters, data structure 80 | layouts and accessors, or small macros, inline functions and templates 81 | (ten or fewer lines in length), you do both of the following: 82 | 83 | a) Give prominent notice with each copy of the object code that the 84 | Library is used in it and that the Library and its use are 85 | covered by this License. 86 | 87 | b) Accompany the object code with a copy of the GNU GPL and this license 88 | document. 89 | 90 | 4. Combined Works. 91 | 92 | You may convey a Combined Work under terms of your choice that, 93 | taken together, effectively do not restrict modification of the 94 | portions of the Library contained in the Combined Work and reverse 95 | engineering for debugging such modifications, if you also do each of 96 | the following: 97 | 98 | a) Give prominent notice with each copy of the Combined Work that 99 | the Library is used in it and that the Library and its use are 100 | covered by this License. 101 | 102 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 103 | document. 104 | 105 | c) For a Combined Work that displays copyright notices during 106 | execution, include the copyright notice for the Library among 107 | these notices, as well as a reference directing the user to the 108 | copies of the GNU GPL and this license document. 109 | 110 | d) Do one of the following: 111 | 112 | 0) Convey the Minimal Corresponding Source under the terms of this 113 | License, and the Corresponding Application Code in a form 114 | suitable for, and under terms that permit, the user to 115 | recombine or relink the Application with a modified version of 116 | the Linked Version to produce a modified Combined Work, in the 117 | manner specified by section 6 of the GNU GPL for conveying 118 | Corresponding Source. 119 | 120 | 1) Use a suitable shared library mechanism for linking with the 121 | Library. A suitable mechanism is one that (a) uses at run time 122 | a copy of the Library already present on the user's computer 123 | system, and (b) will operate properly with a modified version 124 | of the Library that is interface-compatible with the Linked 125 | Version. 126 | 127 | e) Provide Installation Information, but only if you would otherwise 128 | be required to provide such information under section 6 of the 129 | GNU GPL, and only to the extent that such information is 130 | necessary to install and execute a modified version of the 131 | Combined Work produced by recombining or relinking the 132 | Application with a modified version of the Linked Version. (If 133 | you use option 4d0, the Installation Information must accompany 134 | the Minimal Corresponding Source and Corresponding Application 135 | Code. If you use option 4d1, you must provide the Installation 136 | Information in the manner specified by section 6 of the GNU GPL 137 | for conveying Corresponding Source.) 138 | 139 | 5. Combined Libraries. 140 | 141 | You may place library facilities that are a work based on the 142 | Library side by side in a single library together with other library 143 | facilities that are not Applications and are not covered by this 144 | License, and convey such a combined library under terms of your 145 | choice, if you do both of the following: 146 | 147 | a) Accompany the combined library with a copy of the same work based 148 | on the Library, uncombined with any other library facilities, 149 | conveyed under the terms of this License. 150 | 151 | b) Give prominent notice with the combined library that part of it 152 | is a work based on the Library, and explaining where to find the 153 | accompanying uncombined form of the same work. 154 | 155 | 6. Revised Versions of the GNU Lesser General Public License. 156 | 157 | The Free Software Foundation may publish revised and/or new versions 158 | of the GNU Lesser General Public License from time to time. Such new 159 | versions will be similar in spirit to the present version, but may 160 | differ in detail to address new problems or concerns. 161 | 162 | Each version is given a distinguishing version number. If the 163 | Library as you received it specifies that a certain numbered version 164 | of the GNU Lesser General Public License "or any later version" 165 | applies to it, you have the option of following the terms and 166 | conditions either of that published version or of any later version 167 | published by the Free Software Foundation. If the Library as you 168 | received it does not specify a version number of the GNU Lesser 169 | General Public License, you may choose any version of the GNU Lesser 170 | General Public License ever published by the Free Software Foundation. 171 | 172 | If the Library as you received it specifies that a proxy can decide 173 | whether future versions of the GNU Lesser General Public License shall 174 | apply, that proxy's public statement of acceptance of any version is 175 | permanent authorization for you to choose that version for the 176 | Library. 177 | 178 | 179 | ======================================================================== 180 | 181 | ( The following exception for templates is taken from the Qt project ) 182 | 183 | Digia Qt LGPL Exception version 1.1 184 | 185 | As an additional permission to the GNU Lesser General Public License version 186 | 2.1, the object code form of a "work that uses the Library" may incorporate 187 | material from a header file that is part of the Library. You may distribute 188 | such object code under terms of your choice, provided that: 189 | (i) the header files of the Library have not been modified; and 190 | (ii) the incorporated material is limited to numerical parameters, data 191 | structure layouts, accessors, macros, inline functions and 192 | templates; and 193 | (iii) you comply with the terms of Section 6 of the GNU Lesser General 194 | Public License version 2.1. 195 | 196 | Moreover, you may apply this exception to a modified version of the Library, 197 | provided that such modification does not involve copying material from the 198 | Library into the modified Library's header files unless such material is 199 | limited to (i) numerical parameters; (ii) data structure layouts; 200 | (iii) accessors; and (iv) small macros, templates and inline functions of 201 | five lines or less in length. 202 | 203 | Furthermore, you are not required to apply this additional permission to a 204 | modified version of the Library. 205 | 206 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Warning: This makefile rampantly assumes it is being run in UNIX 2 | # Also, there may be some gnu tool chain assumptions: gcc and gmake? 3 | 4 | # *********** 5 | # * PREFACE * 6 | # ***********------+ 7 | # | Subdirectories | 8 | # +----------------+ 9 | # declare subdirectories of the source directory 10 | SUBDIRECTORIES := util file_formats math isct mesh rawmesh accel 11 | 12 | # make sure the subdirectories are mirrored in 13 | # the obj/ debug/ and depend/ directories 14 | # (HACK: use this dummy variable to get access to shell commands) 15 | SHELL_HACK := $(shell mkdir -p bin lib include) 16 | SHELL_HACK := $(shell mkdir -p $(addprefix obj/,$(SUBDIRECTORIES))) 17 | SHELL_HACK := $(shell mkdir -p $(addprefix debug/,$(SUBDIRECTORIES))) 18 | SHELL_HACK := $(shell mkdir -p $(addprefix depend/,$(SUBDIRECTORIES))) 19 | # also make a directory to expose headers in 20 | #SHELL_HACK := $(shell mkdir -p $(addprefix include/,$(SUBDIRECTORIES))) 21 | 22 | # +----------+ 23 | # | Platform | 24 | # +----------+------------------- 25 | # | evaluates to 'Darwin' on mac 26 | # | evaluates to ??? on ??? 27 | # +------------------------------ 28 | PLATFORM := $(shell uname) 29 | 30 | -include makeConstants 31 | 32 | # ********* 33 | # * TOOLS * 34 | # *********--+ 35 | # | Programs | 36 | # +----------+ 37 | CPP11_FLAGS := -std=c++11 38 | CC := clang 39 | CXX := clang++ 40 | ifeq ($(PLATFORM),Darwin) # on mac 41 | CPP11_FLAGS := $(CPP11_FLAGS) -stdlib=libc++ -Wno-c++11-extensions 42 | endif 43 | RM := rm 44 | CP := cp 45 | 46 | # +--------------+ 47 | # | Option Flags | 48 | # +--------------+ 49 | # Let the preprocessor know which platform we're on 50 | ifeq ($(PLATFORM),Darwin) 51 | CONFIG := $(CONFIG) -DMACOSX 52 | else 53 | CONFIG := $(CONFIG) 54 | endif 55 | 56 | # include paths (flattens the hierarchy for include directives) 57 | INC := -I src/ $(addprefix -I src/,$(SUBDIRECTORIES)) 58 | # get the location of GMP header files from makeConstants include file 59 | GMPINC := -I $(GMP_INC_DIR) 60 | INC := $(INC) $(GMPINC) 61 | 62 | # use the second line to disable profiling instrumentation 63 | # PROFILING := -pg 64 | PROFILING := 65 | CCFLAGS := -Wall $(INC) $(CONFIG) -O2 -DNDEBUG $(PROFILING) 66 | CXXFLAGS := $(CCFLAGS) $(CPP11_FLAGS) 67 | CCDFLAGS := -Wall $(INC) $(CONFIG) -ggdb 68 | CXXDFLAGS := $(CCDFLAGS) 69 | 70 | # Place the location of GMP libraries here 71 | GMPLD := -L$(GMP_LIB_DIR) -lgmpxx -lgmp 72 | # static version... 73 | #GMPLD := $(GMP_LIB_DIR)/libgmpxx.a $(GMP_LIB_DIR)/libgmp.a 74 | 75 | LINK := $(CXXFLAGS) $(GMPLD) 76 | LINKD := $(CXXDFLAGS) $(GMPLD) 77 | ifeq ($(PLATFORM),Darwin) 78 | LINK := $(LINK) -Wl,-no_pie 79 | LINKD := $(LINK) -Wl,-no_pie 80 | endif 81 | 82 | 83 | # *********************** 84 | # * SOURCE DECLARATIONS * 85 | # ***********************-----------------+ 86 | # | SRCS defines a generic bag of sources | 87 | # +---------------------------------------+ 88 | MATH_SRCS := 89 | UTIL_SRCS := timer log 90 | ISCT_SRCS := empty3d quantization 91 | MESH_SRCS := 92 | RAWMESH_SRCS := 93 | ACCEL_SRCS := 94 | FILE_SRCS := files ifs off 95 | SRCS := \ 96 | cork \ 97 | $(addprefix math/,$(MATH_SRCS))\ 98 | $(addprefix util/,$(UTIL_SRCS))\ 99 | $(addprefix isct/,$(ISCT_SRCS))\ 100 | $(addprefix mesh/,$(MESH_SRCS))\ 101 | $(addprefix rawmesh/,$(RAWMESH_SRCS))\ 102 | $(addprefix accel/,$(ACCEL_SRCS))\ 103 | $(addprefix file_formats/,$(FILE_SRCS)) 104 | 105 | 106 | # +-----------------------------------+ 107 | # | HEADERS defines headers to export | 108 | # +-----------------------------------+ 109 | MATH_HEADERS := vec.h bbox.h ray.h 110 | UTIL_HEADERS := prelude.h memPool.h iterPool.h shortVec.h \ 111 | unionFind.h 112 | ISCT_HEADERS := unsafeRayTriIsct.h \ 113 | ext4.h fixext4.h gmpext4.h absext4.h \ 114 | quantization.h fixint.h \ 115 | empty3d.h \ 116 | triangle.h 117 | RAWMESH_HEADERS := rawMesh.h rawMesh.tpp 118 | MESH_HEADERS := mesh.h mesh.decl.h \ 119 | mesh.tpp mesh.topoCache.tpp \ 120 | mesh.remesh.tpp mesh.isct.tpp mesh.bool.tpp 121 | ACCEL_HEADERS := aabvh.h 122 | FILE_HEADERS := files.h 123 | HEADERS := \ 124 | cork.h 125 | # $(addprefix math/,$(MATH_HEADERS))\ 126 | # $(addprefix util/,$(UTIL_HEADERS))\ 127 | # $(addprefix isct/,$(ISCT_HEADERS))\ 128 | # $(addprefix mesh/,$(MESH_HEADERS))\ 129 | # $(addprefix rawmesh/,$(RAWMESH_HEADERS))\ 130 | # $(addprefix accel/,$(ACCEL_HEADERS))\ 131 | # $(addprefix file_formats/,$(FILE_HEADERS)) 132 | HEADER_COPIES := $(addprefix include/,$(HEADERS)) 133 | 134 | # +-----------------------------+ 135 | # | stand alone program sources | 136 | # +-----------------------------+ 137 | MAIN_SRC := \ 138 | $(SRCS) \ 139 | main 140 | 141 | # +---------------------------------------+ 142 | # | all sources for dependency generation | 143 | # +---------------------------------------+ 144 | ALL_SRCS := \ 145 | $(SRCS)\ 146 | main 147 | DEPENDS := $(addprefix depend/,$(addsuffix .d,$(ALL_SRCS))) 148 | 149 | # +--------------------------------+ 150 | # | Object Aggregation for Targets | 151 | # +--------------------------------+ 152 | 153 | OBJ := $(addprefix obj/,$(addsuffix .o,$(SRCS))) \ 154 | obj/isct/triangle.o 155 | DEBUG := $(addprefix debug/,$(addsuffix .o,$(SRCS))) \ 156 | obj/isct/triangle.o 157 | 158 | MAIN_OBJ := $(addprefix obj/,$(addsuffix .o,$(MAIN_SRC))) \ 159 | obj/isct/triangle.o 160 | MAIN_DEBUG := $(addprefix debug/,$(addsuffix .o,$(MAIN_SRC))) \ 161 | obj/isct/triangle.o 162 | 163 | LIB_TARGET_NAME := cork 164 | 165 | # ********* 166 | # * RULES * 167 | # *********------+ 168 | # | Target Rules | 169 | # +--------------+ 170 | all: lib/lib$(LIB_TARGET_NAME).a includes \ 171 | bin/off2obj bin/cork 172 | debug: lib/lib$(LIB_TARGET_NAME)debug.a includes 173 | 174 | lib/lib$(LIB_TARGET_NAME).a: $(OBJ) 175 | @echo "Bundling $@" 176 | @ar rcs $@ $(OBJ) 177 | 178 | lib/lib$(LIB_TARGET_NAME)debug.a: $(DEBUG) 179 | @echo "Bundling $@" 180 | @ar rcs $@ $(DEBUG) 181 | 182 | bin/cork: $(MAIN_OBJ) 183 | @echo "Linking cork command line tool" 184 | @$(CXX) -o bin/cork $(MAIN_OBJ) $(LINK) 185 | 186 | bin/off2obj: obj/off2obj.o 187 | @echo "Linking off2obj" 188 | @$(CXX) -o bin/off2obj obj/off2obj.o $(LINK) 189 | 190 | # +------------------------------+ 191 | # | Specialized File Build Rules | 192 | # +------------------------------+ 193 | 194 | obj/isct/triangle.o: src/isct/triangle.c 195 | @echo "Compiling the Triangle library" 196 | @$(CC) -O2 -DNO_TIMER \ 197 | -DREDUCED \ 198 | -DCDT_ONLY -DTRILIBRARY \ 199 | -Wall -DANSI_DECLARATORS \ 200 | -o obj/isct/triangle.o -c src/isct/triangle.c 201 | 202 | # +------------------------------------+ 203 | # | Generic Source->Object Build Rules | 204 | # +------------------------------------+ 205 | obj/%.o: src/%.cpp 206 | @echo "Compiling $@" 207 | @$(CXX) $(CXXFLAGS) -o $@ -c $< 208 | 209 | debug/%.o: src/%.cpp 210 | @echo "Compiling $@" 211 | @$(CXX) $(CXXDFLAGS) -o $@ -c $< 212 | 213 | # dependency file build rules 214 | depend/%.d: src/%.cpp 215 | @$(CXX) $(CXXFLAGS) -MM $< | \ 216 | sed -e 's@^\(.*\)\.o:@depend/$*.d debug/$*.o obj/$*.o:@' > $@ 217 | 218 | # +-------------------+ 219 | # | include copy rule | 220 | # +-------------------+--------------------- 221 | # | This rule exists to safely propagate 222 | # | header file dependencies to other 223 | # | targets that depend on the common code 224 | # +----------------------------------------- 225 | includes: $(HEADER_COPIES) 226 | 227 | include/%.h: src/%.h 228 | @echo "updating $@" 229 | @cp $< $@ 230 | #also support template implementation files 231 | include/%.tpp: src/%.tpp 232 | @echo "updating $@" 233 | @cp $< $@ 234 | 235 | # +---------------+ 236 | # | cleaning rule | 237 | # +---------------+ 238 | clean: 239 | -@$(RM) -r obj depend debug include bin lib 240 | -@$(RM) bin/off2obj 241 | # -@$(RM) gmon.out 242 | -@$(RM) lib/lib$(LIB_TARGET_NAME).a 243 | -@$(RM) lib/lib$(LIB_TARGET_NAME)debug.a 244 | 245 | -include $(DEPENDS) 246 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Cork Boolean Library 2 | ==================== 3 | 4 | Welcome to the Cork Boolean/CSG library. Cork is designed to support Boolean operations between triangle meshes. 5 | 6 | Surprisingly, most Boolean/CSG libraries available today (early 2013) are not robust to numerical errors. Floating-point errors often lead to segmentation faults or produce grossly inaccurate results (e.g. nothing) despite the code being provided . The few libraries which are robust (e.g. CGAL) require the user to correctly configure the arithmetic settings to ensure robustness. 7 | 8 | Cork is designed with the philosophy that you, the user, don't know and don't care about esoteric problems with floating point arithmetic. You just want a Boolean library with a simple interface, that you can rely on... Unfortunately since Cork is still in ongoing development, this may be more or less true at the moment. This code should be very usable for a research project, perhaps slightly less so for use in a product. 9 | 10 | Cork was developed by Gilbert Bernstein, a computer scientist who has worked on robust geometric intersections in various projects since 2007. He's reasonably confident he knows what he's doing. =D 11 | 12 | WARNING: Unfortunately, there are a number of known problems with Cork. I have zero time to work on the library since I'm currently busy working on a thesis. (March 2016) If you would like to pay me large sums of money to improve this library, maybe we should talk. Otherwise, I'm really quite sorry to say I don't have time. 13 | 14 | 15 | Installation 16 | ============ 17 | 18 | Dependencies (Mac/Linux) 19 | ------------ 20 | 21 | In order to build Cork on Mac or Linux, you will need Clang 3.1+ and GMP (GNU Multi-Precision arithmetic library). Eventually, Cork will support GCC. If you would like more information, or have special system requirements, please e-mail me: I'm much more likely to extend support to a platform if I receive requests. 22 | 23 | Mac 24 | --- 25 | 26 | On OS X 10.8, Clang 3.1+ is the default compiler. If you are using the Homebrew package manager, I recommend installing GMP that way. 27 | 28 | Linux 29 | ----- 30 | 31 | Clang/LLVM 3.1 and GMP can be installed via your package manager. 32 | 33 | 34 | Mac/Linux 35 | ---- 36 | 37 | To build the project, type 38 | 39 | make 40 | 41 | that's it. 42 | 43 | 44 | If the build system is unable to find your GMP installation, please edit the paths in file makeConstants. In general, the project uses a basic makefile. In the event that you have to do something more complicated to get the library to compile, or if you are unable to get it to compile, please e-mail me or open an issue on GitHub. Doing so is much more effective than cursing at your computer, and will save other users trouble in the future. 45 | 46 | 47 | Windows 48 | ---- 49 | 50 | Cork uses C++11, so you will need the most recent compiler; Visual Studio 2012 or higher please. You will also need to install the MPIR arithmetic library into your Visual Studio environment. 51 | 52 | Once this is done, you can use the solution and project files in the /win/ subdirectory to build the demo program. The solution/project is not currently configured to build a DLL. Please bug me if this is an issue for you. 53 | 54 | 55 | Licensing 56 | ========= 57 | 58 | Cork is licensed under the LGPL with an exception (from QT) to more easily allow use of template code. In plain English, the following are some guidelines on the use of this code: 59 | 60 | * Unless you also intend to release your project under LGPL/GPL, you must make sure to DYNAMICALLY link against the Cork library. However, you may include unmodified header files without compromising your proprietary code. 61 | 62 | * If you distribute your code, (publicly or privately, compiled or in source form, for free or commercially) you must (a) acknowledge your use of Cork, (b) include the COPYRIGHT information and (c) either distribute the Cork code or clearly indicate where a copy may be found. 63 | 64 | Of course, none of the above supercedes the actual COPYRIGHT. 65 | 66 | 67 | -------------------------------------------------------------------------------- /makeConstants: -------------------------------------------------------------------------------- 1 | 2 | GMP_INC_DIR = /usr/local/Cellar/gmp/5.0.2/include 3 | GMP_LIB_DIR = /usr/local/Cellar/gmp/5.0.2/lib -------------------------------------------------------------------------------- /src/accel/aabvh.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | aabvh.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include "bbox.h" 29 | 30 | #include 31 | 32 | // maximum leaf size 33 | static const uint LEAF_SIZE = 8; 34 | 35 | template 36 | struct GeomBlob 37 | { 38 | BBox3d bbox; 39 | Vec3d point; // representative point, usually the box midpoint 40 | GeomIdx id; 41 | }; 42 | 43 | template 44 | struct AABVHNode 45 | { 46 | BBox3d bbox; 47 | AABVHNode *left; 48 | AABVHNode *right; 49 | ShortVec blobids; 50 | inline bool isLeaf() const { return left == nullptr; } 51 | }; 52 | 53 | template 54 | class AABVH 55 | { 56 | public: 57 | AABVH(const std::vector< GeomBlob > &geoms) : 58 | root(nullptr), blobs(geoms), tmpids(geoms.size()) 59 | { 60 | ENSURE(blobs.size() > 0); 61 | 62 | for(uint k=0; k action 73 | ) { 74 | // do a recursive search and invoke the action at each 75 | // piece of geometry 76 | std::stack< AABVHNode* > nodes; 77 | nodes.push(root); 78 | 79 | while(!nodes.empty()) { 80 | AABVHNode *node = nodes.top(); 81 | nodes.pop(); 82 | 83 | // check bounding box isct 84 | if(!hasIsct(node->bbox, bbox)) continue; 85 | 86 | // otherwise... 87 | if(node->isLeaf()) { 88 | for(uint bid : node->blobids) { 89 | if(hasIsct(bbox, blobs[bid].bbox)) 90 | action(blobs[bid].id); 91 | } 92 | } else { 93 | nodes.push(node->left); 94 | nodes.push(node->right); 95 | } 96 | } 97 | } 98 | 99 | private: 100 | // process range of tmpids including begin, excluding end 101 | // last_dim provides a hint by saying which dimension a 102 | // split was last made along 103 | AABVHNode* constructTree(uint begin, uint end, uint last_dim) 104 | { 105 | ENSURE(end - begin > 0); // don't tell me to build a tree from nothing 106 | // base case 107 | if(end-begin <= LEAF_SIZE) { 108 | AABVHNode *node = node_pool.alloc(); 109 | node->left = nullptr; 110 | node->blobids.resize(end-begin); 111 | for(uint k=0; kblobids[k] = tmpids[begin + k]; 113 | node->bbox = convex(node->bbox, blobs[blobid].bbox); 114 | } 115 | return node; 116 | } 117 | // otherwise, let's try to split this geometry up 118 | 119 | uint dim = (last_dim+1)%3; 120 | uint mid = (begin + end) / 2; 121 | quickSelect(mid, begin, end, dim); 122 | 123 | // now recurse 124 | AABVHNode *node = node_pool.alloc(); 125 | node->left = constructTree(begin, mid, dim); 126 | node->right = constructTree(mid, end, dim); 127 | node->bbox = convex(node->left->bbox, node->right->bbox); 128 | return node; 129 | } 130 | 131 | // precondition: begin <= select < end 132 | void quickSelect(uint select, uint begin, uint end, uint dim) 133 | { 134 | // NOTE: values equal to the pivot 135 | // may appear on either side of the split 136 | if(end-1 == select) return; 137 | 138 | // p(ivot)i(ndex) and p(ivot)v(alue) 139 | uint pi = randMod(end-begin) + begin; 140 | double pv = blobs[tmpids[pi]].point[dim]; 141 | 142 | int front = begin; 143 | int back = end-1; 144 | while(front < back) { 145 | if(blobs[tmpids[front]].point[dim] < pv) { 146 | front++; 147 | } 148 | else if(blobs[tmpids[back]].point[dim] > pv) { 149 | back--; 150 | } 151 | else { 152 | std::swap(tmpids[front], tmpids[back]); 153 | front++; 154 | back--; 155 | } 156 | } 157 | if(front == back && blobs[tmpids[front]].point[dim] <= pv) { 158 | front++; 159 | } 160 | 161 | if(select < uint(front)) { 162 | quickSelect(select, begin, front, dim); 163 | } else { 164 | quickSelect(select, front, end, dim); 165 | } 166 | } 167 | private: 168 | AABVHNode *root; 169 | 170 | IterPool< AABVHNode > node_pool; 171 | std::vector< GeomBlob > blobs; 172 | std::vector tmpids; // used during construction 173 | }; 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /src/cork.cpp: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | cork.cpp 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #include "cork.h" 27 | 28 | #include "mesh.h" 29 | 30 | 31 | void freeCorkTriMesh(CorkTriMesh *mesh) 32 | { 33 | delete[] mesh->triangles; 34 | delete[] mesh->vertices; 35 | mesh->n_triangles = 0; 36 | mesh->n_vertices = 0; 37 | } 38 | 39 | 40 | struct CorkTriangle; 41 | 42 | struct CorkVertex : 43 | public MinimalVertexData, 44 | public RemeshVertexData, 45 | public IsctVertexData, 46 | public BoolVertexData 47 | { 48 | void merge(const CorkVertex &v0, const CorkVertex &v1) { 49 | double a0 = 0.5; 50 | if(v0.manifold && !v1.manifold) a0 = 0.0; 51 | if(!v0.manifold && v1.manifold) a0 = 1.0; 52 | double a1 = 1.0 - a0; 53 | 54 | pos = a0 * v0.pos + a1 * v1.pos; 55 | } 56 | void interpolate(const CorkVertex &v0, const CorkVertex &v1) { 57 | double a0 = 0.5; 58 | double a1 = 0.5; 59 | pos = a0 * v0.pos + a1 * v1.pos; 60 | } 61 | 62 | 63 | void isct(IsctVertEdgeTriInput input) 64 | { 65 | Vec2d a_e = Vec2d(1,1)/2.0; 66 | Vec3d a_t = Vec3d(1,1,1)/3.0; 67 | a_e /= 2.0; 68 | a_t /= 2.0; 69 | } 70 | void isct(IsctVertTriTriTriInput input) 71 | { 72 | Vec3d a[3]; 73 | for(uint k=0; k<3; k++) { 74 | a[k] = Vec3d(1,1,1)/3.0; 75 | a[k] /= 3.0; 76 | } 77 | for(uint i=0; i<3; i++) { 78 | for(uint j=0; j<3; j++) { 79 | }} 80 | } 81 | void isctInterpolate(const CorkVertex &v0, const CorkVertex &v1) { 82 | double a0 = len(v1.pos - pos); 83 | double a1 = len(v0.pos - pos); 84 | if(a0 + a1 == 0.0) a0 = a1 = 0.5; // safety 85 | double sum = a0+a1; 86 | a0 /= sum; 87 | a1 /= sum; 88 | } 89 | }; 90 | 91 | struct CorkTriangle : 92 | public MinimalTriangleData, 93 | public RemeshTriangleData, 94 | public IsctTriangleData, 95 | public BoolTriangleData 96 | { 97 | void merge(const CorkTriangle &, const CorkTriangle &) {} 98 | static void split(CorkTriangle &, CorkTriangle &, 99 | const CorkTriangle &) {} 100 | void move(const CorkTriangle &) {} 101 | void subdivide(SubdivideTriInput input) 102 | { 103 | bool_alg_data = input.pt->bool_alg_data; 104 | } 105 | }; 106 | 107 | //using RawCorkMesh = RawMesh; 108 | //using CorkMesh = Mesh; 109 | typedef RawMesh RawCorkMesh; 110 | typedef Mesh CorkMesh; 111 | 112 | void corkTriMesh2CorkMesh( 113 | CorkTriMesh in, 114 | CorkMesh *mesh_out 115 | ) { 116 | RawCorkMesh raw; 117 | raw.vertices.resize(in.n_vertices); 118 | raw.triangles.resize(in.n_triangles); 119 | if(in.n_vertices == 0 || in.n_triangles == 0) { 120 | CORK_ERROR("empty mesh input to Cork routine."); 121 | *mesh_out = CorkMesh(raw); 122 | return; 123 | } 124 | 125 | uint max_ref_idx = 0; 126 | for(uint i=0; i in.n_vertices) { 138 | CORK_ERROR("mesh input to Cork routine has an out of range reference " 139 | "to a vertex."); 140 | raw.vertices.clear(); 141 | raw.triangles.clear(); 142 | *mesh_out = CorkMesh(raw); 143 | return; 144 | } 145 | 146 | for(uint i=0; iraw(); 159 | 160 | out->n_triangles = raw.triangles.size(); 161 | out->n_vertices = raw.vertices.size(); 162 | 163 | out->triangles = new uint[(out->n_triangles) * 3]; 164 | out->vertices = new float[(out->n_vertices) * 3]; 165 | 166 | for(uint i=0; in_triangles; i++) { 167 | (out->triangles)[3*i+0] = raw.triangles[i].a; 168 | (out->triangles)[3*i+1] = raw.triangles[i].b; 169 | (out->triangles)[3*i+2] = raw.triangles[i].c; 170 | } 171 | 172 | for(uint i=0; in_vertices; i++) { 173 | (out->vertices)[3*i+0] = raw.vertices[i].pos.x; 174 | (out->vertices)[3*i+1] = raw.vertices[i].pos.y; 175 | (out->vertices)[3*i+2] = raw.vertices[i].pos.z; 176 | } 177 | } 178 | 179 | 180 | bool isSolid(CorkTriMesh cmesh) 181 | { 182 | CorkMesh mesh; 183 | corkTriMesh2CorkMesh(cmesh, &mesh); 184 | 185 | bool solid = true; 186 | 187 | if(mesh.isSelfIntersecting()) { 188 | CORK_ERROR("isSolid() was given a self-intersecting mesh"); 189 | solid = false; 190 | } 191 | 192 | if(!mesh.isClosed()) { 193 | CORK_ERROR("isSolid() was given a non-closed mesh"); 194 | solid = false; 195 | } 196 | 197 | return solid; 198 | } 199 | 200 | void computeUnion( 201 | CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out 202 | ) { 203 | CorkMesh cmIn0, cmIn1; 204 | corkTriMesh2CorkMesh(in0, &cmIn0); 205 | corkTriMesh2CorkMesh(in1, &cmIn1); 206 | 207 | cmIn0.boolUnion(cmIn1); 208 | 209 | corkMesh2CorkTriMesh(&cmIn0, out); 210 | } 211 | 212 | void computeDifference( 213 | CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out 214 | ) { 215 | CorkMesh cmIn0, cmIn1; 216 | corkTriMesh2CorkMesh(in0, &cmIn0); 217 | corkTriMesh2CorkMesh(in1, &cmIn1); 218 | 219 | cmIn0.boolDiff(cmIn1); 220 | 221 | corkMesh2CorkTriMesh(&cmIn0, out); 222 | } 223 | 224 | void computeIntersection( 225 | CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out 226 | ) { 227 | CorkMesh cmIn0, cmIn1; 228 | corkTriMesh2CorkMesh(in0, &cmIn0); 229 | corkTriMesh2CorkMesh(in1, &cmIn1); 230 | 231 | cmIn0.boolIsct(cmIn1); 232 | 233 | corkMesh2CorkTriMesh(&cmIn0, out); 234 | } 235 | 236 | void computeSymmetricDifference( 237 | CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out 238 | ) { 239 | CorkMesh cmIn0, cmIn1; 240 | corkTriMesh2CorkMesh(in0, &cmIn0); 241 | corkTriMesh2CorkMesh(in1, &cmIn1); 242 | 243 | cmIn0.boolXor(cmIn1); 244 | 245 | corkMesh2CorkTriMesh(&cmIn0, out); 246 | } 247 | 248 | void resolveIntersections( 249 | CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out 250 | ) { 251 | CorkMesh cmIn0, cmIn1; 252 | corkTriMesh2CorkMesh(in0, &cmIn0); 253 | corkTriMesh2CorkMesh(in1, &cmIn1); 254 | 255 | cmIn0.disjointUnion(cmIn1); 256 | cmIn0.resolveIntersections(); 257 | 258 | corkMesh2CorkTriMesh(&cmIn0, out); 259 | } 260 | 261 | -------------------------------------------------------------------------------- /src/cork.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | cork.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #ifndef uint 29 | typedef unsigned int uint; 30 | #endif 31 | 32 | // if a mesh is taken as input, the client must manage the memory 33 | // if a mesh is given as output, please use the provided 34 | // function to free the allocated memory. 35 | struct CorkTriMesh 36 | { 37 | uint n_triangles; 38 | uint n_vertices; 39 | uint *triangles; 40 | float *vertices; 41 | }; 42 | 43 | void freeCorkTriMesh(CorkTriMesh *mesh); 44 | 45 | // the inputs to Boolean operations must be "solid": 46 | // - closed (aka. watertight; see comment at bottom) 47 | // - non-self-intersecting 48 | // additionally, inputs should use a counter-clockwise convention 49 | // for triangle facing. If the triangles are presented in clockwise 50 | // orientation, the object is interpreted as its unbounded complement 51 | 52 | // This function will test whether or not a mesh is solid 53 | bool isSolid(CorkTriMesh mesh); 54 | 55 | // Boolean operations follow 56 | // result = A U B 57 | void computeUnion(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out); 58 | 59 | // result = A - B 60 | void computeDifference(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out); 61 | 62 | // result = A ^ B 63 | void computeIntersection(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out); 64 | 65 | // result = A XOR B 66 | void computeSymmetricDifference( 67 | CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out); 68 | 69 | // Not a Boolean operation, but related: 70 | // No portion of either surface is deleted. However, the 71 | // curve of intersection between the two surfaces is made explicit, 72 | // such that the two surfaces are now connected. 73 | void resolveIntersections(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out); 74 | 75 | -------------------------------------------------------------------------------- /src/file_formats/files.cpp: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | files.cpp 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #include "files.h" 27 | 28 | #include 29 | using std::cout; 30 | using std::cerr; 31 | using std::endl; 32 | 33 | namespace Files { 34 | 35 | using std::string; 36 | 37 | // private module data 38 | namespace { 39 | } 40 | 41 | int readTriMesh(string filename, FileMesh *mesh) 42 | { 43 | int lastdot = filename.find_last_of('.'); 44 | if(lastdot < 0) return 1; 45 | string suffix = filename.substr(lastdot, filename.length()-lastdot); 46 | if(suffix == ".ifs") 47 | return readIFS(filename, mesh); 48 | else if (suffix == ".off") 49 | return readOFF(filename, mesh); 50 | else 51 | return 1; 52 | } 53 | 54 | int writeTriMesh(string filename, FileMesh *mesh) 55 | { 56 | int lastdot = filename.find_last_of('.'); 57 | if(lastdot < 0) return 1; 58 | string suffix = filename.substr(lastdot, filename.length()-lastdot); 59 | if(suffix == ".ifs") 60 | return writeIFS(filename, mesh); 61 | else if (suffix == ".off") 62 | return writeOFF(filename, mesh); 63 | else 64 | return 1; 65 | } 66 | 67 | } // end namespace Files 68 | -------------------------------------------------------------------------------- /src/file_formats/files.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | files.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include 29 | 30 | //#include "triMesh.h" 31 | 32 | #include "rawMesh.h" 33 | 34 | /* 35 | * Files provides a wrapper for different file types and a common 36 | * data view for the rest of the program. This wrapper was introduced 37 | * to make it easier to support multiple file types using other people's 38 | * file importer/exporter code 39 | */ 40 | 41 | namespace Files { 42 | 43 | // all functions with integer return values here are intended 44 | // to return an error count as if they were a main function 45 | 46 | struct FileVertex : public MinimalVertexData {}; 47 | struct FileTriangle : public MinimalTriangleData {}; 48 | typedef RawMesh FileMesh; 49 | //using FileMesh = RawMesh; 50 | 51 | // generic filetype functions 52 | // these detect which filetype to use by inspecting the filename 53 | int readTriMesh(std::string filename, FileMesh *mesh); 54 | int writeTriMesh(std::string filename, FileMesh *mesh); 55 | 56 | // specific filetype functions 57 | int readIFS(std::string filename, FileMesh *mesh); 58 | int writeIFS(std::string filename, FileMesh *mesh); 59 | 60 | int readOFF(std::string filename, FileMesh *mesh); 61 | int writeOFF(std::string filename, FileMesh *mesh); 62 | 63 | } // end namespace Files 64 | -------------------------------------------------------------------------------- /src/file_formats/ifs.cpp: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | ifs.cpp 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #include "files.h" 27 | 28 | #include 29 | #include 30 | using std::ifstream; 31 | using std::ofstream; 32 | using std::cout; 33 | using std::endl; 34 | #include 35 | 36 | 37 | namespace Files { 38 | 39 | using std::string; 40 | 41 | // private module data 42 | namespace { 43 | typedef float float32; 44 | typedef unsigned int uint32; 45 | 46 | bool swapBytes; 47 | bool writeFlipping = false; 48 | } 49 | 50 | // All functions return true 51 | // if there are no errors 52 | 53 | inline void flip(char *bytes, int num) 54 | { 55 | char temp; 56 | for(int i=0; ivertices.resize(num_vertices); 277 | for(auto &v : data->vertices) { 278 | if(!read_vertex(in, v.pos)) return 1; 279 | } 280 | 281 | // TRIANGLES 282 | if(!checkString(in,"TRIANGLES")) return 1; 283 | if(!readString(in,junk_str)) return 1; 284 | uint32 num_tris; 285 | if(!read_uint32(in, num_tris)) return 1; 286 | data->triangles.resize(num_tris); 287 | for(auto &tri : data->triangles) { 288 | if(!read_triangle(in, tri)) return 1; 289 | } 290 | 291 | // TEXTURECOORD 292 | if(hasTextures) { 293 | // noop 294 | } 295 | 296 | return 0; 297 | } 298 | 299 | int writeIFS(string filename, FileMesh *data) 300 | { 301 | swapBytes = writeFlipping; 302 | string junk_str; 303 | if(!data) return 1; 304 | 305 | ofstream out; 306 | out.open(filename.c_str(), std::ios::out | std::ios::binary); 307 | if(!out) return 1; 308 | 309 | // "IFS" 310 | if(!writeString(out,"IFS")) return 1; 311 | // version # 312 | float32 version = 1.0; // i.e. no textures 313 | if(!write_float32(out,version)) return 1; 314 | // model name 315 | if(!writeString(out,"no_name")) return 1; 316 | 317 | // VERTICES 318 | if(!writeString(out,"VERTICES")) return 1; 319 | uint32 num_vertices = data->vertices.size(); 320 | if(!write_uint32(out, num_vertices)) return 1; 321 | for(const auto &v : data->vertices) { 322 | if(!write_vertex(out, v.pos)) return 1; 323 | } 324 | 325 | // TRIANGLES 326 | if(!writeString(out,"TRIANGLES")) return 1; 327 | uint32 num_tris = data->triangles.size(); 328 | if(!write_uint32(out, num_tris)) return 1; 329 | for(const auto &tri : data->triangles) { 330 | if(!write_triangle(out, tri)) return 1; 331 | } 332 | 333 | // TEXTURECOORD 334 | // not used 335 | 336 | return 0; 337 | } 338 | 339 | } // end namespace Files 340 | -------------------------------------------------------------------------------- /src/file_formats/off.cpp: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | off.cpp 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #include "files.h" 27 | 28 | #include 29 | #include 30 | using std::ifstream; 31 | using std::ofstream; 32 | using std::endl; 33 | 34 | 35 | namespace Files { 36 | 37 | using std::string; 38 | using std::vector; 39 | 40 | int readOFF(string filename, FileMesh *data) 41 | { 42 | if(!data) return 1; 43 | 44 | ifstream in; // will close on exit from this read function 45 | in.open(filename.c_str()); 46 | if(!in) return 1; 47 | 48 | // "OFF" 49 | string filetype; 50 | in >> filetype; 51 | if(filetype != "OFF") return 1; 52 | 53 | // counts of things 54 | int numvertices, numfaces, numedges; 55 | in >> numvertices >> numfaces >> numedges; 56 | if(!in) return 1; 57 | data->vertices.resize(numvertices); 58 | data->triangles.resize(numfaces); 59 | 60 | // vertex data 61 | for(auto &v : data->vertices) { 62 | Vec3d &p = v.pos; 63 | in >> p.x >> p.y >> p.z; 64 | } 65 | if(!in) return 1; 66 | 67 | // face data 68 | for(auto &tri : data->triangles) { 69 | int polysize; 70 | in >> polysize; 71 | if(polysize != 3) return 1; 72 | 73 | in >> tri.a >> tri.b >> tri.c; 74 | } 75 | if(!in) return 1; 76 | 77 | return 0; 78 | } 79 | 80 | int writeOFF(string filename, FileMesh *data) 81 | { 82 | if(!data) return 1; 83 | 84 | ofstream out; 85 | out.open(filename.c_str()); 86 | if(!out) return 1; 87 | 88 | // "OFF" 89 | out << "OFF" << endl; 90 | 91 | // numvertices, numfaces, numedges=0 92 | int numvertices = data->vertices.size(); 93 | int numfaces = data->triangles.size(); 94 | out << numvertices << ' ' << numfaces << ' ' << 0 << endl; 95 | 96 | // vertex data 97 | for(const auto &v : data->vertices) { 98 | const Vec3d &p = v.pos; 99 | out << p.x << ' ' << p.y << ' ' << p.z << endl; 100 | } 101 | 102 | // face data 103 | for(const auto &tri : data->triangles) { 104 | out << "3 " << tri.a << ' ' << tri.b << ' ' << tri.c << endl; 105 | } 106 | if(!out) return 1; 107 | 108 | return 0; 109 | } 110 | 111 | 112 | 113 | } // end namespace Files 114 | -------------------------------------------------------------------------------- /src/isct/absext4.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | absext4.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | /* 29 | * 30 | * AbsExt4 31 | * 32 | * Support for performing exterior calculus in R4 33 | * 34 | * Used for performing filter computations. 35 | * All numbers are positive! (overflow/underflow are concerns) 36 | * and all numbers are kept positive 37 | * 38 | */ 39 | 40 | #include "ext4.h" 41 | 42 | #include 43 | 44 | namespace AbsExt4 { 45 | 46 | using namespace Ext4; 47 | using std::fabs; 48 | 49 | struct AbsExt4_1 { 50 | union { 51 | double v[4]; 52 | struct { 53 | double e0; 54 | double e1; 55 | double e2; 56 | double e3; 57 | }; 58 | }; 59 | }; 60 | 61 | struct AbsExt4_2 { 62 | union { 63 | double v[6]; 64 | struct { 65 | double e01; 66 | double e02; 67 | double e03; 68 | double e12; 69 | double e13; 70 | double e23; 71 | }; 72 | }; 73 | }; 74 | 75 | struct AbsExt4_3 { 76 | union { 77 | double v[4]; 78 | struct { 79 | double e012; 80 | double e013; 81 | double e023; 82 | double e123; 83 | }; 84 | }; 85 | }; 86 | 87 | // ************************ 88 | // An abs takes a k-vector and returns a version with 89 | // absolute values of all the coordinates taken 90 | inline void abs(AbsExt4_1 &out, const Ext4_1 &in) { 91 | for(int i=0; i<4; i++) 92 | out.v[i] = fabs(in.v[i]); 93 | } 94 | inline void abs(AbsExt4_2 &out, const Ext4_2 &in) { 95 | for(int i=0; i<6; i++) 96 | out.v[i] = fabs(in.v[i]); 97 | } 98 | inline void abs(AbsExt4_3 &out, const Ext4_3 &in) { 99 | for(int i=0; i<4; i++) 100 | out.v[i] = fabs(in.v[i]); 101 | } 102 | 103 | 104 | // ************************ 105 | // A neg takes a k-vector and returns its negation 106 | // neg(X,Y) is safe for X=Y 107 | inline void neg(AbsExt4_1 &out, const AbsExt4_1 &in) { 108 | out = in; 109 | } 110 | inline void neg(AbsExt4_2 &out, const AbsExt4_2 &in) { 111 | out = in; 112 | } 113 | inline void neg(AbsExt4_3 &out, const AbsExt4_3 &in) { 114 | out = in; 115 | } 116 | 117 | 118 | // ************************ 119 | // A dual operation takes a k-vector and returns a (4-k)-vector 120 | // A reverse dual operation inverts the dual operation 121 | // dual(X,Y) is not safe for X=Y (same with revdual) 122 | inline void dual(AbsExt4_1 &out, const AbsExt4_3 &in) { 123 | out.e0 = in.e123; 124 | out.e1 = in.e023; 125 | out.e2 = in.e013; 126 | out.e3 = in.e012; 127 | } 128 | inline void dual(AbsExt4_2 &out, const AbsExt4_2 &in) { 129 | out.e01 = in.e23; 130 | out.e02 = in.e13; 131 | out.e03 = in.e12; 132 | out.e12 = in.e03; 133 | out.e13 = in.e02; 134 | out.e23 = in.e01; 135 | } 136 | inline void dual(AbsExt4_3 &out, const AbsExt4_1 &in) { 137 | out.e012 = in.e3; 138 | out.e013 = in.e2; 139 | out.e023 = in.e1; 140 | out.e123 = in.e0; 141 | } 142 | inline void revdual(AbsExt4_1 &out, const AbsExt4_3 &in) { 143 | out.e0 = in.e123; 144 | out.e1 = in.e023; 145 | out.e2 = in.e013; 146 | out.e3 = in.e012; 147 | } 148 | inline void revdual(AbsExt4_2 &out, const AbsExt4_2 &in) { 149 | out.e01 = in.e23; 150 | out.e02 = in.e13; 151 | out.e03 = in.e12; 152 | out.e12 = in.e03; 153 | out.e13 = in.e02; 154 | out.e23 = in.e01; 155 | } 156 | inline void revdual(AbsExt4_3 &out, const AbsExt4_1 &in) { 157 | out.e012 = in.e3; 158 | out.e013 = in.e2; 159 | out.e023 = in.e1; 160 | out.e123 = in.e0; 161 | } 162 | 163 | 164 | // ************************ 165 | // A join takes a j-vector and a k-vector and returns a (j+k)-vector 166 | inline void join(AbsExt4_2 &out, const AbsExt4_1 &lhs, const AbsExt4_1 &rhs) { 167 | out.e01 = (lhs.e0 * rhs.e1) + (rhs.e0 * lhs.e1); 168 | out.e02 = (lhs.e0 * rhs.e2) + (rhs.e0 * lhs.e2); 169 | out.e03 = (lhs.e0 * rhs.e3) + (rhs.e0 * lhs.e3); 170 | out.e12 = (lhs.e1 * rhs.e2) + (rhs.e1 * lhs.e2); 171 | out.e13 = (lhs.e1 * rhs.e3) + (rhs.e1 * lhs.e3); 172 | out.e23 = (lhs.e2 * rhs.e3) + (rhs.e2 * lhs.e3); 173 | } 174 | inline void join(AbsExt4_3 &out, const AbsExt4_2 &lhs, const AbsExt4_1 &rhs) { 175 | out.e012 = (lhs.e01 * rhs.e2) + (lhs.e02 * rhs.e1) + (lhs.e12 *rhs.e0); 176 | out.e013 = (lhs.e01 * rhs.e3) + (lhs.e03 * rhs.e1) + (lhs.e13 *rhs.e0); 177 | out.e023 = (lhs.e02 * rhs.e3) + (lhs.e03 * rhs.e2) + (lhs.e23 *rhs.e0); 178 | out.e123 = (lhs.e12 * rhs.e3) + (lhs.e13 * rhs.e2) + (lhs.e23 *rhs.e1); 179 | } 180 | inline void join(AbsExt4_3 &out, const AbsExt4_1 &lhs, const AbsExt4_2 &rhs) { 181 | join(out, rhs, lhs); 182 | } 183 | 184 | 185 | // ************************ 186 | // A meet takes a j-vector and a k-vector and returns a (j+k-4)-vector 187 | inline void meet(AbsExt4_2 &out, const AbsExt4_3 &lhs, const AbsExt4_3 &rhs) { 188 | AbsExt4_2 out_dual; 189 | AbsExt4_1 lhs_dual; 190 | AbsExt4_1 rhs_dual; 191 | dual(lhs_dual, lhs); 192 | dual(rhs_dual, rhs); 193 | join(out_dual, lhs_dual, rhs_dual); 194 | revdual(out, out_dual); 195 | } 196 | inline void meet(AbsExt4_1 &out, const AbsExt4_2 &lhs, const AbsExt4_3 &rhs) { 197 | AbsExt4_3 out_dual; 198 | AbsExt4_2 lhs_dual; 199 | AbsExt4_1 rhs_dual; 200 | dual(lhs_dual, lhs); 201 | dual(rhs_dual, rhs); 202 | join(out_dual, lhs_dual, rhs_dual); 203 | revdual(out, out_dual); 204 | } 205 | inline void meet(AbsExt4_1 &out, const AbsExt4_3 &lhs, const AbsExt4_2 &rhs) { 206 | AbsExt4_3 out_dual; 207 | AbsExt4_1 lhs_dual; 208 | AbsExt4_2 rhs_dual; 209 | dual(lhs_dual, lhs); 210 | dual(rhs_dual, rhs); 211 | join(out_dual, lhs_dual, rhs_dual); 212 | revdual(out, out_dual); 213 | } 214 | 215 | 216 | // ************************ 217 | // An inner product takes two k-vectors and produces a single number 218 | inline double inner(const AbsExt4_1 &lhs, const AbsExt4_1 &rhs) { 219 | double acc = 0.0; 220 | for(int i=0; i<4; i++) 221 | acc += lhs.v[i] * rhs.v[i]; 222 | return acc; 223 | } 224 | inline double inner(const AbsExt4_2 &lhs, const AbsExt4_2 &rhs) { 225 | double acc = 0.0; 226 | for(int i=0; i<6; i++) 227 | acc += lhs.v[i] * rhs.v[i]; 228 | return acc; 229 | } 230 | inline double inner(const AbsExt4_3 &lhs, const AbsExt4_3 &rhs) { 231 | double acc = 0.0; 232 | for(int i=0; i<4; i++) 233 | acc += lhs.v[i] * rhs.v[i]; 234 | return acc; 235 | } 236 | 237 | 238 | 239 | 240 | } // end namespace AbsExt4 241 | 242 | 243 | -------------------------------------------------------------------------------- /src/isct/empty3d.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | empty3d.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include "vec.h" 29 | 30 | namespace Empty3d { 31 | 32 | struct TriIn 33 | { 34 | Vec3d p[3]; 35 | }; 36 | 37 | struct EdgeIn 38 | { 39 | Vec3d p[2]; 40 | }; 41 | 42 | 43 | 44 | struct TriEdgeIn 45 | { 46 | TriIn tri; 47 | EdgeIn edge; 48 | }; 49 | bool isEmpty(const TriEdgeIn &input); 50 | Vec3d coords(const TriEdgeIn &input); 51 | bool emptyExact(const TriEdgeIn &input); 52 | Vec3d coordsExact(const TriEdgeIn &input); 53 | 54 | struct TriTriTriIn 55 | { 56 | TriIn tri[3]; 57 | }; 58 | bool isEmpty(const TriTriTriIn &input); 59 | Vec3d coords(const TriTriTriIn &input); 60 | bool emptyExact(const TriTriTriIn &input); 61 | Vec3d coordsExact(const TriTriTriIn &input); 62 | 63 | extern int degeneracy_count; // count degeneracies encountered 64 | extern int exact_count; // count of filter calls failed 65 | extern int callcount; // total call count 66 | 67 | /* 68 | // exact versions 69 | 70 | 71 | bool emptyExact(const Cell3d0 &c0, 72 | const Complex3d2 &complex, 73 | const Metric3d2 &metric); 74 | 75 | void cell3d0toPointExact(SmVector3 &point, 76 | const Cell3d0 &c0, 77 | const Complex3d2 &complex, 78 | const Metric3d2 &metric); 79 | */ 80 | } // end namespace Empty3d 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/isct/ext4.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | ext4.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | /* 29 | * 30 | * Ext4 31 | * 32 | * Support for performing exterior calculus in R4 33 | * 34 | */ 35 | 36 | namespace Ext4 { 37 | 38 | // types for k-vectors in R4: 39 | // Ext4_k 40 | 41 | struct Ext4_1 { 42 | union { 43 | double v[4]; 44 | struct { 45 | double e0; 46 | double e1; 47 | double e2; 48 | double e3; 49 | }; 50 | }; 51 | }; 52 | 53 | struct Ext4_2 { 54 | union { 55 | double v[6]; 56 | struct { 57 | double e01; 58 | double e02; 59 | double e03; 60 | double e12; 61 | double e13; 62 | double e23; 63 | }; 64 | }; 65 | }; 66 | 67 | struct Ext4_3 { 68 | union { 69 | double v[4]; 70 | struct { 71 | double e012; 72 | double e013; 73 | double e023; 74 | double e123; 75 | }; 76 | }; 77 | }; 78 | 79 | // ************************ 80 | // Output routines 81 | 82 | // NONE CURRENTLY 83 | 84 | 85 | // ************************ 86 | // A neg takes a k-vector and returns its negation 87 | // neg(X,Y) is safe for X=Y 88 | inline void neg(Ext4_1 &out, const Ext4_1 &in) { 89 | for(int i=0; i<4; i++) 90 | out.v[i] = -in.v[i]; 91 | } 92 | inline void neg(Ext4_2 &out, const Ext4_2 &in) { 93 | for(int i=0; i<6; i++) 94 | out.v[i] = -in.v[i]; 95 | } 96 | inline void neg(Ext4_3 &out, const Ext4_3 &in) { 97 | for(int i=0; i<4; i++) 98 | out.v[i] = -in.v[i]; 99 | } 100 | 101 | 102 | // ************************ 103 | // A dual operation takes a k-vector and returns a (4-k)-vector 104 | // A reverse dual operation inverts the dual operation 105 | // dual(X,Y) is not safe for X=Y (same with revdual) 106 | inline void dual(Ext4_1 &out, const Ext4_3 &in) { 107 | out.e0 = in.e123; 108 | out.e1 = -in.e023; 109 | out.e2 = in.e013; 110 | out.e3 = -in.e012; 111 | } 112 | inline void dual(Ext4_2 &out, const Ext4_2 &in) { 113 | out.e01 = in.e23; 114 | out.e02 = -in.e13; 115 | out.e03 = in.e12; 116 | out.e12 = in.e03; 117 | out.e13 = -in.e02; 118 | out.e23 = in.e01; 119 | } 120 | inline void dual(Ext4_3 &out, const Ext4_1 &in) { 121 | out.e012 = in.e3; 122 | out.e013 = -in.e2; 123 | out.e023 = in.e1; 124 | out.e123 = -in.e0; 125 | } 126 | inline void revdual(Ext4_1 &out, const Ext4_3 &in) { 127 | out.e0 = -in.e123; 128 | out.e1 = in.e023; 129 | out.e2 = -in.e013; 130 | out.e3 = in.e012; 131 | } 132 | inline void revdual(Ext4_2 &out, const Ext4_2 &in) { 133 | out.e01 = in.e23; 134 | out.e02 = -in.e13; 135 | out.e03 = in.e12; 136 | out.e12 = in.e03; 137 | out.e13 = -in.e02; 138 | out.e23 = in.e01; 139 | } 140 | inline void revdual(Ext4_3 &out, const Ext4_1 &in) { 141 | out.e012 = -in.e3; 142 | out.e013 = in.e2; 143 | out.e023 = -in.e1; 144 | out.e123 = in.e0; 145 | } 146 | 147 | 148 | // ************************ 149 | // A join takes a j-vector and a k-vector and returns a (j+k)-vector 150 | inline void join(Ext4_2 &out, const Ext4_1 &lhs, const Ext4_1 &rhs) { 151 | out.e01 = (lhs.e0 * rhs.e1) - (rhs.e0 * lhs.e1); 152 | out.e02 = (lhs.e0 * rhs.e2) - (rhs.e0 * lhs.e2); 153 | out.e03 = (lhs.e0 * rhs.e3) - (rhs.e0 * lhs.e3); 154 | out.e12 = (lhs.e1 * rhs.e2) - (rhs.e1 * lhs.e2); 155 | out.e13 = (lhs.e1 * rhs.e3) - (rhs.e1 * lhs.e3); 156 | out.e23 = (lhs.e2 * rhs.e3) - (rhs.e2 * lhs.e3); 157 | } 158 | inline void join(Ext4_3 &out, const Ext4_2 &lhs, const Ext4_1 &rhs) { 159 | out.e012 = (lhs.e01 * rhs.e2) - (lhs.e02 * rhs.e1) + (lhs.e12 *rhs.e0); 160 | out.e013 = (lhs.e01 * rhs.e3) - (lhs.e03 * rhs.e1) + (lhs.e13 *rhs.e0); 161 | out.e023 = (lhs.e02 * rhs.e3) - (lhs.e03 * rhs.e2) + (lhs.e23 *rhs.e0); 162 | out.e123 = (lhs.e12 * rhs.e3) - (lhs.e13 * rhs.e2) + (lhs.e23 *rhs.e1); 163 | } 164 | inline void join(Ext4_3 &out, const Ext4_1 &lhs, const Ext4_2 &rhs) { 165 | join(out, rhs, lhs); 166 | // no negation since swapping the arguments requires two 167 | // swaps of 1-vectors 168 | } 169 | 170 | 171 | // ************************ 172 | // A meet takes a j-vector and a k-vector and returns a (j+k-4)-vector 173 | inline void meet(Ext4_2 &out, const Ext4_3 &lhs, const Ext4_3 &rhs) { 174 | Ext4_2 out_dual; 175 | Ext4_1 lhs_dual; 176 | Ext4_1 rhs_dual; 177 | dual(lhs_dual, lhs); 178 | dual(rhs_dual, rhs); 179 | join(out_dual, lhs_dual, rhs_dual); 180 | revdual(out, out_dual); 181 | } 182 | inline void meet(Ext4_1 &out, const Ext4_2 &lhs, const Ext4_3 &rhs) { 183 | Ext4_3 out_dual; 184 | Ext4_2 lhs_dual; 185 | Ext4_1 rhs_dual; 186 | dual(lhs_dual, lhs); 187 | dual(rhs_dual, rhs); 188 | join(out_dual, lhs_dual, rhs_dual); 189 | revdual(out, out_dual); 190 | } 191 | inline void meet(Ext4_1 &out, const Ext4_3 &lhs, const Ext4_2 &rhs) { 192 | Ext4_3 out_dual; 193 | Ext4_1 lhs_dual; 194 | Ext4_2 rhs_dual; 195 | dual(lhs_dual, lhs); 196 | dual(rhs_dual, rhs); 197 | join(out_dual, lhs_dual, rhs_dual); 198 | revdual(out, out_dual); 199 | } 200 | 201 | 202 | // ************************ 203 | // An inner product takes two k-vectors and produces a single number 204 | inline double inner(const Ext4_1 &lhs, const Ext4_1 &rhs) { 205 | double acc = 0.0; 206 | for(int i=0; i<4; i++) 207 | acc += lhs.v[i] * rhs.v[i]; 208 | return acc; 209 | } 210 | inline double inner(const Ext4_2 &lhs, const Ext4_2 &rhs) { 211 | double acc = 0.0; 212 | for(int i=0; i<6; i++) 213 | acc += lhs.v[i] * rhs.v[i]; 214 | return acc; 215 | } 216 | inline double inner(const Ext4_3 &lhs, const Ext4_3 &rhs) { 217 | double acc = 0.0; 218 | for(int i=0; i<4; i++) 219 | acc += lhs.v[i] * rhs.v[i]; 220 | return acc; 221 | } 222 | 223 | 224 | } 225 | 226 | -------------------------------------------------------------------------------- /src/isct/fixext4.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | fixext4.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | /* 29 | * 30 | * FixExt4 31 | * 32 | * Support for performing exterior calculus in R4 33 | * 34 | */ 35 | 36 | //#include 37 | //using std::cout; 38 | //using std::endl; 39 | #include 40 | 41 | 42 | #include "fixint.h" 43 | 44 | namespace FixExt4 { 45 | 46 | using namespace FixInt; 47 | 48 | // types for k-vectors in R4: 49 | // Ext4_k 50 | 51 | template 52 | struct FixExt4_1 { 53 | typename BitInt::Rep e0; 54 | typename BitInt::Rep e1; 55 | typename BitInt::Rep e2; 56 | typename BitInt::Rep e3; 57 | }; 58 | 59 | template 60 | struct FixExt4_2 { 61 | typename BitInt::Rep e01; 62 | typename BitInt::Rep e02; 63 | typename BitInt::Rep e03; 64 | typename BitInt::Rep e12; 65 | typename BitInt::Rep e13; 66 | typename BitInt::Rep e23; 67 | }; 68 | 69 | template 70 | struct FixExt4_3 { 71 | typename BitInt::Rep e012; 72 | typename BitInt::Rep e013; 73 | typename BitInt::Rep e023; 74 | typename BitInt::Rep e123; 75 | }; 76 | 77 | 78 | // ******************************** 79 | // Output Routines 80 | template 81 | std::ostream& operator<<(std::ostream &out, const FixExt4_1 &ext) 82 | { 83 | return out << '[' << toString(ext.e0) 84 | << ',' << toString(ext.e1) 85 | << ',' << toString(ext.e2) 86 | << ',' << toString(ext.e3) << ']'; 87 | } 88 | template 89 | std::ostream& operator<<(std::ostream &out, const FixExt4_2 &ext) 90 | { 91 | return out << '[' << toString(ext.e01) 92 | << ',' << toString(ext.e02) 93 | << ',' << toString(ext.e03) 94 | << ',' << toString(ext.e12) 95 | << ',' << toString(ext.e13) 96 | << ',' << toString(ext.e23) << ']'; 97 | } 98 | template 99 | std::ostream& operator<<(std::ostream &out, const FixExt4_3 &ext) 100 | { 101 | return out << '[' << toString(ext.e012) 102 | << ',' << toString(ext.e013) 103 | << ',' << toString(ext.e023) 104 | << ',' << toString(ext.e123) << ']'; 105 | } 106 | 107 | 108 | // ******************************** 109 | // A neg takes a k-vector and returns its negation 110 | // neg(X,Y) is safe for X=Y 111 | template inline 112 | void neg(FixExt4_1 &out, const FixExt4_1 &in) 113 | { 114 | neg(out.e0, in.e0); 115 | neg(out.e1, in.e1); 116 | neg(out.e2, in.e2); 117 | neg(out.e3, in.e3); 118 | } 119 | template inline 120 | void neg(FixExt4_2 &out, const FixExt4_2 &in) 121 | { 122 | neg(out.e01, in.e01); 123 | neg(out.e02, in.e02); 124 | neg(out.e03, in.e03); 125 | neg(out.e12, in.e12); 126 | neg(out.e13, in.e13); 127 | neg(out.e23, in.e23); 128 | } 129 | template inline 130 | void neg(FixExt4_3 &out, const FixExt4_3 &in) 131 | { 132 | neg(out.e012, in.e012); 133 | neg(out.e013, in.e013); 134 | neg(out.e023, in.e023); 135 | neg(out.e123, in.e123); 136 | } 137 | 138 | 139 | // ******************************** 140 | // A dual operation takes a k-vector and returns a (4-k)-vector 141 | // A reverse dual operation inverts the dual operation 142 | // dual(X,Y) is not safe for X=Y (same with revdual) 143 | template inline 144 | void dual(FixExt4_1 &out, const FixExt4_3 &in) 145 | { 146 | out.e0 = in.e123; 147 | neg(out.e1, in.e023); 148 | out.e2 = in.e013; 149 | neg(out.e3, in.e012); 150 | } 151 | template inline 152 | void dual(FixExt4_2 &out, const FixExt4_2 &in) 153 | { 154 | out.e01 = in.e23; 155 | neg(out.e02, in.e13); 156 | out.e03 = in.e12; 157 | out.e12 = in.e03; 158 | neg(out.e13, in.e02); 159 | out.e23 = in.e01; 160 | } 161 | template inline 162 | void dual(FixExt4_3 &out, const FixExt4_1 &in) 163 | { 164 | out.e012 = in.e3; 165 | neg(out.e013, in.e2); 166 | out.e023 = in.e1; 167 | neg(out.e123, in.e0); 168 | } 169 | template inline 170 | void revdual(FixExt4_1 &out, const FixExt4_3 &in) 171 | { 172 | neg(out.e0, in.e123); 173 | out.e1 = in.e023; 174 | neg(out.e2, in.e013); 175 | out.e3 = in.e012; 176 | } 177 | template inline 178 | void revdual(FixExt4_2 &out, const FixExt4_2 &in) 179 | { 180 | out.e01 = in.e23; 181 | neg(out.e02, in.e13); 182 | out.e03 = in.e12; 183 | out.e12 = in.e03; 184 | neg(out.e13, in.e02); 185 | out.e23 = in.e01; 186 | } 187 | template inline 188 | void revdual(FixExt4_3 &out, const FixExt4_1 &in) 189 | { 190 | neg(out.e012, in.e3); 191 | out.e013 = in.e2; 192 | neg(out.e023, in.e1); 193 | out.e123 = in.e0; 194 | } 195 | 196 | 197 | // ******************************** 198 | // A join takes a j-vector and a k-vector and returns a (j+k)-vector 199 | template inline 200 | void join(FixExt4_2<(Nlhs + Nrhs + 1)> &out, 201 | const FixExt4_1 &lhs, 202 | const FixExt4_1 &rhs) 203 | { 204 | typename BitInt<(Nlhs + Nrhs)>::Rep a; 205 | typename BitInt<(Nlhs + Nrhs)>::Rep b; 206 | mul(a, lhs.e0, rhs.e1); mul(b, rhs.e0, lhs.e1); 207 | //cout << "a/b limbs: " << BITS_TO_LIMBS(Nlhs+Nrhs) << endl; 208 | //cout << "out bits: " << BITS_TO_LIMBS(Nlhs+Nrhs+1) << endl; 209 | //cout << "a,b: " << toString(a) << ',' << toString(b) << endl; 210 | sub(out.e01, a, b); 211 | mul(a, lhs.e0, rhs.e2); mul(b, rhs.e0, lhs.e2); 212 | sub(out.e02, a, b); 213 | mul(a, lhs.e0, rhs.e3); mul(b, rhs.e0, lhs.e3); 214 | sub(out.e03, a, b); 215 | mul(a, lhs.e1, rhs.e2); mul(b, rhs.e1, lhs.e2); 216 | sub(out.e12, a, b); 217 | mul(a, lhs.e1, rhs.e3); mul(b, rhs.e1, lhs.e3); 218 | sub(out.e13, a, b); 219 | mul(a, lhs.e2, rhs.e3); mul(b, rhs.e2, lhs.e3); 220 | sub(out.e23, a, b); 221 | } 222 | template inline 223 | void join(FixExt4_3<(Nlhs + Nrhs + 2)> &out, 224 | const FixExt4_2 &lhs, 225 | const FixExt4_1 &rhs) 226 | { 227 | typename BitInt<(Nlhs + Nrhs)>::Rep a; 228 | typename BitInt<(Nlhs + Nrhs)>::Rep b; 229 | typename BitInt<(Nlhs + Nrhs)>::Rep c; 230 | typename BitInt<(Nlhs + Nrhs + 1)>::Rep x; 231 | //cout << "Nlhs: " << Nlhs << " Nrhs: " << Nrhs << endl; 232 | mul(a, lhs.e01, rhs.e2); mul(b, lhs.e02, rhs.e1); mul(c, lhs.e12, rhs.e0); 233 | //cout << "a,b,c: " << toString(a) << ',' 234 | // << toString(b) << ',' << toString(c) << endl; 235 | sub(x, a, b); add(out.e012, x, c); 236 | mul(a, lhs.e01, rhs.e3); mul(b, lhs.e03, rhs.e1); mul(c, lhs.e13, rhs.e0); 237 | //cout << "a,b,c: " << toString(a) << ',' 238 | // << toString(b) << ',' << toString(c) << endl; 239 | sub(x, a, b); add(out.e013, x, c); 240 | mul(a, lhs.e02, rhs.e3); mul(b, lhs.e03, rhs.e2); mul(c, lhs.e23, rhs.e0); 241 | //cout << "a,b,c: " << toString(a) << ',' 242 | // << toString(b) << ',' << toString(c) << endl; 243 | sub(x, a, b); add(out.e023, x, c); 244 | mul(a, lhs.e12, rhs.e3); mul(b, lhs.e13, rhs.e2); mul(c, lhs.e23, rhs.e1); 245 | //cout << "a,b,c: " << toString(a) << ',' 246 | // << toString(b) << ',' << toString(c) << endl; 247 | sub(x, a, b); add(out.e123, x, c); 248 | } 249 | template inline 250 | void join(FixExt4_3<(Nlhs + Nrhs + 2)> &out, 251 | const FixExt4_1 &lhs, 252 | const FixExt4_2 &rhs) 253 | { 254 | join(out, rhs, lhs); 255 | // no negation since swapping the arguments requires two 256 | // swaps of 1-vectors 257 | } 258 | 259 | 260 | // ******************************** 261 | // A meet takes a j-vector and a k-vector and returns a (j+k-4)-vector 262 | template inline 263 | void meet(FixExt4_2<(Nlhs + Nrhs + 1)> &out, 264 | const FixExt4_3 &lhs, 265 | const FixExt4_3 &rhs) 266 | { 267 | FixExt4_2<(Nlhs + Nrhs + 1)> out_dual; 268 | FixExt4_1 lhs_dual; 269 | FixExt4_1 rhs_dual; 270 | dual(lhs_dual, lhs); 271 | dual(rhs_dual, rhs); 272 | join(out_dual, lhs_dual, rhs_dual); 273 | revdual(out, out_dual); 274 | } 275 | template inline 276 | void meet(FixExt4_1<(Nlhs + Nrhs + 2)> &out, 277 | const FixExt4_2 &lhs, 278 | const FixExt4_3 &rhs) 279 | { 280 | FixExt4_3<(Nlhs + Nrhs + 2)> out_dual; 281 | FixExt4_2 lhs_dual; 282 | FixExt4_1 rhs_dual; 283 | dual(lhs_dual, lhs); 284 | dual(rhs_dual, rhs); 285 | join(out_dual, lhs_dual, rhs_dual); 286 | revdual(out, out_dual); 287 | } 288 | template inline 289 | void meet(FixExt4_1<(Nlhs + Nrhs + 2)> &out, 290 | const FixExt4_3 &lhs, 291 | const FixExt4_2 &rhs) 292 | { 293 | FixExt4_3<(Nlhs + Nrhs + 2)> out_dual; 294 | FixExt4_1 lhs_dual; 295 | FixExt4_2 rhs_dual; 296 | dual(lhs_dual, lhs); 297 | dual(rhs_dual, rhs); 298 | join(out_dual, lhs_dual, rhs_dual); 299 | revdual(out, out_dual); 300 | } 301 | 302 | 303 | // ******************************** 304 | // An inner product takes two k-vectors and produces a single number 305 | template inline 306 | void inner(typename BitInt<(Nlhs + Nrhs + 2)>::Rep &out, 307 | const FixExt4_1 &lhs, 308 | const FixExt4_1 &rhs) 309 | { 310 | typename BitInt<(Nlhs + Nrhs)>::Rep p0; mul(p0, lhs.e0, rhs.e0); 311 | typename BitInt<(Nlhs + Nrhs)>::Rep p1; mul(p1, lhs.e1, rhs.e1); 312 | typename BitInt<(Nlhs + Nrhs)>::Rep p2; mul(p2, lhs.e2, rhs.e2); 313 | typename BitInt<(Nlhs + Nrhs)>::Rep p3; mul(p3, lhs.e3, rhs.e3); 314 | typename BitInt<(Nlhs + Nrhs + 1)>::Rep a; add(a, p0, p1); 315 | typename BitInt<(Nlhs + Nrhs + 1)>::Rep b; add(b, p2, p3); 316 | add(out, a, b); 317 | } 318 | template inline 319 | void inner(typename BitInt<(Nlhs + Nrhs + 3)>::Rep &out, 320 | const FixExt4_2 &lhs, 321 | const FixExt4_2 &rhs) 322 | { 323 | typename BitInt<(Nlhs + Nrhs)>::Rep p0; mul(p0, lhs.e01, rhs.e01); 324 | typename BitInt<(Nlhs + Nrhs)>::Rep p1; mul(p1, lhs.e02, rhs.e02); 325 | typename BitInt<(Nlhs + Nrhs)>::Rep p2; mul(p2, lhs.e03, rhs.e03); 326 | typename BitInt<(Nlhs + Nrhs)>::Rep p3; mul(p3, lhs.e12, rhs.e12); 327 | typename BitInt<(Nlhs + Nrhs)>::Rep p4; mul(p4, lhs.e13, rhs.e13); 328 | typename BitInt<(Nlhs + Nrhs)>::Rep p5; mul(p5, lhs.e23, rhs.e23); 329 | typename BitInt<(Nlhs + Nrhs + 1)>::Rep a; add(a, p0, p1); 330 | typename BitInt<(Nlhs + Nrhs + 1)>::Rep b; add(b, p2, p3); 331 | typename BitInt<(Nlhs + Nrhs + 1)>::Rep c; add(c, p4, p5); 332 | typename BitInt<(Nlhs + Nrhs + 2)>::Rep x; add(x, a, b); 333 | add(out, x, c); 334 | } 335 | template inline 336 | void inner(typename BitInt<(Nlhs + Nrhs + 2)>::Rep &out, 337 | const FixExt4_3 &lhs, 338 | const FixExt4_3 &rhs) 339 | { 340 | typename BitInt<(Nlhs + Nrhs)>::Rep p0; mul(p0, lhs.e012, rhs.e012); 341 | typename BitInt<(Nlhs + Nrhs)>::Rep p1; mul(p1, lhs.e013, rhs.e013); 342 | typename BitInt<(Nlhs + Nrhs)>::Rep p2; mul(p2, lhs.e023, rhs.e023); 343 | typename BitInt<(Nlhs + Nrhs)>::Rep p3; mul(p3, lhs.e123, rhs.e123); 344 | typename BitInt<(Nlhs + Nrhs + 1)>::Rep a; add(a, p0, p1); 345 | typename BitInt<(Nlhs + Nrhs + 1)>::Rep b; add(b, p2, p3); 346 | add(out, a, b); 347 | } 348 | 349 | 350 | 351 | 352 | 353 | 354 | } // end namespace FixExt4 355 | 356 | -------------------------------------------------------------------------------- /src/isct/fixint.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | fixint.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | /* 29 | * 30 | * fixint.H 31 | * 32 | * Support for known size big integers 33 | * 34 | * See the BitInt wrapper class towards the end of the file 35 | * for the type you want to use. Specifically you want to declare 36 | * 37 | * BitInt<128>::Rep myInt; 38 | * 39 | * to get an integer guaranteed to hold at least 128 bits. 40 | * Provided the size of all integers used in this fashion 41 | * is declared appropriately, the template magic will 42 | * statically decide which specialized function to call. 43 | * 44 | */ 45 | 46 | 47 | 48 | #ifdef _WIN32 49 | #include 50 | #else 51 | #include 52 | #endif 53 | 54 | #include 55 | #include 56 | #include 57 | 58 | namespace FixInt { 59 | 60 | // static assertion using templates. Usage: 61 | // ASSERT_STATIC< expr_to_assert >::test(); 62 | template 63 | struct ASSERT_STATIC {}; 64 | template<> 65 | struct ASSERT_STATIC { static void test() {}; }; 66 | 67 | 68 | const static unsigned int LIMB_BIT_SIZE = GMP_NUMB_BITS; 69 | const static unsigned int SIGN_BIT_OFFSET = LIMB_BIT_SIZE-1; 70 | // mask defining the position of the sign bit in a limb 71 | #define LIMB_SIGN_MASK (mp_limb_t(1) << SIGN_BIT_OFFSET) 72 | // function which tests sign and returns 1 if it's set; 0 otherwise 73 | #define SIGN_BOOL(limbs,n) \ 74 | (((limbs)[(n)-1] & LIMB_SIGN_MASK) >> SIGN_BIT_OFFSET) 75 | // function which tests sign and returns -1 if it's set; 1 otherwise 76 | #define SIGN_INT(limbs,n) (((limbs)[(n)-1] & LIMB_SIGN_MASK)? -1 : 1) 77 | // pattern of all 1s filling up a limb 78 | #define ONES_PATTERN (mp_limb_t(-1)) 79 | #define ZERO_PATTERN (mp_limb_t(0)) 80 | // function which tests sign and returns 81 | #define SIGN_LIMB(limbs,n) (((limbs)[(n)-1] & LIMB_SIGN_MASK)? \ 82 | ONES_PATTERN : ZERO_PATTERN) 83 | #define BITS_TO_LIMBS(n) ((((n)-1)/ LIMB_BIT_SIZE)+1) 84 | 85 | template 86 | class LimbInt { 87 | public: 88 | mp_limb_t limbs[Nlimbs]; 89 | 90 | inline LimbInt(int init) { 91 | ASSERT_STATIC<(sizeof(int) <= sizeof(mp_limb_t))>::test(); 92 | limbs[0] = init; 93 | if(Nlimbs > 1) { 94 | mp_limb_t fill = SIGN_LIMB(limbs,1); 95 | for(int i=1; i 104 | std::ostream& operator<<(std::ostream &out, const LimbInt &num) 105 | { 106 | out << "[" << std::hex << num.limbs[0]; 107 | for(int k=0; k 115 | inline void promote(LimbInt &out, const LimbInt &in) 116 | { 117 | ASSERT_STATIC<(Nout >= Nin)>::test(); 118 | 119 | mpn_copyi(out.limbs, in.limbs, Nin); 120 | 121 | if(Nout > Nin) { // fill out the higher order bits... 122 | mp_limb_t fill = SIGN_LIMB(out.limbs, Nin); 123 | for(int i=Nin; i 130 | inline void add(LimbInt &out, 131 | const LimbInt &lhs, 132 | const LimbInt &rhs) 133 | { 134 | ASSERT_STATIC<(Nout >= Nlhs && Nout >= Nrhs)>::test(); 135 | int Nmax = Nlhs; 136 | if(Nrhs > Nlhs) Nmax = Nrhs; 137 | mp_limb_t carry; 138 | 139 | if(Nlhs == Nrhs) { 140 | carry = mpn_add_n(out.limbs, lhs.limbs, rhs.limbs, Nlhs); 141 | } else if(Nlhs > Nrhs) { 142 | mp_limb_t rhs_is_neg = SIGN_BOOL(rhs.limbs, Nrhs); 143 | carry = mpn_add(out.limbs, lhs.limbs, Nlhs, rhs.limbs, Nrhs); 144 | mp_limb_t borrow = mpn_sub_1(out.limbs+Nrhs, 145 | out.limbs+Nrhs, Nlhs-Nrhs, 146 | rhs_is_neg); 147 | if(Nout > Nmax) carry = carry | (mp_limb_t(1) - borrow); 148 | } else { // Nrhs > Nlhs 149 | mp_limb_t lhs_is_neg = SIGN_BOOL(lhs.limbs, Nlhs); 150 | carry = mpn_add(out.limbs, rhs.limbs, Nrhs, lhs.limbs, Nlhs); 151 | mp_limb_t borrow = mpn_sub_1(out.limbs+Nlhs, 152 | out.limbs+Nlhs, Nrhs-Nlhs, 153 | lhs_is_neg); 154 | if(Nout > Nmax) carry = carry | (mp_limb_t(1) - borrow); 155 | } 156 | 157 | // fill out any new higher order bits 158 | if(Nout > Nmax) { 159 | mp_limb_t rhs_is_neg = SIGN_BOOL(rhs.limbs, Nrhs); 160 | mp_limb_t lhs_is_neg = SIGN_BOOL(lhs.limbs, Nlhs); 161 | mp_limb_t fill_bit = rhs_is_neg ^ lhs_is_neg ^ carry; 162 | mp_limb_t fill = (fill_bit)? ONES_PATTERN : ZERO_PATTERN; 163 | for(int i=Nmax; i 169 | inline void sub(LimbInt &out, 170 | const LimbInt &lhs, 171 | const LimbInt &rhs) 172 | { 173 | // for testing... 174 | LimbInt tempright; 175 | mpn_neg(tempright.limbs, rhs.limbs, Nrhs); 176 | add(out, lhs, tempright); 177 | /*ASSERT_STATIC<(Nout >= Nlhs && Nout >= Nrhs)>::test(); 178 | const mp_limb_t *left = lhs.limbs; 179 | const mp_limb_t *right = rhs.limbs; 180 | int Nleft = Nlhs; 181 | int Nright = Nrhs; 182 | if(Nrhs > Nlhs) { 183 | const mp_limb_t *temp = left; left = right; right = temp; 184 | int tempi = Nleft; Nleft = Nright; Nright = tempi; 185 | } 186 | 187 | mpn_copyi(out.limbs, left, Nleft); 188 | if(Nout != Nleft) { // make sure higher order limbs are filled 189 | mp_limb_t fill = SIGN_LIMB(left, Nleft); 190 | for(int i=Nleft; i= Nlhs && Nout >= Nrhs)>::test(); 202 | int Nmax = Nlhs; 203 | if(Nrhs > Nlhs) Nmax = Nrhs; 204 | mp_limb_t carry; 205 | 206 | if(Nlhs == Nrhs) { 207 | carry = mpn_add_n(out.limbs, lhs.limbs, rhs.limbs, Nlhs); 208 | } else if(Nlhs > Nrhs) { 209 | mp_limb_t rhs_is_neg = SIGN_BOOL(rhs.limbs, Nrhs); 210 | carry = mpn_add(out.limbs, lhs.limbs, Nlhs, rhs.limbs, Nrhs); 211 | mp_limb_t borrow = mpn_sub_1(out.limbs+Nrhs, 212 | out.limbs+Nrhs, Nlhs-Nrhs, 213 | rhs_is_neg); 214 | if(Nout > Nmax) carry = carry | (mp_limb_t(1) - borrow); 215 | } else { // Nrhs > Nlhs 216 | mp_limb_t lhs_is_neg = SIGN_BOOL(lhs.limbs, Nlhs); 217 | carry = mpn_add(out.limbs, rhs.limbs, Nrhs, lhs.limbs, Nlhs); 218 | mp_limb_t borrow = mpn_sub_1(out.limbs+Nlhs, 219 | out.limbs+Nlhs, Nrhs-Nlhs, 220 | lhs_is_neg); 221 | if(Nout > Nmax) carry = carry | (mp_limb_t(1) - borrow); 222 | } 223 | 224 | // fill out any new higher order bits (DOES THIS HAVE TO USE THE CARRY?) 225 | if(Nout > Nmax) { 226 | mp_limb_t rhs_is_neg = SIGN_BOOL(rhs.limbs, Nrhs); 227 | mp_limb_t lhs_is_neg = SIGN_BOOL(lhs.limbs, Nlhs); 228 | mp_limb_t fill_bit = rhs_is_neg ^ lhs_is_neg ^ carry; 229 | mp_limb_t fill = -fill_bit; 230 | for(int i=Nmax; i 239 | inline void neg(LimbInt &out, 240 | const LimbInt &in) 241 | { 242 | ASSERT_STATIC<(Nout >= Nin)>::test(); 243 | 244 | mpn_neg(out.limbs, in.limbs, Nin); 245 | 246 | if(Nout > Nin) { 247 | mp_limb_t fill = SIGN_LIMB(out.limbs, Nin); 248 | for(int i=Nin; i 254 | inline void mul(LimbInt &out, 255 | const LimbInt &lhs, 256 | const LimbInt &rhs) 257 | { 258 | ASSERT_STATIC<(Nout >= Nlhs && Nout >= Nrhs)>::test(); 259 | // handle the possibility that we need to use more space 260 | // than we have... 261 | mp_limb_t *res = out.limbs; 262 | LimbInt tempresult; 263 | if(Nout < Nlhs + Nrhs) 264 | res = tempresult.limbs; 265 | 266 | // multiply 267 | if(Nlhs == Nrhs) 268 | mpn_mul_n(res, lhs.limbs, rhs.limbs, Nlhs); 269 | else if(Nlhs > Nrhs) 270 | mpn_mul(res, lhs.limbs, Nlhs, rhs.limbs, Nrhs); 271 | else // need to flip in order to satisfy calling condition... 272 | mpn_mul(res, rhs.limbs, Nrhs, lhs.limbs, Nlhs); 273 | 274 | mp_limb_t lhs_sign = SIGN_BOOL(lhs.limbs,Nlhs); 275 | mp_limb_t rhs_sign = SIGN_BOOL(rhs.limbs,Nrhs); 276 | 277 | mpn_submul_1((res+Nlhs), rhs.limbs, Nrhs, lhs_sign); 278 | mpn_submul_1((res+Nrhs), lhs.limbs, Nlhs, rhs_sign); 279 | 280 | // transfer large result if we had one... 281 | if(Nout < Nlhs + Nrhs) 282 | mpn_copyi(out.limbs, res, Nout); 283 | 284 | // if we have more limbs than needed for the multiply, 285 | // fill out the extra higher order limbs... 286 | if(Nout > Nlhs + Nrhs) { 287 | mp_limb_t fill = SIGN_LIMB(out.limbs, Nlhs+Nrhs); 288 | for(int i=Nlhs+Nrhs; i 294 | inline 295 | int sign(const LimbInt &in) 296 | { 297 | bool nonzero = false; 298 | for(int i=0; i 306 | //inline 307 | //double approximate(const LimbInt &in) 308 | //{ 309 | // std::cout << in << std::endl; 310 | // // not the most efficient implementation, but it should work 311 | // LimbInt tmp; 312 | // double sign; 313 | // if(SIGN_BOOL(in.limbs, N-1)) { 314 | // neg(tmp, in); 315 | // sign = -1.0; 316 | // } else { 317 | // tmp = in; 318 | // sign = 1.0; 319 | // } 320 | // std::cout << tmp << std::endl; 321 | // std::cout << typeid(mp_limb_t).name() << std::endl; 322 | // std::cout << double(in.limbs[2]) << std::endl; 323 | // double result = 0.0; 324 | // for(int i=0; i 331 | inline 332 | std::string toString(const LimbInt &num) 333 | { 334 | char cbuf[(N*LIMB_BIT_SIZE*3)/10 + 3]; 335 | LimbInt garbage = num; 336 | bool neg = SIGN_BOOL(num.limbs,N); 337 | if(neg) 338 | mpn_neg(garbage.limbs, garbage.limbs, N); 339 | 340 | int count = mpn_get_str(reinterpret_cast(cbuf), 341 | 10, garbage.limbs, N); 342 | 343 | std::string result = ""; 344 | 345 | if(neg) result += '-'; 346 | int i=0; 347 | for(;i::Rep my128bitNumberVariable; 359 | template 360 | class BitInt { 361 | public: 362 | typedef LimbInt Rep; 363 | private: 364 | BitInt(); 365 | }; 366 | 367 | } // end namespace FIXINT 368 | -------------------------------------------------------------------------------- /src/isct/gmpext4.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | gmpext4.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #ifdef _WIN32 29 | #pragma warning(disable: 4800) 30 | #pragma warning(disable: 4244) 31 | #include 32 | #pragma warning(default: 4244) 33 | #pragma warning(default: 4800) 34 | #else 35 | #include 36 | #endif 37 | 38 | #include 39 | 40 | 41 | namespace GMPExt4 { 42 | 43 | // types for k-vectors in R4: 44 | // Ext4_k 45 | 46 | struct GmpExt4_1 { 47 | mpz_class e0; 48 | mpz_class e1; 49 | mpz_class e2; 50 | mpz_class e3; 51 | }; 52 | 53 | struct GmpExt4_2 { 54 | mpz_class e01; 55 | mpz_class e02; 56 | mpz_class e03; 57 | mpz_class e12; 58 | mpz_class e13; 59 | mpz_class e23; 60 | }; 61 | 62 | struct GmpExt4_3 { 63 | mpz_class e012; 64 | mpz_class e013; 65 | mpz_class e023; 66 | mpz_class e123; 67 | }; 68 | 69 | 70 | // ******************************** 71 | // Output Routines 72 | inline std::ostream& operator<<(std::ostream &out, const GmpExt4_1 &ext) 73 | { 74 | return out << '[' << ext.e0 75 | << ',' << ext.e1 76 | << ',' << ext.e2 77 | << ',' << ext.e3 << ']'; 78 | } 79 | inline std::ostream& operator<<(std::ostream &out, const GmpExt4_2 &ext) 80 | { 81 | return out << '[' << ext.e01 82 | << ',' << ext.e02 83 | << ',' << ext.e03 84 | << ',' << ext.e12 85 | << ',' << ext.e13 86 | << ',' << ext.e23 << ']'; 87 | } 88 | inline std::ostream& operator<<(std::ostream &out, const GmpExt4_3 &ext) 89 | { 90 | return out << '[' << ext.e012 91 | << ',' << ext.e013 92 | << ',' << ext.e023 93 | << ',' << ext.e123 << ']'; 94 | } 95 | 96 | 97 | // ******************************** 98 | // A neg takes a k-vector and returns its negation 99 | // neg(X,Y) is safe for X=Y 100 | inline 101 | void neg(GmpExt4_1 &out, const GmpExt4_1 &in) 102 | { 103 | out.e0 = -in.e0; 104 | out.e1 = -in.e1; 105 | out.e2 = -in.e2; 106 | out.e3 = -in.e3; 107 | } 108 | inline 109 | void neg(GmpExt4_2 &out, const GmpExt4_2 &in) 110 | { 111 | out.e01 = -in.e01; 112 | out.e02 = -in.e02; 113 | out.e03 = -in.e03; 114 | out.e12 = -in.e12; 115 | out.e13 = -in.e13; 116 | out.e23 = -in.e23; 117 | } 118 | inline 119 | void neg(GmpExt4_3 &out, const GmpExt4_3 &in) 120 | { 121 | out.e012 = -in.e012; 122 | out.e013 = -in.e013; 123 | out.e023 = -in.e023; 124 | out.e123 = -in.e123; 125 | } 126 | 127 | 128 | // ******************************** 129 | // A dual operation takes a k-vector and returns a (4-k)-vector 130 | // A reverse dual operation inverts the dual operation 131 | // dual(X,Y) is not safe for X=Y (same with revdual) 132 | inline 133 | void dual(GmpExt4_1 &out, const GmpExt4_3 &in) 134 | { 135 | out.e0 = in.e123; 136 | out.e1 = -in.e023; 137 | out.e2 = in.e013; 138 | out.e3 = -in.e012; 139 | } 140 | inline 141 | void dual(GmpExt4_2 &out, const GmpExt4_2 &in) 142 | { 143 | out.e01 = in.e23; 144 | out.e02 = -in.e13; 145 | out.e03 = in.e12; 146 | out.e12 = in.e03; 147 | out.e13 = -in.e02; 148 | out.e23 = in.e01; 149 | } 150 | inline 151 | void dual(GmpExt4_3 &out, const GmpExt4_1 &in) 152 | { 153 | out.e012 = in.e3; 154 | out.e013 = -in.e2; 155 | out.e023 = in.e1; 156 | out.e123 = -in.e0; 157 | } 158 | inline 159 | void revdual(GmpExt4_1 &out, const GmpExt4_3 &in) 160 | { 161 | out.e0 = -in.e123; 162 | out.e1 = in.e023; 163 | out.e2 = -in.e013; 164 | out.e3 = in.e012; 165 | } 166 | inline 167 | void revdual(GmpExt4_2 &out, const GmpExt4_2 &in) 168 | { 169 | out.e01 = in.e23; 170 | out.e02 = -in.e13; 171 | out.e03 = in.e12; 172 | out.e12 = in.e03; 173 | out.e13 = -in.e02; 174 | out.e23 = in.e01; 175 | } 176 | inline 177 | void revdual(GmpExt4_3 &out, const GmpExt4_1 &in) 178 | { 179 | out.e012 = -in.e3; 180 | out.e013 = in.e2; 181 | out.e023 = -in.e1; 182 | out.e123 = in.e0; 183 | } 184 | 185 | 186 | // ******************************** 187 | // A join takes a j-vector and a k-vector and returns a (j+k)-vector 188 | inline 189 | void join(GmpExt4_2 &out, const GmpExt4_1 &lhs, const GmpExt4_1 &rhs) 190 | { 191 | out.e01 = (lhs.e0 * rhs.e1) - (rhs.e0 * lhs.e1); 192 | out.e02 = (lhs.e0 * rhs.e2) - (rhs.e0 * lhs.e2); 193 | out.e03 = (lhs.e0 * rhs.e3) - (rhs.e0 * lhs.e3); 194 | out.e12 = (lhs.e1 * rhs.e2) - (rhs.e1 * lhs.e2); 195 | out.e13 = (lhs.e1 * rhs.e3) - (rhs.e1 * lhs.e3); 196 | out.e23 = (lhs.e2 * rhs.e3) - (rhs.e2 * lhs.e3); 197 | } 198 | inline 199 | void join(GmpExt4_3 &out, const GmpExt4_2 &lhs, const GmpExt4_1 &rhs) 200 | { 201 | out.e012 = (lhs.e01 * rhs.e2) - (lhs.e02 * rhs.e1) + (lhs.e12 *rhs.e0); 202 | out.e013 = (lhs.e01 * rhs.e3) - (lhs.e03 * rhs.e1) + (lhs.e13 *rhs.e0); 203 | out.e023 = (lhs.e02 * rhs.e3) - (lhs.e03 * rhs.e2) + (lhs.e23 *rhs.e0); 204 | out.e123 = (lhs.e12 * rhs.e3) - (lhs.e13 * rhs.e2) + (lhs.e23 *rhs.e1); 205 | } 206 | inline 207 | void join(GmpExt4_3 &out, const GmpExt4_1 &lhs, const GmpExt4_2 &rhs) 208 | { 209 | join(out, rhs, lhs); 210 | // no negation since swapping the arguments requires two 211 | // swaps of 1-vectors 212 | } 213 | 214 | 215 | // ******************************** 216 | // A meet takes a j-vector and a k-vector and returns a (j+k-4)-vector 217 | inline 218 | void meet(GmpExt4_2 &out, const GmpExt4_3 &lhs, const GmpExt4_3 &rhs) 219 | { 220 | GmpExt4_2 out_dual; 221 | GmpExt4_1 lhs_dual; 222 | GmpExt4_1 rhs_dual; 223 | dual(lhs_dual, lhs); 224 | dual(rhs_dual, rhs); 225 | join(out_dual, lhs_dual, rhs_dual); 226 | revdual(out, out_dual); 227 | } 228 | inline 229 | void meet(GmpExt4_1 &out, const GmpExt4_2 &lhs, const GmpExt4_3 &rhs) 230 | { 231 | GmpExt4_3 out_dual; 232 | GmpExt4_2 lhs_dual; 233 | GmpExt4_1 rhs_dual; 234 | dual(lhs_dual, lhs); 235 | dual(rhs_dual, rhs); 236 | join(out_dual, lhs_dual, rhs_dual); 237 | revdual(out, out_dual); 238 | } 239 | inline 240 | void meet(GmpExt4_1 &out, const GmpExt4_3 &lhs, const GmpExt4_2 &rhs) 241 | { 242 | GmpExt4_3 out_dual; 243 | GmpExt4_1 lhs_dual; 244 | GmpExt4_2 rhs_dual; 245 | dual(lhs_dual, lhs); 246 | dual(rhs_dual, rhs); 247 | join(out_dual, lhs_dual, rhs_dual); 248 | revdual(out, out_dual); 249 | } 250 | 251 | 252 | // ******************************** 253 | // An inner product takes two k-vectors and produces a single number 254 | inline 255 | mpz_class inner(const GmpExt4_1 &lhs, const GmpExt4_1 &rhs) 256 | { 257 | return lhs.e0 * rhs.e0 + 258 | lhs.e1 * rhs.e1 + 259 | lhs.e2 * rhs.e2 + 260 | lhs.e3 * rhs.e3; 261 | } 262 | inline 263 | mpz_class inner(const GmpExt4_2 &lhs, const GmpExt4_2 &rhs) 264 | { 265 | return lhs.e01 * rhs.e01 + 266 | lhs.e02 * rhs.e02 + 267 | lhs.e03 * rhs.e03 + 268 | lhs.e12 * rhs.e12 + 269 | lhs.e13 * rhs.e13 + 270 | lhs.e23 * rhs.e23; 271 | } 272 | inline 273 | mpz_class inner(const GmpExt4_3 &lhs, const GmpExt4_3 &rhs) 274 | { 275 | return lhs.e012 * rhs.e012 + 276 | lhs.e013 * rhs.e013 + 277 | lhs.e023 * rhs.e023 + 278 | lhs.e123 * rhs.e123; 279 | } 280 | 281 | 282 | 283 | 284 | 285 | 286 | } // end namespace GMPExt4 287 | -------------------------------------------------------------------------------- /src/isct/quantization.cpp: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | quantization.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #include "quantization.h" 27 | 28 | namespace Quantization { 29 | 30 | double MAGNIFY = 1.0; 31 | double RESHRINK = 1.0; 32 | 33 | } // end namespace Quantization 34 | 35 | -------------------------------------------------------------------------------- /src/isct/quantization.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | quantization.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include 29 | 30 | namespace Quantization { 31 | 32 | // NOTE: none of these values should be modified by the clients 33 | static const int BITS = 30; 34 | // MAGNIFY * RESHRINK == 1 35 | extern double MAGNIFY; 36 | extern double RESHRINK; 37 | inline int quantize2int(double number) { 38 | return int(number * MAGNIFY); 39 | } 40 | inline double quantizedInt2double(int number) { 41 | return RESHRINK * double(number); 42 | } 43 | inline double quantize(double number) { 44 | return RESHRINK * double(int(number * MAGNIFY)); 45 | } 46 | 47 | // given the specified number of bits, 48 | // and bound on the coordinate values of points, 49 | // fit as fine-grained a grid as possible over the space. 50 | inline void callibrate(double maximumMagnitude) 51 | { 52 | int max_exponent; 53 | std::frexp(maximumMagnitude, &max_exponent); 54 | max_exponent++; // ensure that 2^max_exponent > maximumMagnitude 55 | 56 | // set constants 57 | MAGNIFY = std::pow(2.0, BITS - max_exponent); 58 | // we are guaranteed that maximumMagnitude * MAGNIFY < 2.0^BITS 59 | RESHRINK = std::pow(2.0, max_exponent - BITS); 60 | } 61 | 62 | 63 | } // end namespace Quantization 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/isct/unsafeRayTriIsct.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | unsafeRayTriIsct.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include "ray.h" 29 | #include "vec.h" 30 | 31 | struct isct_ray_triangle_result 32 | { 33 | double t; 34 | Vec3d bary; 35 | }; 36 | 37 | inline 38 | bool isct_ray_triangle( 39 | Ray3d ray, 40 | Vec3d va, 41 | Vec3d vb, 42 | Vec3d vc, 43 | double *t, 44 | Vec3d *bary 45 | ) { 46 | ENSURE(t); 47 | ENSURE(bary); 48 | 49 | // re-center the problem at the base point of the ray 50 | va -= ray.p; 51 | vb -= ray.p; 52 | vc -= ray.p; 53 | 54 | // Then compute volumes of tetrahedra spanning 55 | // * the base point / ray direction line segment 56 | // * an edge of the triangle 57 | // Keeping orientations in mind... 58 | double volAB = det(va, vb, ray.r); 59 | double volBC = det(vb, vc, ray.r); 60 | double volCA = - det(va, vc, ray.r); 61 | // then also compute the volume of tet with the entire triangle as a face... 62 | double volABC = det(va, vb, vc); 63 | // if any of the signs of the edge tests 64 | // disagree with the sign of the whole triangle, then 65 | // the ray does not pass through the triangle 66 | if(volAB * volABC < 0 || 67 | volBC * volABC < 0 || 68 | volCA * volABC < 0) return false; 69 | 70 | // otherwise, compute the t - value for the ray to intersect 71 | // if this is negative, then the client can detect that the 72 | // ray would have to travel backwards to hit the triangle in question. 73 | double edgeSum = volAB + volBC + volCA; 74 | if(edgeSum == 0) return false; 75 | *t = volABC / (volAB + volBC + volCA); 76 | if(*t <= 0) return false; 77 | 78 | *bary = Vec3d(volBC/edgeSum, volCA/edgeSum, volAB/edgeSum); 79 | return true; 80 | } 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | main.cpp 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | 27 | // This file contains a command line program that can be used 28 | // to exercise Cork's functionality without having to write 29 | // any code. 30 | 31 | #include "files.h" 32 | 33 | #include 34 | using std::cout; 35 | using std::cerr; 36 | using std::endl; 37 | #include 38 | using std::stringstream; 39 | using std::string; 40 | 41 | using std::ostream; 42 | 43 | #include "cork.h" 44 | 45 | 46 | void file2corktrimesh( 47 | const Files::FileMesh &in, CorkTriMesh *out 48 | ) { 49 | out->n_vertices = in.vertices.size(); 50 | out->n_triangles = in.triangles.size(); 51 | 52 | out->triangles = new uint[(out->n_triangles) * 3]; 53 | out->vertices = new float[(out->n_vertices) * 3]; 54 | 55 | for(uint i=0; in_triangles; i++) { 56 | (out->triangles)[3*i+0] = in.triangles[i].a; 57 | (out->triangles)[3*i+1] = in.triangles[i].b; 58 | (out->triangles)[3*i+2] = in.triangles[i].c; 59 | } 60 | 61 | for(uint i=0; in_vertices; i++) { 62 | (out->vertices)[3*i+0] = in.vertices[i].pos.x; 63 | (out->vertices)[3*i+1] = in.vertices[i].pos.y; 64 | (out->vertices)[3*i+2] = in.vertices[i].pos.z; 65 | } 66 | } 67 | 68 | void corktrimesh2file( 69 | CorkTriMesh in, Files::FileMesh &out 70 | ) { 71 | out.vertices.resize(in.n_vertices); 72 | out.triangles.resize(in.n_triangles); 73 | 74 | for(uint i=0; i 0) { 92 | cerr << "Unable to load in " << filename << endl; 93 | exit(1); 94 | } 95 | 96 | file2corktrimesh(filemesh, out); 97 | } 98 | void saveMesh(string filename, CorkTriMesh in) 99 | { 100 | Files::FileMesh filemesh; 101 | 102 | corktrimesh2file(in, filemesh); 103 | 104 | if(Files::writeTriMesh(filename, &filemesh) > 0) { 105 | cerr << "Unable to write to " << filename << endl; 106 | exit(1); 107 | } 108 | } 109 | 110 | 111 | 112 | class CmdList { 113 | public: 114 | CmdList(); 115 | ~CmdList() {} 116 | 117 | void regCmd( 118 | string name, 119 | string helptxt, 120 | std::function< void(std::vector::iterator &, 121 | const std::vector::iterator &) > body 122 | ); 123 | 124 | void printHelp(ostream &out); 125 | void runCommands(std::vector::iterator &arg_it, 126 | const std::vector::iterator &end_it); 127 | 128 | private: 129 | struct Command { 130 | string name; // e.g. "show" will be invoked with option "-show" 131 | string helptxt; // lines to be displayed 132 | std::function< void(std::vector::iterator &, 133 | const std::vector::iterator &) > body; 134 | }; 135 | std::vector commands; 136 | }; 137 | 138 | CmdList::CmdList() 139 | { 140 | regCmd("help", 141 | "-help show this help message", 142 | [this](std::vector::iterator &, 143 | const std::vector::iterator &) { 144 | printHelp(cout); 145 | exit(0); 146 | }); 147 | } 148 | 149 | void CmdList::regCmd( 150 | string name, 151 | string helptxt, 152 | std::function< void(std::vector::iterator &, 153 | const std::vector::iterator &) > body 154 | ) { 155 | Command cmd = { 156 | name, 157 | helptxt, 158 | body 159 | }; 160 | commands.push_back(cmd); 161 | } 162 | 163 | void CmdList::printHelp(ostream &out) 164 | { 165 | out << 166 | "Welcome to Cork. Usage:" << endl << 167 | " > cork [-command arg0 arg1 ... argn]*" << endl << 168 | "for example," << endl << 169 | " > cork -union box0.off box1.off result.off" << endl << 170 | "Options:" << endl; 171 | for(auto &cmd : commands) 172 | out << cmd.helptxt << endl; 173 | out << endl; 174 | } 175 | 176 | void CmdList::runCommands(std::vector::iterator &arg_it, 177 | const std::vector::iterator &end_it) 178 | { 179 | while(arg_it != end_it) { 180 | string arg_cmd = *arg_it; 181 | if(arg_cmd[0] != '-') { 182 | cerr << arg_cmd << endl; 183 | cerr << "All commands must begin with '-'" << endl; 184 | exit(1); 185 | } 186 | arg_cmd = arg_cmd.substr(1); 187 | arg_it++; 188 | 189 | bool found = true; 190 | for(auto &cmd : commands) { 191 | if(arg_cmd == cmd.name) { 192 | cmd.body(arg_it, end_it); 193 | found = true; 194 | break; 195 | } 196 | } 197 | if(!found) { 198 | cerr << "Command -" + arg_cmd + " is not recognized" << endl; 199 | exit(1); 200 | } 201 | } 202 | } 203 | 204 | 205 | std::function< void( 206 | std::vector::iterator &, 207 | const std::vector::iterator & 208 | ) > 209 | genericBinaryOp( 210 | std::function< void(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out) > 211 | binop 212 | ) { 213 | return [binop] 214 | (std::vector::iterator &args, 215 | const std::vector::iterator &end) { 216 | // data... 217 | CorkTriMesh in0; 218 | CorkTriMesh in1; 219 | CorkTriMesh out; 220 | 221 | if(args == end) { cerr << "too few args" << endl; exit(1); } 222 | loadMesh(*args, &in0); 223 | args++; 224 | 225 | if(args == end) { cerr << "too few args" << endl; exit(1); } 226 | loadMesh(*args, &in1); 227 | args++; 228 | 229 | binop(in0, in1, &out); 230 | 231 | if(args == end) { cerr << "too few args" << endl; exit(1); } 232 | saveMesh(*args, out); 233 | args++; 234 | 235 | freeCorkTriMesh(&out); 236 | 237 | delete[] in0.vertices; 238 | delete[] in0.triangles; 239 | delete[] in1.vertices; 240 | delete[] in1.triangles; 241 | }; 242 | } 243 | 244 | 245 | int main(int argc, char *argv[]) 246 | { 247 | initRand(); // that's useful 248 | 249 | if(argc < 2) { 250 | cout << "Please type 'cork -help' for instructions" << endl; 251 | exit(0); 252 | } 253 | 254 | // store arguments in a standard container 255 | std::vector args(argc); 256 | for(int k=0; k::iterator &args, 272 | const std::vector::iterator &end) { 273 | CorkTriMesh in; 274 | if(args == end) { cerr << "too few args" << endl; exit(1); } 275 | string filename = *args; 276 | loadMesh(*args, &in); 277 | args++; 278 | 279 | bool solid = isSolid(in); 280 | cout << "The mesh " << filename << " is: " << endl; 281 | cout << " " << ((solid)? "SOLID" : "NOT SOLID") << endl; 282 | 283 | delete[] in.vertices; 284 | delete[] in.triangles; 285 | }); 286 | cmds.regCmd("union", 287 | "-union in0 in1 out Compute the Boolean union of in0 and in1,\n" 288 | " and output the result", 289 | genericBinaryOp(computeUnion)); 290 | cmds.regCmd("diff", 291 | "-diff in0 in1 out Compute the Boolean difference of in0 and in1,\n" 292 | " and output the result", 293 | genericBinaryOp(computeDifference)); 294 | cmds.regCmd("isct", 295 | "-isct in0 in1 out Compute the Boolean intersection of in0 and in1,\n" 296 | " and output the result", 297 | genericBinaryOp(computeIntersection)); 298 | cmds.regCmd("xor", 299 | "-xor in0 in1 out Compute the Boolean XOR of in0 and in1,\n" 300 | " and output the result\n" 301 | " (aka. the symmetric difference)", 302 | genericBinaryOp(computeSymmetricDifference)); 303 | cmds.regCmd("resolve", 304 | "-resolve in0 in1 out Intersect the two meshes in0 and in1,\n" 305 | " and output the connected mesh with those\n" 306 | " intersections made explicit and connected", 307 | genericBinaryOp(resolveIntersections)); 308 | 309 | 310 | cmds.runCommands(arg_it, args.end()); 311 | 312 | return 0; 313 | } 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | -------------------------------------------------------------------------------- /src/math/bbox.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | bbox.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include "vec.h" 29 | 30 | #include 31 | 32 | // NOTE on usage of BBoxes 33 | // all BBoxes are initialized so that 34 | // convex(BBox(), bb) == bb 35 | // for any bb 36 | 37 | 38 | // ************************************************************************** 39 | // * BBox2 stores 2-dimensional axis aligned bounding boxes 40 | // ************************************************************************** 41 | template 42 | class BBox2 { 43 | public: // data 44 | Vec2 minp, maxp; 45 | public: // constructors 46 | BBox2(const Vec2 &minpp, const Vec2 &maxpp) : 47 | minp(minpp), maxp(maxpp) {} 48 | inline BBox2(const BBox2 &bb) : minp(bb.minp), maxp(bb.maxp) {} 49 | inline BBox2(); // specialized implementations for float/double only 50 | }; 51 | 52 | template<> inline 53 | BBox2::BBox2() : 54 | minp( FLT_MAX, FLT_MAX), 55 | maxp(-FLT_MAX,-FLT_MAX) 56 | {} 57 | template<> inline 58 | BBox2::BBox2() : 59 | minp( DBL_MAX, DBL_MAX), 60 | maxp(-DBL_MAX,-DBL_MAX) 61 | {} 62 | 63 | template 64 | inline bool isEmpty(const BBox2 &bb) { 65 | return bb.maxp[0] < bb.minp[0] || 66 | bb.maxp[1] < bb.minp[1]; 67 | } 68 | template 69 | inline bool isIn(const Vec2 &p, const BBox2 &bb) { 70 | return bb.minp[0] <= p[0] && p[0] <= bb.maxp[0] && 71 | bb.minp[1] <= p[1] && p[1] <= bb.maxp[1]; 72 | } 73 | template 74 | inline bool hasIsct(const BBox2 &lhs, const BBox2 &rhs) { 75 | return lhs.minp[0] <= rhs.maxp[0] && lhs.maxp[0] >= rhs.minp[0] && 76 | lhs.minp[1] <= rhs.maxp[1] && lhs.maxp[1] >= rhs.minp[1]; 77 | } 78 | template 79 | inline BBox2 convex(const BBox2 &lhs, const BBox2 &rhs) { 80 | return BBox2(min(lhs.minp, rhs.minp), max(lhs.maxp, rhs.maxp)); 81 | } 82 | template 83 | inline BBox2 isct(const BBox2 &lhs, const BBox2 &rhs) { 84 | return BBox2(max(lhs.minp, rhs.minp), min(lhs.maxp, rhs.maxp)); 85 | } 86 | 87 | template 88 | inline Vec2 dim(const BBox2 &bb) { 89 | return bb.maxp - bb.minp; 90 | } 91 | template 92 | inline N perimeter(const BBox2 &bb) { 93 | Vec2 d = dim(bb); 94 | return 2*(d[0] + d[1]); 95 | } 96 | 97 | template 98 | inline std::ostream& operator<<(std::ostream &out, const BBox2 &bb) { 99 | return out << "[min" << bb.minp << ";max" << bb.maxp << ']'; 100 | } 101 | 102 | // ************************************************************************** 103 | // * BBox3 stores 3-dimensional axis aligned bounding boxes 104 | // ************************************************************************** 105 | template 106 | class BBox3 { 107 | public: // data 108 | Vec3 minp, maxp; 109 | public: // constructors 110 | BBox3(const Vec3 &minpp, const Vec3 &maxpp) : 111 | minp(minpp), maxp(maxpp) {} 112 | inline BBox3(const BBox3 &bb) : minp(bb.minp), maxp(bb.maxp) {} 113 | inline BBox3(); // specialized implementations for float/double only 114 | }; 115 | 116 | template<> inline 117 | BBox3::BBox3() : 118 | minp( FLT_MAX, FLT_MAX, FLT_MAX), 119 | maxp(-FLT_MAX,-FLT_MAX,-FLT_MAX) 120 | {} 121 | template<> inline 122 | BBox3::BBox3() : 123 | minp( DBL_MAX, DBL_MAX, DBL_MAX), 124 | maxp(-DBL_MAX,-DBL_MAX,-DBL_MAX) 125 | {} 126 | 127 | template 128 | inline bool isEmpty(const BBox3 &bb) { 129 | return bb.maxp[0] < bb.minp[0] || 130 | bb.maxp[1] < bb.minp[1] || 131 | bb.maxp[2] < bb.minp[2]; 132 | } 133 | template 134 | inline bool isIn(const Vec3 &p, const BBox3 &bb) { 135 | return bb.minp[0] <= p[0] && p[0] <= bb.maxp[0] && 136 | bb.minp[1] <= p[1] && p[1] <= bb.maxp[1] && 137 | bb.minp[2] <= p[2] && p[2] <= bb.maxp[2]; 138 | } 139 | template 140 | inline bool hasIsct(const BBox3 &lhs, const BBox3 &rhs) { 141 | return lhs.minp[0] <= rhs.maxp[0] && lhs.maxp[0] >= rhs.minp[0] && 142 | lhs.minp[1] <= rhs.maxp[1] && lhs.maxp[1] >= rhs.minp[1] && 143 | lhs.minp[2] <= rhs.maxp[2] && lhs.maxp[2] >= rhs.minp[2]; 144 | } 145 | template 146 | inline BBox3 convex(const BBox3 &lhs, const BBox3 &rhs) { 147 | return BBox3(min(lhs.minp, rhs.minp), max(lhs.maxp, rhs.maxp)); 148 | } 149 | template 150 | inline BBox3 isct(const BBox3 &lhs, const BBox3 &rhs) { 151 | return BBox3(max(lhs.minp, rhs.minp), min(lhs.maxp, rhs.maxp)); 152 | } 153 | 154 | template 155 | inline Vec3 dim(const BBox3 &bb) { 156 | return bb.maxp - bb.minp; 157 | } 158 | template 159 | inline N surfaceArea(const BBox3 &bb) { 160 | Vec3 d = dim(bb); 161 | return 2*(d[1]*d[2] + d[0]*d[2] + d[0]*d[1]); 162 | } 163 | 164 | template 165 | inline std::ostream& operator<<(std::ostream &out, const BBox3 &bb) { 166 | return out << "[min" << bb.minp << ";max" << bb.maxp << ']'; 167 | } 168 | 169 | 170 | // ************************************************************************** 171 | // * BBox4 stores 4-dimensional axis aligned bounding boxes 172 | // ************************************************************************** 173 | template 174 | class BBox4 { 175 | public: // data 176 | Vec4 minp, maxp; 177 | public: // constructors 178 | BBox4(const Vec4 &minpp, const Vec4 &maxpp) : 179 | minp(minpp), maxp(maxpp) {} 180 | inline BBox4(const BBox4 &bb) : minp(bb.minp), maxp(bb.maxp) {} 181 | inline BBox4(); // specialized implementations for float/double only 182 | }; 183 | 184 | template<> inline 185 | BBox4::BBox4() : 186 | minp( FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX), 187 | maxp(-FLT_MAX,-FLT_MAX,-FLT_MAX,-FLT_MAX) 188 | {} 189 | template<> inline 190 | BBox4::BBox4() : 191 | minp( DBL_MAX, DBL_MAX, DBL_MAX, DBL_MAX), 192 | maxp(-DBL_MAX,-DBL_MAX,-DBL_MAX,-DBL_MAX) 193 | {} 194 | 195 | template 196 | inline bool isEmpty(const BBox4 &bb) { 197 | return bb.maxp[0] < bb.minp[0] || 198 | bb.maxp[1] < bb.minp[1] || 199 | bb.maxp[2] < bb.minp[2] || 200 | bb.maxp[3] < bb.minp[3]; 201 | } 202 | template 203 | inline bool isIn(const Vec4 &p, const BBox4 &bb) { 204 | return bb.minp[0] <= p[0] && p[0] <= bb.maxp[0] && 205 | bb.minp[1] <= p[1] && p[1] <= bb.maxp[1] && 206 | bb.minp[2] <= p[2] && p[2] <= bb.maxp[2] && 207 | bb.minp[3] <= p[3] && p[3] <= bb.maxp[3]; 208 | } 209 | template 210 | inline bool hasIsct(const BBox4 &lhs, const BBox4 &rhs) { 211 | return lhs.minp[0] <= rhs.maxp[0] && lhs.maxp[0] >= rhs.minp[0] && 212 | lhs.minp[1] <= rhs.maxp[1] && lhs.maxp[1] >= rhs.minp[1] && 213 | lhs.minp[2] <= rhs.maxp[2] && lhs.maxp[2] >= rhs.minp[2] && 214 | lhs.minp[3] <= rhs.maxp[3] && lhs.maxp[3] >= rhs.minp[3]; 215 | } 216 | template 217 | inline BBox4 convex(const BBox4 &lhs, const BBox4 &rhs) { 218 | return BBox4(min(lhs.minp, rhs.minp), max(lhs.maxp, rhs.maxp)); 219 | } 220 | template 221 | inline BBox4 isct(const BBox4 &lhs, const BBox4 &rhs) { 222 | return BBox4(max(lhs.minp, rhs.minp), min(lhs.maxp, rhs.maxp)); 223 | } 224 | 225 | template 226 | inline Vec4 dim(const BBox4 &bb) { 227 | return bb.maxp - bb.minp; 228 | } 229 | 230 | template 231 | inline std::ostream& operator<<(std::ostream &out, const BBox4 &bb) { 232 | return out << "[min" << bb.minp << ";max" << bb.maxp << ']'; 233 | } 234 | 235 | 236 | 237 | // define some common useful versions of the boxes 238 | typedef BBox2 BBox2f; 239 | typedef BBox3 BBox3f; 240 | typedef BBox4 BBox4f; 241 | 242 | typedef BBox2 BBox2d; 243 | typedef BBox3 BBox3d; 244 | typedef BBox4 BBox4d; 245 | 246 | 247 | -------------------------------------------------------------------------------- /src/math/ray.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | ray.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include "vec.h" 29 | 30 | template 31 | struct Ray3 32 | { 33 | Vec3 p; // point of origin 34 | Vec3 r; // ray direction 35 | 36 | Ray3() {} 37 | Ray3(const Vec3 &point, const Vec3 &dir) : 38 | p(point), r(dir) 39 | {} 40 | template 41 | Ray3(const Ray3 &cp) : p(cp.p), r(cp.r) {} 42 | }; 43 | 44 | 45 | template 46 | inline std::ostream& operator<<(std::ostream &out, const Ray3 &ray) { 47 | return out << '[' << ray.p << ';' << ray.r << ']'; 48 | } 49 | 50 | 51 | typedef Ray3 Ray3f; 52 | typedef Ray3 Ray3d; 53 | 54 | -------------------------------------------------------------------------------- /src/mesh/mesh.bool.tpp: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | mesh.bool.tpp 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include 29 | 30 | template 31 | class Mesh::BoolProblem 32 | { 33 | public: 34 | BoolProblem(Mesh *owner) : mesh(owner) 35 | {} 36 | virtual ~BoolProblem() {} 37 | 38 | // do things 39 | void doSetup(Mesh &rhs); 40 | 41 | // choose what to remove 42 | enum TriCode { KEEP_TRI, DELETE_TRI, FLIP_TRI }; 43 | void doDeleteAndFlip( 44 | std::function classify 45 | ); 46 | 47 | private: // methods 48 | struct BoolEdata { 49 | bool is_isct; 50 | }; 51 | 52 | inline byte& boolData(uint tri_id) { 53 | return mesh->tris[tri_id].data.bool_alg_data; 54 | } 55 | 56 | void populateECache() 57 | { 58 | ecache = mesh->createEGraphCache(); 59 | 60 | // label some of the edges as intersection edges and others as not 61 | ecache.for_each([&](uint i, uint j, EGraphEntry &entry) { 62 | entry.data.is_isct = false; 63 | byte operand = boolData(entry.tids[0]); 64 | for(uint k=1; k &tids)> action 77 | ) { 78 | ecache.for_each([&](uint i, uint j, EGraphEntry &entry) { 79 | if(entry.data.is_isct) { 80 | ShortVec tid0s; 81 | ShortVec tid1s; 82 | for(uint tid : entry.tids) { 83 | if(boolData(tid) & 1) 84 | tid1s.push_back(tid); 85 | else 86 | tid0s.push_back(tid); 87 | } 88 | action(i,j, true, tid1s); 89 | action(i,j, true, tid0s); 90 | } else { 91 | action(i,j, false, entry.tids); 92 | } 93 | }); 94 | } 95 | 96 | void prepInsideOutsideTests() 97 | { 98 | } 99 | 100 | bool isInside(uint tid, byte operand) { 101 | // find the point to trace outward from... 102 | Vec3d p(0,0,0); 103 | p += mesh->verts[mesh->tris[tid].a].pos; 104 | p += mesh->verts[mesh->tris[tid].b].pos; 105 | p += mesh->verts[mesh->tris[tid].c].pos; 106 | p /= 3.0; 107 | // ok, we've got the point, now let's pick a direction 108 | Ray3d r; 109 | r.p = p; 110 | r.r = Vec3d(drand(0.5,1.5), drand(0.5,1.5), drand(0.5, 1.5)); 111 | 112 | 113 | int winding = 0; 114 | // pass all triangles over ray 115 | for(Tri &tri : mesh->tris) { 116 | // ignore triangles from the same operand surface 117 | if((tri.data.bool_alg_data & 1) == operand) continue; 118 | 119 | double flip = 1.0; 120 | uint a = tri.a; 121 | uint b = tri.b; 122 | uint c = tri.c; 123 | Vec3d va = mesh->verts[a].pos; 124 | Vec3d vb = mesh->verts[b].pos; 125 | Vec3d vc = mesh->verts[c].pos; 126 | // normalize vertex order (to prevent leaks) 127 | if(a > b) { std::swap(a, b); std::swap(va, vb); flip = -flip; } 128 | if(b > c) { std::swap(b, c); std::swap(vb, vc); flip = -flip; } 129 | if(a > b) { std::swap(a, b); std::swap(va, vb); flip = -flip; } 130 | 131 | double t; 132 | Vec3d bary; 133 | if(isct_ray_triangle(r, va, vb, vc, &t, &bary)) { 134 | Vec3d normal = flip * cross(vb - va, vc - va); 135 | if(dot(normal, r.r) > 0.0) { // UNSAFE 136 | winding++; 137 | } else { 138 | winding--; 139 | } 140 | } 141 | } 142 | 143 | // now, we've got a winding number to work with... 144 | return winding > 0; 145 | } 146 | 147 | private: // data 148 | Mesh *mesh; 149 | EGraphCache ecache; 150 | }; 151 | 152 | 153 | static inline double triArea( 154 | Vec3d a, Vec3d b, Vec3d c 155 | ) { 156 | return len(cross(b-a, c-a)); 157 | } 158 | 159 | 160 | template 161 | void Mesh::BoolProblem::doSetup( 162 | Mesh &rhs 163 | ) { 164 | // Label surfaces... 165 | mesh->for_tris([](TriData &tri, VertData&, VertData&, VertData&) { 166 | tri.bool_alg_data = 0; 167 | }); 168 | rhs.for_tris([](TriData &tri, VertData&, VertData&, VertData&) { 169 | tri.bool_alg_data = 1; 170 | }); 171 | 172 | mesh->disjointUnion(rhs); 173 | mesh->resolveIntersections(); 174 | 175 | populateECache(); 176 | 177 | // form connected components; 178 | // we get one component for each connected component in one 179 | // of the two input meshes. 180 | // These components are not necessarily uniformly inside or outside 181 | // of the other operand mesh. 182 | UnionFind uf(mesh->tris.size()); 183 | for_ecache([&](uint, uint, bool, const ShortVec &tids) { 184 | uint tid0 = tids[0]; 185 | for(uint k=1; k uq_ids(mesh->tris.size(), uint(-1)); 191 | std::vector< std::vector > components; 192 | for(uint i=0; itris.size(); i++) { 193 | uint ufid = uf.find(i); 194 | if(uq_ids[ufid] == uint(-1)) { // unassigned 195 | uint N = components.size(); 196 | components.push_back(std::vector()); 197 | 198 | uq_ids[ufid] = uq_ids[i] = N; 199 | components[N].push_back(i); 200 | } else { // assigned already 201 | uq_ids[i] = uq_ids[ufid]; // propagate assignment 202 | components[uq_ids[i]].push_back(i); 203 | } 204 | } 205 | 206 | std::vector visited(mesh->tris.size(), false); 207 | 208 | // find the "best" triangle in each component, 209 | // and ray cast to determine inside-ness vs. outside-ness 210 | for(auto &comp : components) { 211 | // find max according to score 212 | uint best_tid = comp[0]; 213 | double best_area = 0.0; 214 | // SEARCH 215 | for(uint tid : comp) { 216 | Vec3d va = mesh->verts[mesh->tris[tid].a].pos; 217 | Vec3d vb = mesh->verts[mesh->tris[tid].b].pos; 218 | Vec3d vc = mesh->verts[mesh->tris[tid].c].pos; 219 | 220 | double area = triArea(va, vb, vc); 221 | if(area > best_area) { 222 | best_area = area; 223 | best_tid = tid; 224 | } 225 | } 226 | 227 | byte operand = boolData(best_tid); 228 | bool inside = isInside(best_tid, operand); 229 | 230 | // NOW PROPAGATE classification throughout the component. 231 | // do a breadth first propagation 232 | std::queue work; 233 | 234 | // begin by tagging the first triangle 235 | boolData(best_tid) |= (inside)? 2 : 0; 236 | visited[best_tid] = true; 237 | work.push(best_tid); 238 | 239 | while(!work.empty()) { 240 | uint curr_tid = work.front(); 241 | work.pop(); 242 | 243 | for(uint k=0; k<3; k++) { 244 | uint a = mesh->tris[curr_tid].v[k]; 245 | uint b = mesh->tris[curr_tid].v[(k+1)%3]; 246 | auto &entry = ecache(a,b); 247 | byte inside_sig = boolData(curr_tid) & 2; 248 | if(entry.data.is_isct) inside_sig ^= 2; 249 | for(uint tid : entry.tids) { 250 | if(visited[tid]) continue; 251 | if((boolData(tid)&1) != operand) continue; 252 | 253 | boolData(tid) |= inside_sig; 254 | visited[tid] = true; 255 | work.push(tid); 256 | } 257 | } 258 | } 259 | } 260 | } 261 | 262 | 263 | template 264 | void Mesh::BoolProblem::doDeleteAndFlip( 265 | std::function classify 266 | ) { 267 | TopoCache topocache(mesh); 268 | 269 | std::vector toDelete; 270 | topocache.tris.for_each([&](Tptr tptr) { 271 | TriCode code = classify(boolData(tptr->ref)); 272 | switch(code) { 273 | case DELETE_TRI: 274 | toDelete.push_back(tptr); 275 | break; 276 | case FLIP_TRI: 277 | topocache.flipTri(tptr); 278 | break; 279 | case KEEP_TRI: 280 | default: 281 | break; 282 | } 283 | }); 284 | 285 | for(Tptr tptr : toDelete) { 286 | topocache.deleteTri(tptr); 287 | } 288 | 289 | topocache.commit(); 290 | } 291 | 292 | 293 | 294 | 295 | 296 | template 297 | void Mesh::boolUnion(Mesh &rhs) 298 | { 299 | BoolProblem bprob(this); 300 | 301 | bprob.doSetup(rhs); 302 | 303 | bprob.doDeleteAndFlip([](byte data) -> typename BoolProblem::TriCode { 304 | if((data & 2) == 2) // part of op 0/1 INSIDE op 1/0 305 | return BoolProblem::DELETE_TRI; 306 | else // part of op 0/1 OUTSIDE op 1/0 307 | return BoolProblem::KEEP_TRI; 308 | }); 309 | } 310 | 311 | template 312 | void Mesh::boolDiff(Mesh &rhs) 313 | { 314 | BoolProblem bprob(this); 315 | 316 | bprob.doSetup(rhs); 317 | 318 | bprob.doDeleteAndFlip([](byte data) -> typename BoolProblem::TriCode { 319 | if(data == 2 || // part of op 0 INSIDE op 1 320 | data == 1) // part of op 1 OUTSIDE op 0 321 | return BoolProblem::DELETE_TRI; 322 | else if(data == 3) // part of op 1 INSIDE op 1 323 | return BoolProblem::FLIP_TRI; 324 | else // part of op 0 OUTSIDE op 1 325 | return BoolProblem::KEEP_TRI; 326 | }); 327 | } 328 | 329 | template 330 | void Mesh::boolIsct(Mesh &rhs) 331 | { 332 | BoolProblem bprob(this); 333 | 334 | bprob.doSetup(rhs); 335 | 336 | bprob.doDeleteAndFlip([](byte data) -> typename BoolProblem::TriCode { 337 | if((data & 2) == 0) // part of op 0/1 OUTSIDE op 1/0 338 | return BoolProblem::DELETE_TRI; 339 | else // part of op 0/1 INSIDE op 1/0 340 | return BoolProblem::KEEP_TRI; 341 | }); 342 | } 343 | 344 | template 345 | void Mesh::boolXor(Mesh &rhs) 346 | { 347 | BoolProblem bprob(this); 348 | 349 | bprob.doSetup(rhs); 350 | 351 | bprob.doDeleteAndFlip([](byte data) -> typename BoolProblem::TriCode { 352 | if((data & 2) == 0) // part of op 0/1 OUTSIDE op 1/0 353 | return BoolProblem::KEEP_TRI; 354 | else // part of op 0/1 INSIDE op 1/0 355 | return BoolProblem::FLIP_TRI; 356 | }); 357 | } 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | -------------------------------------------------------------------------------- /src/mesh/mesh.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | mesh.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | // SIMPLE USAGE: 29 | // In order to get standard template inclusion behavior/usage 30 | // just include this file. Then the entire template code 31 | // will be included in the compilation unit. 32 | // ADVANCED USAGE: 33 | // Only include "mesh.decl.h" where-ever you would normally include a 34 | // header file. This will avoid including the implementation code in 35 | // the current compilation unit. 36 | // Then, create a seperate cpp file which includes "mesh.h" and 37 | // explicitly instantiates the template with the desired template 38 | // parameters. 39 | // By following this scheme, you can prevent re-compiling the entire 40 | // template implementation in every usage compilation unit and every 41 | // time those compilation units are recompiled during development. 42 | 43 | // Declaration 44 | #include "mesh.decl.h" 45 | 46 | // Implementation 47 | #include "mesh.tpp" 48 | #include "mesh.remesh.tpp" 49 | #include "mesh.isct.tpp" 50 | #include "mesh.bool.tpp" 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/mesh/mesh.tpp: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | mesh.tpp 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include 29 | #include "unsafeRayTriIsct.h" 30 | #include 31 | #include 32 | #include 33 | 34 | #include "unionFind.h" 35 | 36 | // constructors 37 | template 38 | Mesh::Mesh() {} 39 | template 40 | Mesh::Mesh(Mesh &&cp) 41 | : tris(cp.tris), verts(cp.verts) 42 | {} 43 | template 44 | Mesh::Mesh(const RawMesh &raw) : 45 | tris(raw.triangles.size()), verts(raw.vertices) 46 | { 47 | // fill out the triangles 48 | for(uint i=0; i 56 | Mesh::~Mesh() {} 57 | 58 | template 59 | void Mesh::operator=(Mesh &&src) 60 | { 61 | tris = src.tris; 62 | verts = src.verts; 63 | } 64 | 65 | template 66 | bool Mesh::valid() const 67 | { 68 | for(uint i=0; i= verts.size() || 82 | tris[i].b >= verts.size() || 83 | tris[i].c >= verts.size()) { 84 | std::ostringstream message; 85 | message << "triangle #" << i << " should have indices in " 86 | << "the range 0 to " << (verts.size()-1) 87 | << ", but it has invalid indices: " 88 | << tris[i].a << ", " << tris[i].b << ", " << tris[i].c; 89 | CORK_ERROR(message.str()); 90 | return false; 91 | } 92 | } 93 | 94 | return true; 95 | } 96 | 97 | template 98 | RawMesh Mesh::raw() const 99 | { 100 | RawMesh result; 101 | result.vertices = verts; 102 | result.triangles.resize(tris.size()); 103 | for(uint i=0; i 113 | void Mesh::disjointUnion(const Mesh &cp) 114 | { 115 | uint oldVsize = verts.size(); 116 | uint oldTsize = tris.size(); 117 | uint cpVsize = cp.verts.size(); 118 | uint cpTsize = cp.tris.size(); 119 | uint newVsize = oldVsize + cpVsize; 120 | uint newTsize = oldTsize + cpTsize; 121 | 122 | std::vector v_remap(cpVsize); // oh this is obvious... 123 | verts.resize(newVsize); 124 | tris.resize(newTsize); 125 | 126 | for(uint i=0; i 146 | typename Mesh::Isct 147 | Mesh::pick(Ray3d ray) 148 | { 149 | Isct result; 150 | result.ray = ray; 151 | result.exists = false; 152 | 153 | double mint = DBL_MAX; 154 | 155 | // pass all triangles over ray 156 | for(uint i=0; i b) { std::swap(a, b); std::swap(va, vb); } 167 | if(b > c) { std::swap(b, c); std::swap(vb, vc); } 168 | if(a > b) { std::swap(a, b); std::swap(va, vb); } 169 | 170 | double t; 171 | Vec3d bary; 172 | if(isct_ray_triangle(ray, va, vb, vc, &t, &bary)) { 173 | if(t > 0 && t < mint) { 174 | result.exists = true; 175 | mint = t; 176 | result.tri_id = i; 177 | result.isct = ray.p + t * ray.r; 178 | result.bary = bary; 179 | } 180 | } 181 | } 182 | 183 | return result; 184 | } 185 | 186 | 187 | 188 | 189 | template 190 | bool Mesh::isClosed() 191 | { 192 | EGraphCache chains = createEGraphCache(); 193 | chains.for_each([&](uint i, uint j, EGraphEntry &entry) { 194 | entry.data = 0; 195 | }); 196 | // count up how many times each edge is encountered in one 197 | // orientation vs. the other 198 | for(Tri &tri : tris) { 199 | chains(tri.a, tri.b).data ++; 200 | chains(tri.b, tri.a).data --; 201 | 202 | chains(tri.b, tri.c).data ++; 203 | chains(tri.c, tri.b).data --; 204 | 205 | chains(tri.c, tri.a).data ++; 206 | chains(tri.a, tri.c).data --; 207 | } 208 | // now go through and see if any of these are non-zero 209 | bool closed = true; 210 | chains.for_each([&](uint i, uint j, EGraphEntry &entry) { 211 | if(entry.data != 0) 212 | closed = false; 213 | }); 214 | return closed; 215 | } 216 | 217 | 218 | 219 | 220 | static inline 221 | bool contains(const ShortVec &list, uint item) 222 | { 223 | for(uint k : list) 224 | if(k == item) 225 | return true; 226 | return false; 227 | } 228 | 229 | template 230 | typename Mesh::NeighborCache 231 | Mesh::createNeighborCache() 232 | { 233 | NeighborCache result; 234 | result.skeleton.resize(verts.size()); 235 | 236 | for(uint tid = 0; tid < tris.size(); tid++) { 237 | const Tri &tri = tris[tid]; 238 | 239 | result(tri.a, tri.b).tids.push_back(tid); 240 | result(tri.b, tri.a).tids.push_back(tid); 241 | 242 | result(tri.a, tri.c).tids.push_back(tid); 243 | result(tri.c, tri.a).tids.push_back(tid); 244 | 245 | result(tri.b, tri.c).tids.push_back(tid); 246 | result(tri.c, tri.b).tids.push_back(tid); 247 | } 248 | 249 | return result; 250 | } 251 | 252 | // This function signature is an amazing disaster... 253 | #ifdef _WIN32 254 | template 255 | template 256 | typename Mesh::EGraphCache 257 | #else 258 | template 259 | template 260 | typename Mesh::template EGraphCache 261 | #endif 262 | Mesh::createEGraphCache() 263 | { 264 | EGraphCache result; 265 | result.skeleton.resize(verts.size()); 266 | 267 | for(uint tid = 0; tid < tris.size(); tid++) { 268 | const Tri &tri = tris[tid]; 269 | 270 | result(tri.a, tri.b).tids.push_back(tid); 271 | result(tri.b, tri.a).tids.push_back(tid); 272 | 273 | result(tri.a, tri.c).tids.push_back(tid); 274 | result(tri.c, tri.a).tids.push_back(tid); 275 | 276 | result(tri.b, tri.c).tids.push_back(tid); 277 | result(tri.c, tri.b).tids.push_back(tid); 278 | } 279 | 280 | return result; 281 | } 282 | 283 | 284 | template 285 | std::vector Mesh::getComponentIds() 286 | { 287 | UnionFind uf(verts.size()); 288 | for(const Tri &tri : tris) { 289 | uf.unionIds(tri.a, tri.b); 290 | uf.unionIds(tri.a, tri.c); 291 | } 292 | 293 | return uf.dump(); 294 | } 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | -------------------------------------------------------------------------------- /src/off2obj.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using std::cin; 4 | using std::cout; 5 | using std::endl; 6 | #include 7 | using std::string; 8 | #include 9 | using std::vector; 10 | 11 | int main(int argc, const char* argv[]) 12 | { 13 | string input; 14 | if(!(cin >> input) || input != "OFF") return 1; 15 | 16 | int numvertices; 17 | int numfaces; 18 | int numedges; 19 | 20 | if(!(cin >> numvertices >> numfaces >> numedges) || numedges > 0) 21 | return 1; 22 | 23 | vector vertices(numvertices*3); 24 | vector< vector > faces(numfaces); 25 | 26 | for(int i=0; i> coord; 33 | cout << ' ' << coord; 34 | } 35 | cout << endl; 36 | } 37 | 38 | for(int i=0; i> vcount) || vcount < 3) return 1; 42 | 43 | cout << "f "; 44 | for(int v=0; v> index; 48 | cout << ' ' << index+1; 49 | } 50 | cout << endl; 51 | } 52 | 53 | return 0; 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/rawmesh/rawMesh.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | rawMesh.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include 29 | 30 | #include "vec.h" 31 | 32 | #include 33 | 34 | // vertex and triangle data must satisfy the following minimal specifications! 35 | // These exact field names must be used! 36 | struct MinimalVertexData 37 | { 38 | Vec3d pos; // required for both RawMesh and Mesh 39 | }; 40 | 41 | struct MinimalTriangleData 42 | { 43 | // Vertex Ids: (only used in raw mesh form) 44 | int a, b, c; 45 | }; 46 | 47 | // Raw mesh presents an exposed interface to a mesh. 48 | // This allows for easy input/output of data to and from the more powerful 49 | // Mesh data structure, as well as supporting more basic mesh applications 50 | template 51 | struct RawMesh 52 | { 53 | std::vector vertices; 54 | std::vector triangles; 55 | }; 56 | 57 | // allow for data to move between different kinds of raw meshes 58 | template 60 | inline RawMesh transduce( 61 | const RawMesh &input, 62 | std::function vertTransduce, 63 | std::function triTransduce 64 | ); 65 | 66 | 67 | #include "rawMesh.tpp" 68 | -------------------------------------------------------------------------------- /src/rawmesh/rawMesh.tpp: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | rawMesh.tpp 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | 29 | template 31 | inline RawMesh transduce( 32 | const RawMesh &input, 33 | std::function vertTransduce, 34 | std::function triTransduce 35 | ) { 36 | RawMesh output; 37 | 38 | uint nVert = input.vertices.size(); 39 | uint nTri = input.triangles.size(); 40 | output.vertices.resize(nVert); 41 | output.triangles.resize(nTri); 42 | 43 | for(uint i=0; i. 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include "prelude.h" 29 | // +------------------------------------------------------------------------- 30 | // | WHAT IS THIS? 31 | // | 32 | // | An IterPool is 33 | // | *) a memory pool -- new items can be requested, old items released 34 | // | *) iterable -- all of the allocated items can be iterated over 35 | // | It was built primarily to support dynamic connectivity structures 36 | // | for triangle meshes, such as those used during re-meshing. 37 | // | 38 | // | These processes often require the frequent allocation and 39 | // | deallocation of mesh elements and become easier to write when 40 | // | elements do not move around in memory, since valid pointers can be 41 | // | maintained. std::vector does not provide guaranteed static locations. 42 | // | 43 | // | Using a memory pool--threaded with a linked list--provides fast 44 | // | allocation/deallocation and relatively speedy enumeration of all 45 | // | currently allocated elements. While not as memory access friendly 46 | // | as an array or std::vector, the cost of linked list enumeration 47 | // | comes out in the wash compared to the pointer chasing performed 48 | // | for each element. 49 | // +------------------------------------------------------------------------- 50 | 51 | #include "memPool.h" 52 | #include 53 | 54 | template 55 | class IterPool 56 | { 57 | private: 58 | uint numAlloced; 59 | public: 60 | IterPool(int minInitBlocks=10) : 61 | numAlloced(0), 62 | block_list(nullptr), 63 | pool(minInitBlocks) 64 | {} 65 | IterPool(IterPool &&src) 66 | : numAlloced(src.numAlloced), 67 | block_list(src.block_list), 68 | pool(std::move(src.pool)) 69 | { 70 | src.block_list = nullptr; 71 | } 72 | ~IterPool() { 73 | // run through and destruct all remaining elements 74 | for_each([](T* obj) { 75 | obj->~T(); 76 | }); 77 | } 78 | 79 | void clear() { 80 | for_each([](T* obj) { 81 | obj->~T(); 82 | }); 83 | numAlloced = 0; 84 | block_list = nullptr; 85 | pool.clear(); 86 | } 87 | 88 | void operator=(IterPool &&src) 89 | { 90 | for_each([](T* obj) { 91 | obj->~T(); 92 | }); 93 | block_list = src.block_list; 94 | src.block_list = nullptr; 95 | pool = std::move(src.pool); 96 | } 97 | 98 | 99 | private: 100 | struct Block { 101 | T datum; 102 | Block *next; 103 | Block *prev; 104 | }; 105 | Block *block_list; 106 | 107 | public: // allocation/deallocation support 108 | T* alloc() { 109 | Block *new_block = pool.alloc(); 110 | if(block_list) block_list->prev = new_block; 111 | new_block->next = block_list; 112 | new_block->prev = NULL; 113 | block_list = new_block; 114 | 115 | T* obj = (T*)new_block; 116 | new (obj) T(); // invoke default constructor when allocating 117 | 118 | numAlloced++; 119 | 120 | return obj; 121 | } 122 | void free(T* item) { 123 | if(item == NULL) return; 124 | item->~T(); // invoke destructor before releasing 125 | 126 | numAlloced--; 127 | 128 | Block *ptr = (Block*)(item); 129 | if(ptr->next) ptr->next->prev = ptr->prev; 130 | if(ptr->prev) ptr->prev->next = ptr->next; 131 | if(ptr == block_list) block_list = ptr->next; 132 | pool.free(ptr); 133 | } 134 | 135 | public: 136 | inline void for_each(std::function func) const { 137 | for(Block *block = block_list; 138 | block != NULL; 139 | block = block->next) { 140 | func((T*)(block)); 141 | } 142 | } 143 | inline bool contains(T* tptr) const { 144 | for(Block *block = block_list; 145 | block != NULL; 146 | block = block->next) { 147 | if(tptr == (T*)(block)) 148 | return true; 149 | } 150 | return false; 151 | } 152 | inline uint size() const { 153 | return numAlloced; 154 | } 155 | public: // iteration support 156 | class iterator { 157 | public: 158 | iterator() : ptr(NULL) {} 159 | iterator(Block *init) : ptr(init) {} 160 | iterator(const iterator &cp) : ptr(cp.ptr) {} 161 | 162 | iterator& operator++() { // prefix version 163 | ptr = ptr->next; 164 | return *this; 165 | } 166 | iterator operator++(int) { 167 | iterator it(ptr); 168 | ptr = ptr->next; 169 | return it; 170 | } // postfix version 171 | T& operator*() { 172 | return ptr->datum; 173 | } 174 | T* operator->() { 175 | return (T*)(ptr); 176 | } 177 | bool operator==(const iterator &rhs) { 178 | return ptr == rhs.ptr; 179 | } 180 | bool operator!=(const iterator &rhs) { 181 | return ptr != rhs.ptr; 182 | } 183 | private: 184 | Block *ptr; 185 | }; 186 | 187 | iterator begin() { 188 | return iterator(block_list); 189 | } 190 | iterator end() { 191 | return iterator(NULL); 192 | } 193 | 194 | private: 195 | MemPool pool; 196 | }; 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /src/util/log.cpp: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | log.cpp 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #include "prelude.h" 27 | 28 | #include 29 | using std::atexit; 30 | 31 | #include 32 | #include 33 | using std::ofstream; 34 | using std::endl; 35 | 36 | namespace { 37 | 38 | ofstream error_log_stream; 39 | 40 | void on_exit() 41 | { 42 | error_log_stream << "Ending error logging at " << endl; 43 | std::time_t time_var = std::time(NULL); 44 | error_log_stream << std::ctime(&time_var) << endl; 45 | error_log_stream.close(); 46 | } 47 | 48 | } 49 | 50 | void logInit() 51 | { 52 | error_log_stream.open("error_log.txt", std::ios_base::app | std::ios_base::out ); 53 | error_log_stream << "Begining error logging at " << endl; 54 | std::time_t time_var = std::time(NULL); 55 | error_log_stream << std::ctime(&time_var);// << endl; 56 | 57 | atexit(on_exit); 58 | } 59 | 60 | // exposes the error log for writing 61 | std::ostream& err() 62 | { 63 | static bool first = true; 64 | if(first) { 65 | logInit(); 66 | first = false; 67 | } 68 | return error_log_stream; 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/util/memPool.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | memPool.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | /* 32 | * RESPONSIBILITIES OF THE USER / CLIENT CODE 33 | * 34 | * MemPool will not invoke constructors or destructors 35 | * on memory that it allocates or frees. There is a simple 36 | * reason for this: One advantage of MemPool is that a large number 37 | * of allocated entries can be disposed of very quickly by simply 38 | * destroying the pool. However, if MemPool were to call constructors 39 | * (and thus be obligated to call destructors), then it would have 40 | * to run through and destruct each element individually when it, itself 41 | * is destroyed. 42 | * 43 | * TAKE-AWAY: Make sure to construct/destruct objects explicity 44 | * when they are allocated with a raw MemPool. 45 | * 46 | */ 47 | 48 | // a pool of Ts 49 | template 50 | class MemPool 51 | { 52 | public: // constructor/destructor 53 | MemPool(int minInitBlocks=10); 54 | MemPool(MemPool &&src); 55 | ~MemPool(); 56 | 57 | void clear(); 58 | 59 | void operator=(MemPool &&); 60 | private: // seal off copying behavior from clients 61 | MemPool(const MemPool &) {} 62 | MemPool& operator=(const MemPool &) { return *this; } 63 | 64 | public: // main use functions 65 | T* alloc(); 66 | void free(T*); 67 | 68 | private: // internal data structures 69 | union Block { 70 | byte datum[sizeof(T)]; // enough space for a T 71 | Block *next; 72 | }; 73 | struct Chunk { 74 | Block *data; // array of size nBlocks 75 | int nBlocks; 76 | Chunk *next; 77 | }; 78 | private: // internal data instances 79 | Chunk *chunk_list; 80 | Block *free_list; 81 | private: // helper functions 82 | void addChunk(); // this should be called only when the free list is empty 83 | }; 84 | 85 | template 86 | MemPool::MemPool(int minInitBlocks) 87 | { 88 | // decide on the size of the first chunk 89 | const int MIN_BLOCKS = 2; // will not create a pool with fewer 90 | // than 2 blocks 91 | int nBlocks = std::max(minInitBlocks, MIN_BLOCKS); 92 | 93 | // allocate the first chunk 94 | chunk_list = (Chunk*)(new byte[sizeof(Chunk)]); 95 | chunk_list->next = NULL; 96 | chunk_list->nBlocks = nBlocks; 97 | chunk_list->data = (Block*)(new byte[sizeof(Block)*nBlocks]); 98 | 99 | // setup the free list 100 | free_list = chunk_list->data; 101 | Block* last_block = chunk_list->data + nBlocks - 1; 102 | for(Block *it = free_list; it != last_block; it++) 103 | it->next = it+1; 104 | last_block->next = NULL; 105 | } 106 | 107 | template 108 | MemPool::MemPool(MemPool &&src) 109 | : chunk_list(src.chunk_list), free_list(src.free_list) 110 | { 111 | src.chunk_list = nullptr; 112 | src.free_list = nullptr; 113 | } 114 | 115 | template 116 | void MemPool::operator=(MemPool &&src) 117 | { 118 | chunk_list = src.chunk_list; 119 | free_list = src.free_list; 120 | src.chunk_list = nullptr; 121 | src.free_list = nullptr; 122 | } 123 | 124 | template 125 | MemPool::~MemPool() 126 | { 127 | // We can ignore the free list here and just go through 128 | // destroying all of the chunks 129 | while(chunk_list != NULL) { 130 | delete[] (byte*)(chunk_list->data); 131 | Chunk *next = chunk_list->next; 132 | delete[] (byte*)(chunk_list); 133 | chunk_list = next; 134 | } 135 | } 136 | 137 | template 138 | void MemPool::clear() 139 | { 140 | // reset the free list 141 | free_list = nullptr; 142 | for(Chunk *chunk = chunk_list; chunk != nullptr; chunk = chunk->next) { 143 | // thread the blocks in this chunk 144 | Block *last_block = chunk->data + chunk->nBlocks - 1; 145 | for(Block *it = chunk->data; it != last_block; it++) 146 | it->next = it+1; 147 | // then push them onto the front of the free list 148 | last_block->next = free_list; 149 | free_list = chunk->data; 150 | } 151 | } 152 | 153 | template inline 154 | T* MemPool::alloc() 155 | { 156 | // if we're out of blocks, add a new chunk 157 | if(free_list == NULL) 158 | addChunk(); 159 | 160 | // pop a block off the free_list 161 | T* ret = reinterpret_cast(free_list); 162 | free_list = free_list->next; 163 | 164 | // invoke constructor on allocated block 165 | //new (ret) T(); // SEE INSTRUCTIONS AT TOP 166 | 167 | return ret; 168 | } 169 | 170 | template inline 171 | void MemPool::free(T* datum) 172 | { 173 | if(datum == NULL) return; // silent fail for freeing NULLed pointers 174 | // invoke destructor 175 | //datum->~T(); // SEE INSTRUCTIONS AT TOP 176 | 177 | Block *block = reinterpret_cast(datum); 178 | 179 | // push this block onto the front of the free_list 180 | // so it can be re-allocated in the future 181 | block->next = free_list; 182 | free_list = block; 183 | } 184 | 185 | template 186 | void MemPool::addChunk() 187 | { 188 | Chunk *new_chunk = (Chunk*)(new byte[sizeof(Chunk)]); 189 | new_chunk->next = chunk_list; 190 | // we always double the size of each new chunk. This ensures that 191 | // the total # of times that we have to add chunks is logarithmic. 192 | // Regardless, the amortized cost of chunk allocation is constant. 193 | new_chunk->nBlocks = chunk_list->nBlocks * 2; 194 | new_chunk->data = (Block*)(new byte[sizeof(Block) * 195 | (new_chunk->nBlocks)]); 196 | chunk_list = new_chunk; 197 | 198 | // now we need to lace the blocks of the fresh chunk up into the free_list 199 | Block *last_block = new_chunk->data + new_chunk->nBlocks - 1; 200 | last_block->next = free_list; 201 | free_list = new_chunk->data; 202 | for(Block *it = new_chunk->data; it != last_block; it++) 203 | it->next = it+1; 204 | } 205 | 206 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /src/util/prelude.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | prelude.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #ifndef uint 35 | typedef unsigned int uint; 36 | #endif 37 | 38 | #ifndef byte 39 | typedef unsigned char byte; 40 | #endif 41 | 42 | // *********** 43 | // * Logging 44 | 45 | // error log -- silent; will not stop program 46 | std::ostream &err(); 47 | 48 | #ifndef ENSURE 49 | #define ENSURE(STATEMENT) { \ 50 | if(!(STATEMENT)) { \ 51 | std::cerr << "ENSURE FAILED at " \ 52 | << __FILE__ << ", line #" << __LINE__ << ":\n" \ 53 | << " " << #STATEMENT << std::endl; \ 54 | err() << "ENSURE FAILED at " \ 55 | << __FILE__ << ", line #" << __LINE__ << ":\n" \ 56 | << " " << #STATEMENT << std::endl; \ 57 | exit(1); \ 58 | } \ 59 | } 60 | #endif // ENSURE 61 | 62 | // Use ERROR to print an error message tagged with the given file/line # 63 | #ifndef CORK_ERROR 64 | #define CORK_ERROR(message) { \ 65 | std::cerr << "error at " \ 66 | << __FILE__ << ", line #" << __LINE__ << ": " \ 67 | << (message) << std::endl; \ 68 | err() << "error at " \ 69 | << __FILE__ << ", line #" << __LINE__ << ": " \ 70 | << (message) << std::endl; \ 71 | } 72 | #endif // CORK_ERROR 73 | 74 | // Use MARKER for debugging to create a trace of control flow... 75 | #ifndef MARKER 76 | #define MARKER(message) { \ 77 | std::cout << "marker at " \ 78 | << __FILE__ << ", line #" << __LINE__ << ": " \ 79 | << (message) << std::endl; \ 80 | } 81 | #endif // MARKER 82 | 83 | // *********** 84 | // * Assorted 85 | 86 | // snap the value a into the specified range 87 | inline double clamp(double a, double mina, double maxa) { 88 | return std::min(maxa, std::max(mina, a)); 89 | } 90 | inline float clamp(float a, float mina, float maxa) { 91 | return std::min(maxa, std::max(mina, a)); 92 | } 93 | 94 | // modulo the value a into the specified range 95 | inline double wrap(double a, double mina, double maxa) { 96 | double val = std::fmod(a - mina, maxa - mina); 97 | if(val < 0.0) val += maxa-mina; 98 | return val + mina; 99 | } 100 | inline float wrap(float a, float mina, float maxa) { 101 | float val = std::fmod(a - mina, maxa - mina); 102 | if(val < 0.0) val += maxa-mina; 103 | return val + mina; 104 | } 105 | 106 | inline double deg2rad(double deg) { 107 | return (M_PI/180.0) * deg; 108 | } 109 | inline double rad2deg(double rad) { 110 | return (180.0/M_PI) * rad; 111 | } 112 | 113 | // ********** 114 | // * Timing 115 | 116 | #ifdef _WIN32 117 | #include 118 | #endif 119 | 120 | class Timer { 121 | public: 122 | Timer(); // automatically start timer on creation 123 | ~Timer(); 124 | public: 125 | void start(); 126 | // returns lap time in milliseconds 127 | double lap(); 128 | // returns total ellapsed time in milliseconds 129 | double stop(); 130 | // re-retrieve values 131 | // if this operation is meaningless, you will receive 0.0 instead 132 | double lastLap() const; 133 | double ellapsed() const; 134 | private: 135 | timeval init; 136 | timeval prev; 137 | double last_lap_duration; 138 | double ellapsed_time_duration; 139 | bool isRunning; 140 | }; 141 | 142 | // *********** 143 | // * Random 144 | 145 | // need functions that allow for the random source 146 | // to be made more deterministic for replays... 147 | 148 | inline void initRand() { 149 | // currently none! Should seed using clock 150 | srand(uint(time(0))); 151 | } 152 | 153 | inline double drand(double min, double max) { 154 | const double invMAX = 1.0/double(RAND_MAX); 155 | double rand0to1 = double(std::rand())*invMAX; 156 | return (max-min)*rand0to1 + min; 157 | } 158 | 159 | inline uint randMod(uint range) { 160 | return std::rand()%range; 161 | } 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /src/util/shortVec.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | shortVec.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include "prelude.h" 29 | #include "memPool.h" 30 | 31 | #include 32 | 33 | // Don't know why, but can't get this to compile 34 | // when I make the datablock def. a member of ShortVec 35 | template 36 | struct ShortVecBlock_Private { 37 | byte data[sizeof(T)*LEN]; 38 | }; 39 | // We allocate these blocks instead of typed arrays 40 | // in order to ensure that we get control of allocation/deallocation 41 | // rather than the allocator attempting to do so. 42 | 43 | template 44 | class ShortVec 45 | { 46 | public: // constructor/destructor 47 | ShortVec(uint size = 0); 48 | ShortVec(uint size, const T &fill_val); 49 | ShortVec(const ShortVec &cp); 50 | //ShortVec(ShortVec &&cp); // move constructor 51 | ~ShortVec(); 52 | 53 | ShortVec& operator=(const ShortVec &vec); 54 | 55 | public: // index accessors 56 | inline T& operator[](uint i) { return data[i]; } 57 | inline const T& operator[](uint i) const { return data[i]; } 58 | 59 | public: // iterators 60 | typedef T* iterator; 61 | typedef const T* const_iterator; 62 | iterator begin() { return data; } 63 | const_iterator begin() const { return data; } 64 | iterator end() { return data + user_size; } 65 | const_iterator end() const { return data + user_size; } 66 | 67 | public: // inspectors 68 | inline uint size() const { return user_size; } 69 | 70 | public: // modifiers 71 | void resize(uint newsize); 72 | void push_back(const T &datum); 73 | void erase(const T &val); // erase if it can be found 74 | 75 | private: // helper functions 76 | T* allocData(uint space, uint &allocated); 77 | void deallocData(T* data_ptr, uint allocated); 78 | 79 | void constructRange(T* array, int begin, int end); 80 | void copyConstructRange(T* src, T* dest, int begin, int end); 81 | void destructRange(T* array, int begin, int end); 82 | 83 | // resize, manage allocation/deallocation, 84 | // but not construction/destruction 85 | void resizeHelper(uint newsize); 86 | 87 | public: // shared data structures and data. 88 | static MemPool< ShortVecBlock_Private > pool; 89 | 90 | private: // instance data 91 | uint user_size; // actual number of entries from client perspective 92 | uint internal_size; // number of entries allocated, if greater than LEN; 93 | // if allocated from the memory pool, this is 0 94 | T* data; 95 | }; 96 | 97 | template 98 | MemPool< ShortVecBlock_Private > ShortVec::pool; 99 | 100 | template inline 101 | T* ShortVec::allocData(uint space, uint &allocated) 102 | { 103 | T* result; 104 | if(space <= LEN) { 105 | allocated = LEN; 106 | result = reinterpret_cast(pool.alloc()); 107 | } else { 108 | allocated = space; 109 | result = reinterpret_cast(new byte[sizeof(T)*space]); 110 | } 111 | //if(LEN == 2) std::cout << " Allocing: " << result << std::endl; 112 | return result; 113 | } 114 | template inline 115 | void ShortVec::deallocData(T* data_ptr, uint allocated) 116 | { 117 | //if(LEN == 2) std::cout << " Deallocing: " << data_ptr << std::endl; 118 | if(allocated <= LEN) 119 | pool.free(reinterpret_cast< ShortVecBlock_Private* >(data_ptr)); 120 | else 121 | delete[] reinterpret_cast(data_ptr); 122 | } 123 | 124 | template inline 125 | void ShortVec::constructRange(T* array, int begin, int end) 126 | { 127 | for(int i=begin; i inline 131 | void ShortVec::copyConstructRange(T* src, T* dest, int begin, int end) 132 | { 133 | // copy actual data over 134 | for(int i=begin; i inline 138 | void ShortVec::destructRange(T* array, int begin, int end) 139 | { 140 | for(int i=begin; i~T(); 142 | } 143 | 144 | // we use a strictly increasing allocation size policy 145 | // with array length doubling to ensure that the cost of 146 | // copying array entries on a reallocation has 147 | // constant amortized cost. This is important when the 148 | // vector is used to accumulate a list of values. 149 | template inline 150 | void ShortVec::resizeHelper(uint newsize) { 151 | if(newsize > internal_size) { // we need more space! 152 | // setup the new data block with at least twice as much space 153 | uint new_space; 154 | T *new_data = allocData(std::max(newsize, internal_size*2), new_space); 155 | // copy data and destroy old copies 156 | copyConstructRange(data, new_data, 0, user_size); 157 | destructRange(data, 0, user_size); 158 | // free old data 159 | deallocData(data, internal_size); 160 | data = new_data; 161 | internal_size = new_space; 162 | } 163 | user_size = newsize; 164 | } 165 | 166 | 167 | 168 | 169 | template inline 170 | ShortVec::ShortVec(uint size) : user_size(size) 171 | { 172 | data = allocData(user_size, internal_size); 173 | constructRange(data, 0, user_size); 174 | } 175 | template inline 176 | ShortVec::ShortVec(uint size, const T &fill_val) : user_size(size) 177 | { 178 | data = allocData(user_size, internal_size); 179 | // then fill 180 | for(uint i=0; i inline 184 | ShortVec::ShortVec(const ShortVec &cp) : user_size(cp.user_size) 185 | { 186 | data = allocData(user_size, internal_size); 187 | // copy actual data over 188 | copyConstructRange(cp.data, data, 0, user_size); 189 | } 190 | /*template inline 191 | ShortVec::ShortVec(ShortVec &&cp) 192 | { 193 | user_size = cp.user_size; 194 | internal_size = cp.internal_size; 195 | data = cp.data; 196 | cp.user_size = 0; // ensure that no destructors are called 197 | cp.internal_size = 0; // ensure that pool free is called 198 | cp.data = NULL; // on a null pointer, which will do nothing 199 | }*/ 200 | template inline 201 | ShortVec::~ShortVec() 202 | { 203 | destructRange(data, 0, user_size); 204 | deallocData(data, internal_size); 205 | } 206 | 207 | template inline 208 | ShortVec& ShortVec::operator=(const ShortVec &vec) 209 | { 210 | uint old_size = user_size; 211 | 212 | // ensure there is enough space allocated at the destination 213 | resizeHelper(vec.user_size); 214 | 215 | // copy assignment for all data in range overlap 216 | for(uint i=0; i old_size) { 222 | copyConstructRange(vec.data, data, old_size, vec.user_size); 223 | } 224 | 225 | // if the new range is smaller, destruct old unused entries 226 | if(vec.user_size < old_size) 227 | destructRange(data, vec.user_size, old_size); 228 | 229 | return *this; 230 | } 231 | 232 | template inline 233 | void ShortVec::resize(uint newsize) { 234 | uint oldsize = user_size; 235 | 236 | resizeHelper(newsize); 237 | 238 | if(oldsize < newsize) 239 | constructRange(data, oldsize, newsize); 240 | 241 | if(newsize < oldsize) 242 | destructRange(data, newsize, oldsize); 243 | } 244 | 245 | template inline 246 | void ShortVec::push_back(const T &datum) 247 | { 248 | uint i = user_size; 249 | resizeHelper(user_size+1); // make room 250 | new (&(data[i])) T(datum); 251 | } 252 | 253 | template inline 254 | void ShortVec::erase(const T &val) 255 | { 256 | for(uint i=0; i. 25 | // +------------------------------------------------------------------------- 26 | #include "prelude.h" 27 | 28 | #ifdef _WIN32 29 | #include 30 | #include 31 | void gettimeofday(struct timeval* t,void* timezone) 32 | { struct _timeb timebuffer; 33 | _ftime( &timebuffer ); 34 | t->tv_sec=timebuffer.time; 35 | t->tv_usec=1000*timebuffer.millitm; 36 | } 37 | #else 38 | #include 39 | #endif 40 | 41 | 42 | 43 | 44 | 45 | Timer::Timer() 46 | { 47 | start(); 48 | } 49 | Timer::~Timer() 50 | { 51 | } 52 | 53 | inline 54 | double timeDiff(const timeval &t0, const timeval &t1) 55 | { 56 | double ms = (t1.tv_sec - t0.tv_sec) * 1000.0 57 | + (t1.tv_usec - t0.tv_usec) / 1000.0; 58 | return ms; 59 | } 60 | 61 | void Timer::start() 62 | { 63 | gettimeofday(&init, NULL); 64 | prev = init; 65 | last_lap_duration = ellapsed_time_duration = 0.0; 66 | isRunning = true; 67 | } 68 | // returns lap time in milliseconds 69 | double Timer::lap() 70 | { 71 | if(!isRunning) 72 | return 0.0; 73 | 74 | timeval now; 75 | gettimeofday(&now, NULL); 76 | 77 | last_lap_duration = timeDiff(prev, now); 78 | return last_lap_duration; 79 | } 80 | // returns total ellapsed time in milliseconds 81 | double Timer::stop() 82 | { 83 | if(!isRunning) 84 | return 0.0; 85 | 86 | timeval now; 87 | gettimeofday(&now, NULL); 88 | 89 | last_lap_duration = timeDiff(prev, now); 90 | ellapsed_time_duration = timeDiff(init, now); 91 | 92 | isRunning = false; 93 | return ellapsed_time_duration; 94 | } 95 | // re-retrieve values 96 | double Timer::lastLap() const 97 | { 98 | return last_lap_duration; 99 | } 100 | double Timer::ellapsed() const 101 | { 102 | return ellapsed_time_duration; 103 | } 104 | -------------------------------------------------------------------------------- /src/util/unionFind.h: -------------------------------------------------------------------------------- 1 | // +------------------------------------------------------------------------- 2 | // | unionFind.h 3 | // | 4 | // | Author: Gilbert Bernstein 5 | // +------------------------------------------------------------------------- 6 | // | COPYRIGHT: 7 | // | Copyright Gilbert Bernstein 2013 8 | // | See the included COPYRIGHT file for further details. 9 | // | 10 | // | This file is part of the Cork library. 11 | // | 12 | // | Cork is free software: you can redistribute it and/or modify 13 | // | it under the terms of the GNU Lesser General Public License as 14 | // | published by the Free Software Foundation, either version 3 of 15 | // | the License, or (at your option) any later version. 16 | // | 17 | // | Cork is distributed in the hope that it will be useful, 18 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // | GNU Lesser General Public License for more details. 21 | // | 22 | // | You should have received a copy 23 | // | of the GNU Lesser General Public License 24 | // | along with Cork. If not, see . 25 | // +------------------------------------------------------------------------- 26 | #pragma once 27 | 28 | #include "prelude.h" 29 | 30 | class UnionFind { 31 | public: 32 | UnionFind(uint N) : ids(N), rank(N, 0) { 33 | for(uint i=0; i rank[jid]) { 53 | return ids[jid] = iid; 54 | } else if(rank[iid] < rank[jid]) { 55 | return ids[iid] = jid; 56 | } else { // equal ranks 57 | rank[jid]++; 58 | return ids[jid] = iid; 59 | } 60 | } 61 | std::vector dump() { 62 | std::vector result(ids.size()); 63 | for(uint i=0; i ids; 70 | std::vector rank; 71 | }; 72 | -------------------------------------------------------------------------------- /win/wincork/wincork.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2012 for Windows Desktop 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wincork", "wincork.vcxproj", "{AD6B1A8B-6983-40ED-9EF2-A7FFC457517E}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {AD6B1A8B-6983-40ED-9EF2-A7FFC457517E}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {AD6B1A8B-6983-40ED-9EF2-A7FFC457517E}.Debug|Win32.Build.0 = Debug|Win32 14 | {AD6B1A8B-6983-40ED-9EF2-A7FFC457517E}.Release|Win32.ActiveCfg = Release|Win32 15 | {AD6B1A8B-6983-40ED-9EF2-A7FFC457517E}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /win/wincork/wincork.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {AD6B1A8B-6983-40ED-9EF2-A7FFC457517E} 15 | wincork 16 | 17 | 18 | 19 | Application 20 | true 21 | v110 22 | MultiByte 23 | 24 | 25 | Application 26 | false 27 | v110 28 | true 29 | MultiByte 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Level3 45 | Disabled 46 | C:\Users\Gilbert\Documents\GitHub\cork\src;C:\Users\Gilbert\Documents\GitHub\cork\src\accel;C:\Users\Gilbert\Documents\GitHub\cork\src\file_formats;C:\Users\Gilbert\Documents\GitHub\cork\src\isct;C:\Users\Gilbert\Documents\GitHub\cork\src\math;C:\Users\Gilbert\Documents\GitHub\cork\src\mesh;C:\Users\Gilbert\Documents\GitHub\cork\src\rawmesh;C:\Users\Gilbert\Documents\GitHub\cork\src\util;%(AdditionalIncludeDirectories) 47 | _USE_MATH_DEFINES;NOMINMAX;%(PreprocessorDefinitions) 48 | MultiThreadedDebugDLL 49 | 50 | 51 | true 52 | mpir.lib %(AdditionalOptions) 53 | 54 | 55 | 56 | 57 | Level3 58 | MaxSpeed 59 | true 60 | true 61 | C:\Users\Gilbert\Documents\GitHub\cork\src;C:\Users\Gilbert\Documents\GitHub\cork\src\accel;C:\Users\Gilbert\Documents\GitHub\cork\src\file_formats;C:\Users\Gilbert\Documents\GitHub\cork\src\isct;C:\Users\Gilbert\Documents\GitHub\cork\src\math;C:\Users\Gilbert\Documents\GitHub\cork\src\mesh;C:\Users\Gilbert\Documents\GitHub\cork\src\rawmesh;C:\Users\Gilbert\Documents\GitHub\cork\src\util;%(AdditionalIncludeDirectories) 62 | _USE_MATH_DEFINES;NOMINMAX;%(PreprocessorDefinitions) 63 | 64 | 65 | true 66 | true 67 | true 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | NO_TIMER;REDUCED;CDT_ONLY;TRILIBRARY;ANSI_DECLARATORS;%(PreprocessorDefinitions) 112 | NO_TIMER;REDUCED;CDT_ONLY;TRILIBRARY;ANSI_DECLARATORS;%(PreprocessorDefinitions) 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /win/wincork/wincork.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {9ae3a789-4b69-4209-b7a9-bd6f776a99db} 18 | 19 | 20 | {dffee6af-cc73-4111-aea0-1e3c33e7d946} 21 | 22 | 23 | {c9671371-9658-48e8-8e42-42c0529667b5} 24 | 25 | 26 | {c4a6b75d-ab40-4390-976e-e7c11d100c68} 27 | 28 | 29 | {23d6d0a6-6cef-4390-a8c6-227728f144fd} 30 | 31 | 32 | {6dae34f2-75d2-4bc3-8697-d959520be5fb} 33 | 34 | 35 | {53f3b672-20eb-4a96-b7af-0b93d0b58d33} 36 | 37 | 38 | {a44d6a76-9c77-490c-a481-64fa326ba037} 39 | 40 | 41 | {3bafd8b3-8406-4070-84a2-41a5f27cbde1} 42 | 43 | 44 | {8ef4296c-8c21-47d0-9033-e0d7e3d67549} 45 | 46 | 47 | 48 | 49 | Header Files\accel 50 | 51 | 52 | Header Files\mesh 53 | 54 | 55 | Header Files\mesh 56 | 57 | 58 | Header Files\rawmesh 59 | 60 | 61 | Header Files\math 62 | 63 | 64 | Header Files\math 65 | 66 | 67 | Header Files\math 68 | 69 | 70 | Header Files\util 71 | 72 | 73 | Header Files\util 74 | 75 | 76 | Header Files\util 77 | 78 | 79 | Header Files\util 80 | 81 | 82 | Header Files\util 83 | 84 | 85 | Header Files\file_formats 86 | 87 | 88 | Header Files\isct 89 | 90 | 91 | Header Files\isct 92 | 93 | 94 | Header Files\isct 95 | 96 | 97 | Header Files\isct 98 | 99 | 100 | Header Files\isct 101 | 102 | 103 | Header Files\isct 104 | 105 | 106 | Header Files\isct 107 | 108 | 109 | Header Files\isct 110 | 111 | 112 | Header Files\isct 113 | 114 | 115 | Header Files 116 | 117 | 118 | 119 | 120 | Header Files\mesh 121 | 122 | 123 | Header Files\mesh 124 | 125 | 126 | Header Files\mesh 127 | 128 | 129 | Header Files\mesh 130 | 131 | 132 | Header Files\mesh 133 | 134 | 135 | Header Files\rawmesh 136 | 137 | 138 | 139 | 140 | Source Files\util 141 | 142 | 143 | Source Files\util 144 | 145 | 146 | Source Files\file_formats 147 | 148 | 149 | Source Files\file_formats 150 | 151 | 152 | Source Files\file_formats 153 | 154 | 155 | Source Files\isct 156 | 157 | 158 | Source Files\isct 159 | 160 | 161 | Source Files\isct 162 | 163 | 164 | Source Files 165 | 166 | 167 | Source Files 168 | 169 | 170 | --------------------------------------------------------------------------------