├── .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