Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2018-02-08 18:27:28 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2018-02-08 18:27:28 +0300
commit92786141159430fa36e59e0229e4bbb84f2f04be (patch)
treedd93e8f2a611ecbbc05646533798e97354d0f34e
parentbdc708762cf0fe0490bee3cf8452446da46d342a (diff)
parente0597baed57fa7a9dfaf6dff6d0fa120784d21ea (diff)
Merge branch 'master' into blender2.8
-rw-r--r--CMakeLists.txt5
-rw-r--r--build_files/cmake/config/blender_full.cmake1
-rw-r--r--build_files/cmake/config/blender_lite.cmake1
-rw-r--r--build_files/cmake/config/blender_release.cmake1
-rw-r--r--build_files/cmake/macros.cmake4
-rw-r--r--extern/CMakeLists.txt4
-rw-r--r--extern/carve/CMakeLists.txt170
-rw-r--r--extern/carve/LICENSE.GPL2361
-rw-r--r--extern/carve/LICENSE.GPL3674
-rw-r--r--extern/carve/README.blender4
-rwxr-xr-xextern/carve/bundle.sh105
-rw-r--r--extern/carve/carve-capi.cc994
-rw-r--r--extern/carve/carve-capi.h164
-rw-r--r--extern/carve/carve-util.cc838
-rw-r--r--extern/carve/carve-util.h300
-rw-r--r--extern/carve/files.txt107
-rw-r--r--extern/carve/include/carve/aabb.hpp156
-rw-r--r--extern/carve/include/carve/aabb_impl.hpp440
-rw-r--r--extern/carve/include/carve/carve.hpp238
-rw-r--r--extern/carve/include/carve/cbrt.h93
-rw-r--r--extern/carve/include/carve/classification.hpp115
-rw-r--r--extern/carve/include/carve/collection.hpp51
-rw-r--r--extern/carve/include/carve/collection/unordered.hpp43
-rw-r--r--extern/carve/include/carve/collection/unordered/boost_impl.hpp45
-rw-r--r--extern/carve/include/carve/collection/unordered/fallback_impl.hpp40
-rw-r--r--extern/carve/include/carve/collection/unordered/libstdcpp_impl.hpp61
-rw-r--r--extern/carve/include/carve/collection/unordered/std_impl.hpp23
-rw-r--r--extern/carve/include/carve/collection/unordered/tr1_impl.hpp58
-rw-r--r--extern/carve/include/carve/collection/unordered/vcpp_impl.hpp65
-rw-r--r--extern/carve/include/carve/collection_types.hpp63
-rw-r--r--extern/carve/include/carve/colour.hpp47
-rw-r--r--extern/carve/include/carve/config.h30
-rw-r--r--extern/carve/include/carve/convex_hull.hpp52
-rw-r--r--extern/carve/include/carve/csg.hpp510
-rw-r--r--extern/carve/include/carve/csg_triangulator.hpp435
-rw-r--r--extern/carve/include/carve/debug_hooks.hpp97
-rw-r--r--extern/carve/include/carve/djset.hpp134
-rw-r--r--extern/carve/include/carve/edge_decl.hpp68
-rw-r--r--extern/carve/include/carve/edge_impl.hpp23
-rw-r--r--extern/carve/include/carve/exact.hpp704
-rw-r--r--extern/carve/include/carve/face_decl.hpp208
-rw-r--r--extern/carve/include/carve/face_impl.hpp142
-rw-r--r--extern/carve/include/carve/faceloop.hpp103
-rw-r--r--extern/carve/include/carve/geom.hpp367
-rw-r--r--extern/carve/include/carve/geom2d.hpp403
-rw-r--r--extern/carve/include/carve/geom3d.hpp324
-rw-r--r--extern/carve/include/carve/geom_impl.hpp672
-rw-r--r--extern/carve/include/carve/gnu_cxx.h4
-rw-r--r--extern/carve/include/carve/heap.hpp425
-rw-r--r--extern/carve/include/carve/input.hpp304
-rw-r--r--extern/carve/include/carve/interpolator.hpp513
-rw-r--r--extern/carve/include/carve/intersection.hpp267
-rw-r--r--extern/carve/include/carve/iobj.hpp106
-rw-r--r--extern/carve/include/carve/kd_node.hpp308
-rw-r--r--extern/carve/include/carve/math.hpp60
-rw-r--r--extern/carve/include/carve/math_constants.hpp33
-rw-r--r--extern/carve/include/carve/matrix.hpp262
-rw-r--r--extern/carve/include/carve/mesh.hpp874
-rw-r--r--extern/carve/include/carve/mesh_impl.hpp1098
-rw-r--r--extern/carve/include/carve/mesh_ops.hpp975
-rw-r--r--extern/carve/include/carve/mesh_simplify.hpp1599
-rw-r--r--extern/carve/include/carve/octree_decl.hpp193
-rw-r--r--extern/carve/include/carve/octree_impl.hpp79
-rw-r--r--extern/carve/include/carve/pointset.hpp24
-rw-r--r--extern/carve/include/carve/pointset_decl.hpp61
-rw-r--r--extern/carve/include/carve/pointset_impl.hpp36
-rw-r--r--extern/carve/include/carve/pointset_iter.hpp18
-rw-r--r--extern/carve/include/carve/poly.hpp24
-rw-r--r--extern/carve/include/carve/poly_decl.hpp25
-rw-r--r--extern/carve/include/carve/poly_impl.hpp25
-rw-r--r--extern/carve/include/carve/polyhedron_base.hpp149
-rw-r--r--extern/carve/include/carve/polyhedron_decl.hpp184
-rw-r--r--extern/carve/include/carve/polyhedron_impl.hpp286
-rw-r--r--extern/carve/include/carve/polyline.hpp24
-rw-r--r--extern/carve/include/carve/polyline_decl.hpp156
-rw-r--r--extern/carve/include/carve/polyline_impl.hpp160
-rw-r--r--extern/carve/include/carve/polyline_iter.hpp203
-rw-r--r--extern/carve/include/carve/random/random.h61
-rw-r--r--extern/carve/include/carve/rescale.hpp100
-rw-r--r--extern/carve/include/carve/rtree.hpp514
-rw-r--r--extern/carve/include/carve/spacetree.hpp264
-rw-r--r--extern/carve/include/carve/tag.hpp44
-rw-r--r--extern/carve/include/carve/timing.hpp96
-rw-r--r--extern/carve/include/carve/tree.hpp324
-rw-r--r--extern/carve/include/carve/triangle_intersection.hpp53
-rw-r--r--extern/carve/include/carve/triangulator.hpp175
-rw-r--r--extern/carve/include/carve/triangulator_impl.hpp851
-rw-r--r--extern/carve/include/carve/util.hpp31
-rw-r--r--extern/carve/include/carve/vcpp_config.h17
-rw-r--r--extern/carve/include/carve/vector.hpp163
-rw-r--r--extern/carve/include/carve/vertex_decl.hpp111
-rw-r--r--extern/carve/include/carve/vertex_impl.hpp24
-rwxr-xr-xextern/carve/include/carve/win32.h58
-rw-r--r--extern/carve/lib/carve.cpp29
-rw-r--r--extern/carve/lib/convex_hull.cpp100
-rw-r--r--extern/carve/lib/csg.cpp93
-rw-r--r--extern/carve/lib/csg_collector.cpp372
-rw-r--r--extern/carve/lib/csg_collector.hpp24
-rw-r--r--extern/carve/lib/csg_data.hpp52
-rw-r--r--extern/carve/lib/csg_detail.hpp73
-rw-r--r--extern/carve/lib/face.cpp286
-rw-r--r--extern/carve/lib/geom2d.cpp266
-rw-r--r--extern/carve/lib/geom3d.cpp166
-rw-r--r--extern/carve/lib/intersect.cpp1735
-rw-r--r--extern/carve/lib/intersect_classify_common.hpp46
-rw-r--r--extern/carve/lib/intersect_classify_common_impl.hpp362
-rw-r--r--extern/carve/lib/intersect_classify_edge.cpp823
-rw-r--r--extern/carve/lib/intersect_classify_group.cpp220
-rw-r--r--extern/carve/lib/intersect_common.hpp83
-rw-r--r--extern/carve/lib/intersect_debug.cpp65
-rw-r--r--extern/carve/lib/intersect_debug.hpp29
-rw-r--r--extern/carve/lib/intersect_face_division.cpp1765
-rw-r--r--extern/carve/lib/intersect_group.cpp232
-rw-r--r--extern/carve/lib/intersect_half_classify_group.cpp199
-rw-r--r--extern/carve/lib/intersection.cpp92
-rw-r--r--extern/carve/lib/math.cpp355
-rw-r--r--extern/carve/lib/mesh.cpp1215
-rw-r--r--extern/carve/lib/octree.cpp399
-rw-r--r--extern/carve/lib/pointset.cpp59
-rw-r--r--extern/carve/lib/polyhedron.cpp1107
-rw-r--r--extern/carve/lib/polyline.cpp67
-rw-r--r--extern/carve/lib/tag.cpp24
-rw-r--r--extern/carve/lib/timing.cpp436
-rw-r--r--extern/carve/lib/triangulator.cpp1200
-rwxr-xr-xextern/carve/mkfiles.sh4
-rw-r--r--extern/carve/patches/clang_is_heap_fix.patch32
-rw-r--r--extern/carve/patches/face_hole_merge_workaround.patch14
-rw-r--r--extern/carve/patches/files/config.h30
-rw-r--r--extern/carve/patches/files/random.h61
-rw-r--r--extern/carve/patches/gcc46.patch11
-rw-r--r--extern/carve/patches/includes.patch84
-rw-r--r--extern/carve/patches/interpolator_reorder.patch12
-rw-r--r--extern/carve/patches/memory_leak_fix.patch11
-rw-r--r--extern/carve/patches/mesh_iterator.patch21
-rw-r--r--extern/carve/patches/mesh_simplify_dissolve_edges.patch64
-rw-r--r--extern/carve/patches/mesh_simplify_uninitialized_var.patch12
-rw-r--r--extern/carve/patches/msvc_fix.patch14
-rw-r--r--extern/carve/patches/random.patch16
-rw-r--r--extern/carve/patches/series13
-rw-r--r--extern/carve/patches/strict_flags.patch439
-rw-r--r--extern/carve/patches/win32.patch37
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py16
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h8
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c11
-rw-r--r--source/blender/modifiers/CMakeLists.txt11
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c106
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.c790
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.h46
-rw-r--r--source/blender/python/intern/CMakeLists.txt4
-rw-r--r--source/blender/python/intern/bpy_app_build_options.c7
-rw-r--r--source/blenderplayer/CMakeLists.txt4
151 files changed, 9 insertions, 34747 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 650f5ec4ff2..0ce35da95f1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -312,7 +312,6 @@ endif()
# Modifiers
option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON)
option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON)
-option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON)
option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
# option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF) # this is now only available in a branch
# mark_as_advanced(WITH_MOD_CLOTH_ELTOPO)
@@ -639,9 +638,8 @@ if(NOT WITH_BOOST)
set_and_warn(WITH_INTERNATIONAL OFF)
set_and_warn(WITH_OPENVDB OFF)
set_and_warn(WITH_OPENCOLORIO OFF)
- set_and_warn(WITH_MOD_BOOLEAN OFF)
elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR
- WITH_OPENVDB OR WITH_OPENCOLORIO OR WITH_MOD_BOOLEAN)
+ WITH_OPENVDB OR WITH_OPENCOLORIO)
# Keep enabled
else()
# New dependency graph needs either Boost or C++11 for function bindings.
@@ -1710,7 +1708,6 @@ if(FIRST_RUN)
endif()
info_cfg_text("Modifiers:")
- info_cfg_option(WITH_MOD_BOOLEAN)
info_cfg_option(WITH_MOD_REMESH)
info_cfg_option(WITH_MOD_FLUID)
info_cfg_option(WITH_MOD_OCEANSIM)
diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake
index 35eba1e6a41..c896c0452b3 100644
--- a/build_files/cmake/config/blender_full.cmake
+++ b/build_files/cmake/config/blender_full.cmake
@@ -34,7 +34,6 @@ set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE)
set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_LZMA ON CACHE BOOL "" FORCE)
set(WITH_LZO ON CACHE BOOL "" FORCE)
-set(WITH_MOD_BOOLEAN ON CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_MOD_SMOKE ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index 98818d4ab50..7db26c3f7c0 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -38,7 +38,6 @@ set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE)
set(WITH_JACK OFF CACHE BOOL "" FORCE)
set(WITH_LZMA OFF CACHE BOOL "" FORCE)
set(WITH_LZO OFF CACHE BOOL "" FORCE)
-set(WITH_MOD_BOOLEAN OFF CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID OFF CACHE BOOL "" FORCE)
set(WITH_MOD_REMESH OFF CACHE BOOL "" FORCE)
set(WITH_MOD_SMOKE OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake
index 3cdbfdfcf3b..1d1793e0aba 100644
--- a/build_files/cmake/config/blender_release.cmake
+++ b/build_files/cmake/config/blender_release.cmake
@@ -34,7 +34,6 @@ set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE)
set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_LZMA ON CACHE BOOL "" FORCE)
set(WITH_LZO ON CACHE BOOL "" FORCE)
-set(WITH_MOD_BOOLEAN ON CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_MOD_SMOKE ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 6f014d7eb3b..09bc01fcae3 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -736,10 +736,6 @@ function(SETUP_BLENDER_SORTED_LIBS)
list(APPEND BLENDER_SORTED_LIBS bf_intern_itasc)
endif()
- if(WITH_MOD_BOOLEAN)
- list(APPEND BLENDER_SORTED_LIBS extern_carve)
- endif()
-
if(WITH_GHOST_XDND)
list(APPEND BLENDER_SORTED_LIBS extern_xdnd)
endif()
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 65958eee6f7..54d3275b760 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -86,10 +86,6 @@ if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
endif()
endif()
-if(WITH_MOD_BOOLEAN)
- add_subdirectory(carve)
-endif()
-
if(WITH_X11 AND WITH_GHOST_XDND)
add_subdirectory(xdnd)
endif()
diff --git a/extern/carve/CMakeLists.txt b/extern/carve/CMakeLists.txt
deleted file mode 100644
index bb81332917e..00000000000
--- a/extern/carve/CMakeLists.txt
+++ /dev/null
@@ -1,170 +0,0 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# The Original Code is Copyright (C) 2006, Blender Foundation
-# All rights reserved.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): Jacques Beaurai, Erwin Coumans
-#
-# ***** END GPL LICENSE BLOCK *****
-
-# NOTE: This file is automatically generated by bundle.sh script
-# If you're doing changes in this file, please update template
-# in that script too
-
-set(INC
- include
-)
-
-set(INC_SYS
-)
-
-set(SRC
- carve-capi.cc
- carve-util.cc
- lib/carve.cpp
- lib/convex_hull.cpp
- lib/csg_collector.cpp
- lib/csg.cpp
- lib/face.cpp
- lib/geom2d.cpp
- lib/geom3d.cpp
- lib/intersect_classify_edge.cpp
- lib/intersect_classify_group.cpp
- lib/intersect.cpp
- lib/intersect_debug.cpp
- lib/intersect_face_division.cpp
- lib/intersect_group.cpp
- lib/intersect_half_classify_group.cpp
- lib/intersection.cpp
- lib/math.cpp
- lib/mesh.cpp
- lib/octree.cpp
- lib/pointset.cpp
- lib/polyhedron.cpp
- lib/polyline.cpp
- lib/tag.cpp
- lib/timing.cpp
- lib/triangulator.cpp
-
- carve-capi.h
- carve-util.h
- lib/csg_collector.hpp
- lib/csg_data.hpp
- lib/csg_detail.hpp
- lib/intersect_classify_common.hpp
- lib/intersect_classify_common_impl.hpp
- lib/intersect_common.hpp
- lib/intersect_debug.hpp
-
- include/carve/aabb.hpp
- include/carve/aabb_impl.hpp
- include/carve/carve.hpp
- include/carve/cbrt.h
- include/carve/classification.hpp
- include/carve/collection.hpp
- include/carve/collection_types.hpp
- include/carve/collection/unordered/boost_impl.hpp
- include/carve/collection/unordered/fallback_impl.hpp
- include/carve/collection/unordered.hpp
- include/carve/collection/unordered/libstdcpp_impl.hpp
- include/carve/collection/unordered/std_impl.hpp
- include/carve/collection/unordered/tr1_impl.hpp
- include/carve/collection/unordered/vcpp_impl.hpp
- include/carve/colour.hpp
- include/carve/convex_hull.hpp
- include/carve/csg.hpp
- include/carve/csg_triangulator.hpp
- include/carve/debug_hooks.hpp
- include/carve/djset.hpp
- include/carve/edge_decl.hpp
- include/carve/edge_impl.hpp
- include/carve/exact.hpp
- include/carve/face_decl.hpp
- include/carve/face_impl.hpp
- include/carve/faceloop.hpp
- include/carve/geom2d.hpp
- include/carve/geom3d.hpp
- include/carve/geom.hpp
- include/carve/geom_impl.hpp
- include/carve/gnu_cxx.h
- include/carve/heap.hpp
- include/carve/input.hpp
- include/carve/interpolator.hpp
- include/carve/intersection.hpp
- include/carve/iobj.hpp
- include/carve/kd_node.hpp
- include/carve/math_constants.hpp
- include/carve/math.hpp
- include/carve/matrix.hpp
- include/carve/mesh.hpp
- include/carve/mesh_impl.hpp
- include/carve/mesh_ops.hpp
- include/carve/mesh_simplify.hpp
- include/carve/octree_decl.hpp
- include/carve/octree_impl.hpp
- include/carve/pointset_decl.hpp
- include/carve/pointset.hpp
- include/carve/pointset_impl.hpp
- include/carve/pointset_iter.hpp
- include/carve/poly_decl.hpp
- include/carve/polyhedron_base.hpp
- include/carve/polyhedron_decl.hpp
- include/carve/polyhedron_impl.hpp
- include/carve/poly.hpp
- include/carve/poly_impl.hpp
- include/carve/polyline_decl.hpp
- include/carve/polyline.hpp
- include/carve/polyline_impl.hpp
- include/carve/polyline_iter.hpp
- include/carve/rescale.hpp
- include/carve/rtree.hpp
- include/carve/spacetree.hpp
- include/carve/tag.hpp
- include/carve/timing.hpp
- include/carve/tree.hpp
- include/carve/triangle_intersection.hpp
- include/carve/triangulator.hpp
- include/carve/triangulator_impl.hpp
- include/carve/util.hpp
- include/carve/vcpp_config.h
- include/carve/vector.hpp
- include/carve/vertex_decl.hpp
- include/carve/vertex_impl.hpp
- include/carve/win32.h
-)
-
-if(WITH_BOOST)
- if(NOT MSVC)
- # Boost is setting as preferred collections library in the Carve code when using MSVC compiler
- add_definitions(
- -DHAVE_BOOST_UNORDERED_COLLECTIONS
- )
- endif()
-
- add_definitions(
- -DCARVE_SYSTEM_BOOST
- -DHAVE_BOOST_LIBRARY
- )
-
- list(APPEND INC_SYS
- ${BOOST_INCLUDE_DIR}
- )
-endif()
-
-blender_add_lib(extern_carve "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/carve/LICENSE.GPL2 b/extern/carve/LICENSE.GPL2
deleted file mode 100644
index 792acb92f6a..00000000000
--- a/extern/carve/LICENSE.GPL2
+++ /dev/null
@@ -1,361 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
-
- The Qt GUI Toolkit is Copyright (C) 1994-2008 Trolltech ASA.
-
- You may use, distribute and copy the Qt GUI Toolkit under the terms of
- GNU General Public License version 2, which is displayed below.
-
--------------------------------------------------------------------------
-
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
--------------------------------------------------------------------------
-
-In addition, as a special exception, Trolltech gives permission to link the
-code of its release of Qt with the OpenSSL project's "OpenSSL" library (or
-modified versions of it that use the same license as the "OpenSSL"
-library), and distribute the linked executables. You must comply with the GNU
-General Public License version 2 or the GNU General Public License version 3
-in all respects for all of the code used other than the "OpenSSL" code. If
-you modify this file, you may extend this exception to your version of the
-file, but you are not obligated to do so. If you do not wish to do so,
-delete this exception statement from your version of this file.
diff --git a/extern/carve/LICENSE.GPL3 b/extern/carve/LICENSE.GPL3
deleted file mode 100644
index 94a9ed024d3..00000000000
--- a/extern/carve/LICENSE.GPL3
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- <program> Copyright (C) <year> <name of author>
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/extern/carve/README.blender b/extern/carve/README.blender
deleted file mode 100644
index 80be40ae558..00000000000
--- a/extern/carve/README.blender
+++ /dev/null
@@ -1,4 +0,0 @@
-Project: Carve, CSG library
-URL: https://code.google.com/archive/p/carve/
-Upstream version 9a85d733a43d
-Local modifications: See patches/ folder
diff --git a/extern/carve/bundle.sh b/extern/carve/bundle.sh
deleted file mode 100755
index 00de08ea93c..00000000000
--- a/extern/carve/bundle.sh
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/bin/sh
-
-if [ "x$1" = "x--i-really-know-what-im-doing" ] ; then
- echo Proceeding as requested by command line ...
-else
- echo "*** Please run again with --i-really-know-what-im-doing ..."
- exit 1
-fi
-
-tmp=`mktemp -d`
-
-hg clone https://code.google.com/p/carve/ $tmp/carve
-
-for p in `cat ./patches/series`; do
- echo "Applying patch $p..."
- cat ./patches/$p | patch -d $tmp/carve -p1
-done
-
-find include -type f -not -iwholename '*.svn*' -exec rm -rf {} \;
-find lib -type f -not -iwholename '*.svn*' -exec rm -rf {} \;
-
-cat "files.txt" | while read f; do
- mkdir -p `dirname $f`
- cp $tmp/carve/$f $f
-done
-
-rm -rf $tmp
-
-sources=`find ./lib -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | sort -d`
-headers=`find ./lib -type f -iname '*.h' -or -iname '*.hpp' | sed -r 's/^\.\//\t/' | sort -d`
-includes=`find ./include -type f -iname '*.h' -or -iname '*.hpp' | sed -r 's/^\.\//\t/' | sort -d`
-
-cp patches/files/config.h include/carve/config.h
-mkdir -p include/carve/random
-cp patches/files/random.h include/carve/random/random.h
-
-cat > CMakeLists.txt << EOF
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# The Original Code is Copyright (C) 2006, Blender Foundation
-# All rights reserved.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): Jacques Beaurai, Erwin Coumans
-#
-# ***** END GPL LICENSE BLOCK *****
-
-# NOTE: This file is automatically generated by bundle.sh script
-# If you're doing changes in this file, please update template
-# in that script too
-
-set(INC
- include
-)
-
-set(INC_SYS
-)
-
-set(SRC
- carve-capi.cc
- carve-util.cc
-${sources}
-
- carve-capi.h
- carve-util.h
-${headers}
-
-${includes}
-)
-
-if(WITH_BOOST)
- if(NOT MSVC)
- # Boost is setting as preferred collections library in the Carve code when using MSVC compiler
- add_definitions(
- -DHAVE_BOOST_UNORDERED_COLLECTIONS
- )
- endif()
-
- add_definitions(
- -DCARVE_SYSTEM_BOOST
- -DHAVE_BOOST_LIBRARY
- )
-
- list(APPEND INC_SYS
- \${BOOST_INCLUDE_DIR}
- )
-endif()
-
-blender_add_lib(extern_carve "\${SRC}" "\${INC}" "\${INC_SYS}")
-EOF
diff --git a/extern/carve/carve-capi.cc b/extern/carve/carve-capi.cc
deleted file mode 100644
index d6666a52c10..00000000000
--- a/extern/carve/carve-capi.cc
+++ /dev/null
@@ -1,994 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation,
- * Sergey Sharybin
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "carve-capi.h"
-#include "carve-util.h"
-
-#include <carve/interpolator.hpp>
-#include <carve/rescale.hpp>
-#include <carve/csg_triangulator.hpp>
-#include <carve/mesh_simplify.hpp>
-
-using carve::mesh::MeshSet;
-
-typedef std::pair<int, int> OrigIndex;
-typedef std::pair<MeshSet<3>::vertex_t *, MeshSet<3>::vertex_t *> VertexPair;
-typedef carve::interpolate::VertexAttr<OrigIndex> OrigVertMapping;
-typedef carve::interpolate::FaceAttr<OrigIndex> OrigFaceMapping;
-typedef carve::interpolate::SwapableFaceEdgeAttr<OrigIndex> OrigFaceEdgeMapping;
-typedef carve::interpolate::SimpleFaceEdgeAttr<bool> FaceEdgeTriangulatedFlag;
-
-typedef struct CarveMeshDescr {
- // Stores mesh data itself.
- MeshSet<3> *poly;
-
- // N-th element of the vector indicates index of an original mesh loop.
- std::unordered_map<std::pair<int, int>, int> orig_loop_index_map;
-
- // Mapping from carve face to an original face index in DM.
- std::unordered_map<const MeshSet<3>::face_t *, int> orig_poly_index_map;
-
- // The folloving mapping is only filled in for output mesh.
-
- // Mapping from the face verts back to original vert index.
- OrigVertMapping orig_vert_mapping;
-
- // Mapping from the face edges back to (original edge index, original loop index).
- OrigFaceEdgeMapping orig_face_edge_mapping;
-
- FaceEdgeTriangulatedFlag face_edge_triangulated_flag;
-
- // Mapping from the faces back to original poly index.
- OrigFaceMapping orig_face_mapping;
-} CarveMeshDescr;
-
-namespace {
-
-template <typename T1, typename T2>
-void edgeIndexMap_put(std::unordered_map<std::pair<T1, T1>, T2> *edge_map,
- const T1 &v1,
- const T1 &v2,
- const T2 &index)
-{
- if (v1 < v2) {
- (*edge_map)[std::make_pair(v1, v2)] = index;
- }
- else {
- (*edge_map)[std::make_pair(v2, v1)] = index;
- }
-}
-
-template <typename T1, typename T2>
-const T2 &edgeIndexMap_get(const std::unordered_map<std::pair<T1, T1>, T2> &edge_map,
- const T1 &v1,
- const T1 &v2)
-{
- typedef std::unordered_map<std::pair<T1, T1>, T2> Map;
- typename Map::const_iterator found;
-
- if (v1 < v2) {
- found = edge_map.find(std::make_pair(v1, v2));
- }
- else {
- found = edge_map.find(std::make_pair(v2, v1));
- }
-
- assert(found != edge_map.end());
- return found->second;
-}
-
-template <typename T1, typename T2>
-bool edgeIndexMap_get_if_exists(const std::unordered_map<std::pair<T1, T1>, T2> &edge_map,
- const T1 &v1,
- const T1 &v2,
- T2 *out)
-{
- typedef std::unordered_map<std::pair<T1, T1>, T2> Map;
- typename Map::const_iterator found;
-
- if (v1 < v2) {
- found = edge_map.find(std::make_pair(v1, v2));
- }
- else {
- found = edge_map.find(std::make_pair(v2, v1));
- }
-
- if (found == edge_map.end()) {
- return false;
- }
- *out = found->second;
- return true;
-}
-
-template <typename T1, typename T2>
-bool edgeIndexMap_exists(const std::unordered_map<std::pair<T1, T1>, T2> &edge_map,
- const T1 &v1,
- const T1 &v2)
-{
- typedef std::unordered_map<std::pair<T1, T1>, T2> Map;
- typename Map::const_iterator found;
-
- if (v1 < v2) {
- found = edge_map.find(std::make_pair(v1, v2));
- }
- else {
- found = edge_map.find(std::make_pair(v2, v1));
- }
-
- return found != edge_map.end();
-}
-
-template <typename T>
-inline int indexOf(const T *element, const std::vector<T> &vector_from)
-{
- return element - &vector_from.at(0);
-}
-
-void initOrigIndexMeshFaceMapping(CarveMeshDescr *mesh,
- int which_mesh,
- std::unordered_map<std::pair<int, int>, int> &orig_loop_index_map,
- std::unordered_map<const MeshSet<3>::face_t*, int> &orig_poly_index_map,
- OrigVertMapping *orig_vert_mapping,
- OrigFaceEdgeMapping *orig_face_edge_mapping,
- FaceEdgeTriangulatedFlag *face_edge_triangulated_flag,
- OrigFaceMapping *orig_face_attr)
-{
- MeshSet<3> *poly = mesh->poly;
-
- std::vector<MeshSet<3>::vertex_t>::iterator vertex_iter =
- poly->vertex_storage.begin();
- for (int i = 0;
- vertex_iter != poly->vertex_storage.end();
- ++i, ++vertex_iter)
- {
- MeshSet<3>::vertex_t *vertex = &(*vertex_iter);
- orig_vert_mapping->setAttribute(vertex,
- std::make_pair(which_mesh, i));
- }
-
- MeshSet<3>::face_iter face_iter = poly->faceBegin();
- for (int i = 0, loop_map_index = 0;
- face_iter != poly->faceEnd();
- ++face_iter, ++i)
- {
- const MeshSet<3>::face_t *face = *face_iter;
-
- // Mapping from carve face back to original poly index.
- int orig_poly_index = orig_poly_index_map[face];
- orig_face_attr->setAttribute(face, std::make_pair(which_mesh, orig_poly_index));
-
- for (MeshSet<3>::face_t::const_edge_iter_t edge_iter = face->begin();
- edge_iter != face->end();
- ++edge_iter, ++loop_map_index)
- {
- int v1 = indexOf(edge_iter->v1(), poly->vertex_storage);
- int v2 = indexOf(edge_iter->v2(), poly->vertex_storage);
-
- int orig_loop_index;
- if (!edgeIndexMap_get_if_exists(orig_loop_index_map,
- v1, v2,
- &orig_loop_index))
- {
- orig_loop_index = -1;
- }
-
- if (orig_loop_index != -1) {
- // Mapping from carve face edge back to original loop index.
- orig_face_edge_mapping->setAttribute(face,
- edge_iter.idx(),
- std::make_pair(which_mesh,
- orig_loop_index));
- }
- else {
- face_edge_triangulated_flag->setAttribute(face,
- edge_iter.idx(),
- true);
- }
- }
- }
-}
-
-void initOrigIndexMapping(CarveMeshDescr *left_mesh,
- CarveMeshDescr *right_mesh,
- OrigVertMapping *orig_vert_mapping,
- OrigFaceEdgeMapping *orig_face_edge_mapping,
- FaceEdgeTriangulatedFlag *face_edge_triangulated_flag,
- OrigFaceMapping *orig_face_mapping)
-{
- initOrigIndexMeshFaceMapping(left_mesh,
- CARVE_MESH_LEFT,
- left_mesh->orig_loop_index_map,
- left_mesh->orig_poly_index_map,
- orig_vert_mapping,
- orig_face_edge_mapping,
- face_edge_triangulated_flag,
- orig_face_mapping);
-
- initOrigIndexMeshFaceMapping(right_mesh,
- CARVE_MESH_RIGHT,
- right_mesh->orig_loop_index_map,
- right_mesh->orig_poly_index_map,
- orig_vert_mapping,
- orig_face_edge_mapping,
- face_edge_triangulated_flag,
- orig_face_mapping);
-}
-
-void origEdgeMappingForFace(MeshSet<3>::face_t *face,
- OrigFaceEdgeMapping *orig_face_edge_mapping,
- std::unordered_map<VertexPair, OrigIndex> *edge_origindex_map)
-{
- OrigIndex origindex_none = std::make_pair((int)CARVE_MESH_NONE, -1);
-
- MeshSet<3>::edge_t *edge = face->edge;
- for (int i = 0;
- i < face->nEdges();
- ++i, edge = edge->next)
- {
- MeshSet<3>::vertex_t *v1 = edge->v1();
- MeshSet<3>::vertex_t *v2 = edge->v2();
-
- OrigIndex orig_edge_index =
- orig_face_edge_mapping->getAttribute(edge->face, i, origindex_none);
-
- edgeIndexMap_put(edge_origindex_map, v1, v2, orig_edge_index);
- }
-}
-
-void dissolveTriangulatedEdges(MeshSet<3>::mesh_t *mesh,
- const std::set< std::pair<int, int> > &open_edges,
- FaceEdgeTriangulatedFlag *face_edge_triangulated_flag,
- OrigFaceEdgeMapping *orig_face_edge_mapping)
-{
- typedef std::unordered_set<MeshSet<3>::edge_t *> edge_set_t;
- typedef std::unordered_set<MeshSet<3>::face_t *> face_set_t;
- edge_set_t triangulated_face_edges;
-
- for (int face_index = 0; face_index < mesh->faces.size(); ++face_index) {
- MeshSet<3>::face_t *face = mesh->faces[face_index];
- MeshSet<3>::edge_t *edge = face->edge;
- for (int edge_index = 0;
- edge_index < face->nEdges();
- ++edge_index, edge = edge->next)
- {
- if (edge->rev) {
- const bool is_triangulated_edge =
- face_edge_triangulated_flag->getAttribute(face,
- edge_index,
- false);
- if (is_triangulated_edge) {
- MeshSet<3>::edge_t *e1 = std::min(edge, edge->rev);
- int v1 = indexOf(e1->v1(), mesh->meshset->vertex_storage),
- v2 = indexOf(e1->v2(), mesh->meshset->vertex_storage);
-
- bool is_open = false;
- if (v1 < v2) {
- is_open = open_edges.find(std::make_pair(v1, v2)) != open_edges.end();
- }
- else {
- is_open = open_edges.find(std::make_pair(v2, v1)) != open_edges.end();
- }
-
- if (is_open == false) {
- triangulated_face_edges.insert(e1);
- }
- }
- }
- }
- }
-
- if (triangulated_face_edges.size()) {
- face_set_t triangulated_faces;
- std::unordered_map<VertexPair, OrigIndex> edge_origindex_map;
-
- for (edge_set_t::iterator it = triangulated_face_edges.begin();
- it != triangulated_face_edges.end();
- ++it)
- {
- MeshSet<3>::edge_t *edge = *it;
-
- origEdgeMappingForFace(edge->face,
- orig_face_edge_mapping,
- &edge_origindex_map);
- triangulated_faces.insert(edge->face);
-
- origEdgeMappingForFace(edge->rev->face,
- orig_face_edge_mapping,
- &edge_origindex_map);
- triangulated_faces.insert(edge->rev->face);
- }
-
- carve::mesh::MeshSimplifier simplifier;
- simplifier.dissolveMeshEdges(mesh, triangulated_face_edges);
-
- for (int face_index = 0; face_index < mesh->faces.size(); face_index++) {
- MeshSet<3>::face_t *face = mesh->faces[face_index];
-
- if (triangulated_faces.find(face) != triangulated_faces.end()) {
- MeshSet<3>::edge_t *edge = face->edge;
- for (int edge_index = 0;
- edge_index < face->nEdges();
- ++edge_index, edge = edge->next)
- {
- MeshSet<3>::vertex_t *v1 = edge->v1();
- MeshSet<3>::vertex_t *v2 = edge->v2();
-
- OrigIndex orig_edge_index =
- edgeIndexMap_get(edge_origindex_map,
- v1,
- v2);
-
- orig_face_edge_mapping->setAttribute(face, edge_index, orig_edge_index);
- }
- }
- }
- }
-}
-
-void dissolveTriangulatedEdges(CarveMeshDescr *mesh_descr)
-{
- MeshSet<3> *poly = mesh_descr->poly;
- FaceEdgeTriangulatedFlag *face_edge_triangulated_flag =
- &mesh_descr->face_edge_triangulated_flag;
-
- std::set< std::pair<int, int> > open_edges;
- for (int mesh_index = 0;
- mesh_index < poly->meshes.size();
- ++mesh_index)
- {
- const MeshSet<3>::mesh_t *mesh = poly->meshes[mesh_index];
- for (int edge_index = 0;
- edge_index < mesh->open_edges.size();
- ++edge_index)
- {
- const MeshSet<3>::edge_t *edge = mesh->open_edges[edge_index];
- int v1 = indexOf(edge->v1(), poly->vertex_storage),
- v2 = indexOf(edge->v2(), poly->vertex_storage);
- if (v1 < v2) {
- open_edges.insert(std::make_pair(v1, v2));
- }
- else {
- open_edges.insert(std::make_pair(v2, v1));
- }
- }
- }
-
- for (int mesh_index = 0; mesh_index < poly->meshes.size(); ++mesh_index) {
- MeshSet<3>::mesh_t *mesh = poly->meshes[mesh_index];
- dissolveTriangulatedEdges(mesh,
- open_edges,
- face_edge_triangulated_flag,
- &mesh_descr->orig_face_edge_mapping);
- }
-}
-
-void clipEar(MeshSet<3>::edge_t *ear)
-{
- MeshSet<3>::edge_t *p_edge = ear->prev;
- MeshSet<3>::edge_t *n_edge = ear->next;
-
- p_edge->next = n_edge;
- n_edge->prev = p_edge;
-
- if (ear->face->edge == ear) {
- ear->face->edge = n_edge;
- }
- ear->face->n_edges--;
-
- delete ear;
-}
-
-MeshSet<3>::edge_t *findDegenerateEar(MeshSet<3>::face_t *face)
-{
- for (MeshSet<3>::face_t::edge_iter_t edge_iter = face->begin();
- edge_iter != face->end();
- ++edge_iter)
- {
- MeshSet<3>::edge_t &edge = *edge_iter;
- if (edge.vert == edge.next->next->vert) {
- return edge.next->next;
- }
- }
- return NULL;
-}
-
-class EarClipper : public carve::csg::CSG::Hook {
-public:
- virtual ~EarClipper() {
- }
-
- virtual void processOutputFace(std::vector<MeshSet<3>::face_t *> &faces,
- const MeshSet<3>::face_t *orig,
- bool flipped) {
- for (size_t face_index = 0; face_index < faces.size(); ++face_index) {
- carve::mesh::MeshSet<3>::face_t *face = faces[face_index];
-
- // There's no ears in quads and tris.
- if (face->nVertices() <= 4) {
- continue;
- }
-
- MeshSet<3>::edge_t *ear;
- while ((ear = findDegenerateEar(face)) != NULL) {
- clipEar(ear);
- }
-
- }
- }
-};
-
-class HoleResolver : public carve::csg::CarveHoleResolver {
-
- void removeDuplicatedFaces(std::vector<MeshSet<3>::face_t *> &faces) {
- std::vector<MeshSet<3>::face_t *> out_faces;
- std::vector<MeshSet<3>::face_t *> duplicated_faces;
-
- for (size_t face_index = 0; face_index < faces.size(); ++face_index) {
- carve::mesh::MeshSet<3>::face_t *face = faces[face_index];
- face->canonicalize();
- }
-
- for (size_t i = 0; i < faces.size(); ++i) {
- carve::mesh::MeshSet<3>::face_t *face = faces[i];
-
- bool found = false;
- for (size_t j = i + 1; j < faces.size() && found == false; ++j) {
- MeshSet<3>::face_t *cur_face = faces[j];
- if (cur_face->nEdges() == face->nEdges() &&
- cur_face->edge->vert == face->edge->vert)
- {
-
- MeshSet<3>::edge_t *cur_edge = cur_face->edge,
- *forward_edge = face->edge,
- *backward_edge = face->edge;
- bool forward_matches = true, backward_matches = true;
-
- for (int a = 0; a < cur_face->nEdges(); ++a) {
- if (forward_edge->vert != cur_edge->vert) {
- forward_matches = false;
- if (backward_matches == false) {
- break;
- }
- }
-
- if (backward_edge->vert != cur_edge->vert) {
- backward_matches = false;
- if (forward_matches == false) {
- break;
- }
- }
-
- cur_edge = cur_edge->next;
- forward_edge = forward_edge->next;
- backward_edge = backward_edge->prev;
- }
-
- if (forward_matches || backward_matches) {
- found = true;
- break;
- }
- }
- }
-
- if (found) {
- duplicated_faces.push_back(face);
- }
- else {
- out_faces.push_back(face);
- }
- }
-
- for (int i = 0; i < duplicated_faces.size(); ++i) {
- delete duplicated_faces[i];
- }
-
- std::swap(faces, out_faces);
- }
-
-public:
- virtual ~HoleResolver() {
- }
-
- virtual void processOutputFace(std::vector<MeshSet<3>::face_t *> &faces,
- const MeshSet<3>::face_t *orig,
- bool flipped) {
- carve::csg::CarveHoleResolver::processOutputFace(faces, orig, flipped);
- if (faces.size() > 1) {
- removeDuplicatedFaces(faces);
- }
- }
-};
-
-template <typename Interpolator>
-void copyFaceEdgeAttrs(const MeshSet<3> *poly,
- Interpolator *old_interpolator,
- Interpolator *new_interpolator)
-{
- for (MeshSet<3>::const_face_iter face_iter = poly->faceBegin();
- face_iter != poly->faceEnd();
- ++face_iter)
- {
- const MeshSet<3>::face_t *face = *face_iter;
-
- for (int edge_index = 0;
- edge_index < face->nEdges();
- ++edge_index)
- {
- new_interpolator->copyAttribute(face,
- edge_index,
- old_interpolator);
- }
- }
-}
-
-template <typename Interpolator>
-void cleanupFaceEdgeAttrs(const MeshSet<3> *left,
- const MeshSet<3> *right,
- Interpolator *interpolator)
-{
- Interpolator new_interpolator;
- copyFaceEdgeAttrs(left, interpolator, &new_interpolator);
- copyFaceEdgeAttrs(right, interpolator, &new_interpolator);
- interpolator->swapAttributes(&new_interpolator);
-}
-
-void cleanupFaceEdgeAttrsCallback(const MeshSet<3> *left,
- const MeshSet<3> *right,
- void *descr_v)
-{
- CarveMeshDescr *descr = (CarveMeshDescr *) descr_v;
- cleanupFaceEdgeAttrs(left,
- right,
- &descr->face_edge_triangulated_flag);
- cleanupFaceEdgeAttrs(left,
- right,
- &descr->orig_face_edge_mapping);
-}
-
-void copyVertexAttrsCallback(const carve::mesh::MeshSet<3>::vertex_t *orig_vert,
- const carve::mesh::MeshSet<3>::vertex_t *new_vert,
- void *descr_v)
-{
- CarveMeshDescr *descr = (CarveMeshDescr *) descr_v;
- if (!descr->orig_vert_mapping.hasAttribute(orig_vert)) {
- return;
- }
- if (descr->orig_vert_mapping.hasAttribute(new_vert)) {
- return;
- }
- OrigIndex attr = descr->orig_vert_mapping.getAttribute(orig_vert);
- descr->orig_vert_mapping.setAttribute(new_vert, attr);
- descr->orig_vert_mapping.removeAttribute(orig_vert);
-}
-
-} // namespace
-
-CarveMeshDescr *carve_addMesh(struct ImportMeshData *import_data,
- CarveMeshImporter *mesh_importer)
-{
-#define MAX_STATIC_VERTS 64
-
- CarveMeshDescr *mesh_descr = new CarveMeshDescr;
-
- // Import verices from external mesh to Carve.
- int num_verts = mesh_importer->getNumVerts(import_data);
- std::vector<MeshSet<3>::vertex_t> vertex_storage;
- vertex_storage.reserve(num_verts);
- for (int i = 0; i < num_verts; i++) {
- float position[3];
- mesh_importer->getVertCoord(import_data, i, position);
- vertex_storage.push_back(carve::geom::VECTOR(position[0],
- position[1],
- position[2]));
- }
-
- // Import polys from external mesh to Carve.
- int verts_of_poly_static[MAX_STATIC_VERTS];
- int *verts_of_poly_dynamic = NULL;
- int verts_of_poly_dynamic_size = 0;
-
- int num_polys = mesh_importer->getNumPolys(import_data);
- int loop_index = 0;
- std::vector<int> face_indices;
- TrianglesStorage triangles_storage;
- std::vector<MeshSet<3>::face_t *> faces;
- std::vector<MeshSet<3>::vertex_t *> face_vertices;
- faces.reserve(num_polys);
- for (int i = 0; i < num_polys; i++) {
- int verts_per_poly =
- mesh_importer->getNumPolyVerts(import_data, i);
- int *verts_of_poly;
-
- if (verts_per_poly <= MAX_STATIC_VERTS) {
- verts_of_poly = verts_of_poly_static;
- }
- else {
- if (verts_of_poly_dynamic_size < verts_per_poly) {
- if (verts_of_poly_dynamic != NULL) {
- delete [] verts_of_poly_dynamic;
- }
- verts_of_poly_dynamic = new int[verts_per_poly];
- verts_of_poly_dynamic_size = verts_per_poly;
- }
- verts_of_poly = verts_of_poly_dynamic;
- }
-
- mesh_importer->getPolyVerts(import_data, i, verts_of_poly);
-
- carve::math::Matrix3 axis_matrix;
- if (!carve_checkPolyPlanarAndGetNormal(vertex_storage,
- verts_per_poly,
- verts_of_poly,
- &axis_matrix)) {
- face_indices.clear();
- int num_triangles = carve_triangulatePoly(import_data,
- mesh_importer,
- vertex_storage,
- verts_per_poly,
- verts_of_poly,
- axis_matrix,
- &face_indices,
- &triangles_storage);
- for (int j = 0; j < num_triangles; ++j) {
- MeshSet<3>::face_t *face = new MeshSet<3>::face_t(
- &vertex_storage[face_indices[j * 3]],
- &vertex_storage[face_indices[j * 3 + 1]],
- &vertex_storage[face_indices[j * 3 + 2]]);
- mesh_descr->orig_poly_index_map[face] = i;
- faces.push_back(face);
- }
- }
- else {
- face_vertices.clear();
- face_vertices.reserve(verts_per_poly);
- for (int j = 0; j < verts_per_poly; ++j) {
- face_vertices.push_back(&vertex_storage[verts_of_poly[j]]);
- }
- MeshSet<3>::face_t *face =
- new MeshSet<3>::face_t(face_vertices.begin(),
- face_vertices.end());
- mesh_descr->orig_poly_index_map[face] = i;
- faces.push_back(face);
- }
-
- for (int j = 0; j < verts_per_poly; ++j) {
- int v1 = verts_of_poly[j];
- int v2 = verts_of_poly[(j + 1) % verts_per_poly];
- edgeIndexMap_put(&mesh_descr->orig_loop_index_map, v1, v2, loop_index++);
- }
- }
-
- if (verts_of_poly_dynamic != NULL) {
- delete [] verts_of_poly_dynamic;
- }
-
- std::vector<MeshSet<3>::mesh_t *> meshes;
- MeshSet<3>::mesh_t::create(faces.begin(), faces.end(), meshes, carve::mesh::MeshOptions());
- mesh_descr->poly = new MeshSet<3> (vertex_storage, meshes);
-
- return mesh_descr;
-
-#undef MAX_STATIC_VERTS
-}
-
-void carve_deleteMesh(CarveMeshDescr *mesh_descr)
-{
- delete mesh_descr->poly;
- delete mesh_descr;
-}
-
-bool carve_performBooleanOperation(CarveMeshDescr *left_mesh,
- CarveMeshDescr *right_mesh,
- int operation,
- CarveMeshDescr **output_mesh)
-{
- *output_mesh = NULL;
-
- carve::csg::CSG::OP op;
- switch (operation) {
-#define OP_CONVERT(the_op) \
- case CARVE_OP_ ## the_op: \
- op = carve::csg::CSG::the_op; \
- break;
- OP_CONVERT(UNION)
- OP_CONVERT(INTERSECTION)
- OP_CONVERT(A_MINUS_B)
- default:
- return false;
-#undef OP_CONVERT
- }
-
- CarveMeshDescr *output_descr = new CarveMeshDescr;
- output_descr->poly = NULL;
- try {
- MeshSet<3> *left = left_mesh->poly, *right = right_mesh->poly;
- carve::geom3d::Vector min, max;
-
- // TODO(sergey): Make importer/exporter to care about re-scale
- // to save extra mesh iteration here.
- carve_getRescaleMinMax(left, right, &min, &max);
-
- carve::rescale::rescale scaler(min.x, min.y, min.z, max.x, max.y, max.z);
- carve::rescale::fwd fwd_r(scaler);
- carve::rescale::rev rev_r(scaler);
-
- left->transform(fwd_r);
- right->transform(fwd_r);
-
- // Initialize attributes for maping from boolean result mesh back to
- // original geometry indices.
- initOrigIndexMapping(left_mesh, right_mesh,
- &output_descr->orig_vert_mapping,
- &output_descr->orig_face_edge_mapping,
- &output_descr->face_edge_triangulated_flag,
- &output_descr->orig_face_mapping);
-
- carve::csg::CSG csg;
-
- csg.hooks.registerHook(new HoleResolver,
- carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT);
-
- csg.hooks.registerHook(new EarClipper,
- carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT);
-
- output_descr->orig_vert_mapping.installHooks(csg);
- output_descr->orig_face_edge_mapping.installHooks(csg);
- output_descr->face_edge_triangulated_flag.installHooks(csg);
- output_descr->orig_face_mapping.installHooks(csg);
-
- // Prepare operands for actual boolean operation.
- //
- // It's needed because operands might consist of several intersecting
- // meshes and in case of another operands intersect an edge loop of
- // intersecting that meshes tessellation of operation result can't be
- // done properly. The only way to make such situations working is to
- // union intersecting meshes of the same operand.
- carve_unionIntersections(&csg, &left, &right,
- copyVertexAttrsCallback,
- cleanupFaceEdgeAttrsCallback,
- (void *) output_descr);
-
- left_mesh->poly = left;
- right_mesh->poly = right;
-
- if (left->meshes.size() == 0 || right->meshes.size() == 0) {
- // Normally shouldn't happen (zero-faces objects are handled by
- // modifier itself), but unioning intersecting meshes which doesn't
- // have consistent normals might lead to empty result which
- // wouldn't work here.
-
- return false;
- }
-
- output_descr->poly = csg.compute(left,
- right,
- op,
- NULL,
- carve::csg::CSG::CLASSIFY_EDGE);
-
- if (output_descr->poly) {
- output_descr->poly->transform(rev_r);
-
- dissolveTriangulatedEdges(output_descr);
- }
- }
- catch (carve::exception e) {
- std::cerr << "CSG failed, exception " << e.str() << std::endl;
- }
- catch (...) {
- std::cerr << "Unknown error in Carve library" << std::endl;
- }
-
- *output_mesh = output_descr;
-
- return output_descr->poly != NULL;
-}
-
-static int exportMesh_handle_edges_list(MeshSet<3> *poly,
- const std::vector<MeshSet<3>::edge_t*> &edges,
- int start_edge_index,
- CarveMeshExporter *mesh_exporter,
- struct ExportMeshData *export_data,
- std::unordered_map<VertexPair, OrigIndex> &edge_origindex_map,
- std::unordered_map<VertexPair, int> *edge_map)
-{
- int num_exported_edges = 0;
-
- for (int i = 0, edge_index = start_edge_index;
- i < edges.size();
- ++i)
- {
- MeshSet<3>::edge_t *edge = edges.at(i);
- MeshSet<3>::vertex_t *v1 = edge->v1();
- MeshSet<3>::vertex_t *v2 = edge->v2();
-
- if (edgeIndexMap_exists(*edge_map, v1, v2)) {
- continue;
- }
-
- const OrigIndex &orig_edge_index = edgeIndexMap_get(edge_origindex_map,
- v1,
- v2);
-
- mesh_exporter->setEdge(export_data,
- edge_index,
- indexOf(v1, poly->vertex_storage),
- indexOf(v2, poly->vertex_storage),
- orig_edge_index.first,
- orig_edge_index.second);
-
- edgeIndexMap_put(edge_map, v1, v2, edge_index);
- ++edge_index;
- ++num_exported_edges;
- }
-
- return num_exported_edges;
-}
-
-void carve_exportMesh(CarveMeshDescr *mesh_descr,
- CarveMeshExporter *mesh_exporter,
- struct ExportMeshData *export_data)
-{
- OrigIndex origindex_none = std::make_pair((int)CARVE_MESH_NONE, -1);
- MeshSet<3> *poly = mesh_descr->poly;
- int num_vertices = poly->vertex_storage.size();
- int num_edges = 0, num_loops = 0, num_polys = 0;
-
- // Get mapping from edge denoted by vertex pair to original edge index,
- //
- // This is needed because internally Carve interpolates data for per-face
- // edges rather then having some global edge storage.
- std::unordered_map<VertexPair, OrigIndex> edge_origindex_map;
- for (MeshSet<3>::face_iter face_iter = poly->faceBegin();
- face_iter != poly->faceEnd();
- ++face_iter)
- {
- MeshSet<3>::face_t *face = *face_iter;
- for (MeshSet<3>::face_t::edge_iter_t edge_iter = face->begin();
- edge_iter != face->end();
- ++edge_iter)
- {
- MeshSet<3>::edge_t &edge = *edge_iter;
- int edge_iter_index = edge_iter.idx();
-
- const OrigIndex &orig_loop_index =
- mesh_descr->orig_face_edge_mapping.getAttribute(face,
- edge_iter_index,
- origindex_none);
-
- OrigIndex orig_edge_index;
-
- if (orig_loop_index.first != CARVE_MESH_NONE) {
- orig_edge_index.first = orig_loop_index.first;
- orig_edge_index.second =
- mesh_exporter->mapLoopToEdge(export_data,
- orig_loop_index.first,
- orig_loop_index.second);
- }
- else {
- orig_edge_index.first = CARVE_MESH_NONE;
- orig_edge_index.second = -1;
- }
-
- MeshSet<3>::vertex_t *v1 = edge.v1();
- MeshSet<3>::vertex_t *v2 = edge.v2();
-
- edgeIndexMap_put(&edge_origindex_map, v1, v2, orig_edge_index);
- }
- }
-
- num_edges = edge_origindex_map.size();
-
- // Count polys and loops from all manifolds.
- for (MeshSet<3>::face_iter face_iter = poly->faceBegin();
- face_iter != poly->faceEnd();
- ++face_iter, ++num_polys)
- {
- MeshSet<3>::face_t *face = *face_iter;
- num_loops += face->nEdges();
- }
-
- // Initialize arrays for geometry in exported mesh.
- mesh_exporter->initGeomArrays(export_data,
- num_vertices,
- num_edges,
- num_loops,
- num_polys);
-
- // Export all the vertices.
- std::vector<MeshSet<3>::vertex_t>::iterator vertex_iter = poly->vertex_storage.begin();
- for (int i = 0; vertex_iter != poly->vertex_storage.end(); ++i, ++vertex_iter) {
- MeshSet<3>::vertex_t *vertex = &(*vertex_iter);
-
- OrigIndex orig_vert_index =
- mesh_descr->orig_vert_mapping.getAttribute(vertex, origindex_none);
-
- float coord[3];
- coord[0] = vertex->v[0];
- coord[1] = vertex->v[1];
- coord[2] = vertex->v[2];
- mesh_exporter->setVert(export_data, i, coord,
- orig_vert_index.first,
- orig_vert_index.second);
- }
-
- // Export all the edges.
- std::unordered_map<VertexPair, int> edge_map;
- for (int i = 0, edge_index = 0; i < poly->meshes.size(); ++i) {
- carve::mesh::Mesh<3> *mesh = poly->meshes[i];
- // Export closed edges.
- edge_index += exportMesh_handle_edges_list(poly,
- mesh->closed_edges,
- edge_index,
- mesh_exporter,
- export_data,
- edge_origindex_map,
- &edge_map);
-
- // Export open edges.
- edge_index += exportMesh_handle_edges_list(poly,
- mesh->open_edges,
- edge_index,
- mesh_exporter,
- export_data,
- edge_origindex_map,
- &edge_map);
- }
-
- // Export all the loops and polys.
- MeshSet<3>::face_iter face_iter = poly->faceBegin();
- for (int loop_index = 0, poly_index = 0;
- face_iter != poly->faceEnd();
- ++face_iter, ++poly_index)
- {
- int start_loop_index = loop_index;
- MeshSet<3>::face_t *face = *face_iter;
- const OrigIndex &orig_face_index =
- mesh_descr->orig_face_mapping.getAttribute(face, origindex_none);
-
- for (MeshSet<3>::face_t::edge_iter_t edge_iter = face->begin();
- edge_iter != face->end();
- ++edge_iter, ++loop_index)
- {
- MeshSet<3>::edge_t &edge = *edge_iter;
- const OrigIndex &orig_loop_index =
- mesh_descr->orig_face_edge_mapping.getAttribute(face,
- edge_iter.idx(),
- origindex_none);
-
- mesh_exporter->setLoop(export_data,
- loop_index,
- indexOf(edge.vert, poly->vertex_storage),
- edgeIndexMap_get(edge_map, edge.v1(), edge.v2()),
- orig_loop_index.first,
- orig_loop_index.second);
- }
-
- mesh_exporter->setPoly(export_data,
- poly_index, start_loop_index, face->nEdges(),
- orig_face_index.first, orig_face_index.second);
- }
-}
diff --git a/extern/carve/carve-capi.h b/extern/carve/carve-capi.h
deleted file mode 100644
index f08ce418762..00000000000
--- a/extern/carve/carve-capi.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation,
- * Sergey Sharybin
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __CARVE_CAPI_H__
-#define __CARVE_CAPI_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct CarveMeshDescr;
-
-//
-// Importer from external storage to Carve module
-//
-
-struct ImportMeshData;
-
-// Get number of vertices.
-typedef int (*CarveImporter_GetNumVerts) (struct ImportMeshData *import_data);
-
-// Get number of edges.
-typedef int (*CarveImporter_GetNumEdges) (struct ImportMeshData *import_data);
-
-// Get number of loops.
-typedef int (*CarveImporter_GetNumLoops) (struct ImportMeshData *import_data);
-
-// Get number of polys.
-typedef int (*CarveImporter_GetNumPolys) (struct ImportMeshData *import_data);
-
-// Get 3D coordinate of vertex with given index.
-typedef void (*CarveImporter_GetVertCoord) (struct ImportMeshData *import_data, int vert_index, float coord[3]);
-
-// Get index of vertices which are adjacent to edge specified by its index.
-typedef void (*CarveImporter_GetEdgeVerts) (struct ImportMeshData *import_data, int edge_index, int *v1, int *v2);
-
-// Get number of adjacent vertices to the poly specified by its index.
-typedef int (*CarveImporter_GetPolyNumVerts) (struct ImportMeshData *import_data, int poly_index);
-
-// Get list of adjacent vertices to the poly specified by its index.
-typedef void (*CarveImporter_GetPolyVerts) (struct ImportMeshData *import_data, int poly_index, int *verts);
-
-// Triangulate 2D polygon.
-typedef int (*CarveImporter_Triangulate2DPoly) (struct ImportMeshData *import_data,
- const float (*vertices)[2], int num_vertices,
- unsigned int (*triangles)[3]);
-
-typedef struct CarveMeshImporter {
- CarveImporter_GetNumVerts getNumVerts;
- CarveImporter_GetNumEdges getNumEdges;
- CarveImporter_GetNumLoops getNumLoops;
- CarveImporter_GetNumPolys getNumPolys;
- CarveImporter_GetVertCoord getVertCoord;
- CarveImporter_GetEdgeVerts getEdgeVerts;
- CarveImporter_GetPolyNumVerts getNumPolyVerts;
- CarveImporter_GetPolyVerts getPolyVerts;
- CarveImporter_Triangulate2DPoly triangulate2DPoly;
-} CarveMeshImporter;
-
-//
-// Exporter from Carve module to external storage
-//
-
-struct ExportMeshData;
-
-// Initialize arrays for geometry.
-typedef void (*CarveExporter_InitGeomArrays) (struct ExportMeshData *export_data,
- int num_verts, int num_edges,
- int num_loops, int num_polys);
-
-// Set coordinate of vertex with given index.
-typedef void (*CarveExporter_SetVert) (struct ExportMeshData *export_data,
- int vert_index, float coord[3],
- int which_orig_mesh, int orig_vert_index);
-
-// Set vertices which are adjacent to the edge specified by its index.
-typedef void (*CarveExporter_SetEdge) (struct ExportMeshData *export_data,
- int edge_index, int v1, int v2,
- int which_orig_mesh, int orig_edge_index);
-
-// Set adjacent loops to the poly specified by its index.
-typedef void (*CarveExporter_SetPoly) (struct ExportMeshData *export_data,
- int poly_index, int start_loop, int num_loops,
- int which_orig_mesh, int orig_poly_index);
-
-// Set list vertex and edge which are adjacent to loop with given index.
-typedef void (*CarveExporter_SetLoop) (struct ExportMeshData *export_data,
- int loop_index, int vertex, int edge,
- int which_orig_mesh, int orig_loop_index);
-
-// Get edge index from a loop index for a given original mesh.
-//
-// A bit of a bummer to access original operands data on export stage,
-// but Blender side still does have this information in derived meshes
-// and we use API to get this data instead of duplicating it in Carve
-// API side. This is because of optimizations reasons.
-typedef int (*CarveExporter_MapLoopToEdge) (struct ExportMeshData *export_data,
- int which_mesh, int loop_index);
-
-typedef struct CarveMeshExporter {
- CarveExporter_InitGeomArrays initGeomArrays;
- CarveExporter_SetVert setVert;
- CarveExporter_SetEdge setEdge;
- CarveExporter_SetPoly setPoly;
- CarveExporter_SetLoop setLoop;
- CarveExporter_MapLoopToEdge mapLoopToEdge;
-} CarveMeshExporter;
-
-enum {
- CARVE_OP_UNION,
- CARVE_OP_INTERSECTION,
- CARVE_OP_A_MINUS_B,
-};
-
-enum {
- CARVE_MESH_NONE,
- CARVE_MESH_LEFT,
- CARVE_MESH_RIGHT
-};
-
-struct CarveMeshDescr *carve_addMesh(struct ImportMeshData *import_data,
- CarveMeshImporter *mesh_importer);
-
-void carve_deleteMesh(struct CarveMeshDescr *mesh_descr);
-
-bool carve_performBooleanOperation(struct CarveMeshDescr *left_mesh,
- struct CarveMeshDescr *right_mesh,
- int operation,
- struct CarveMeshDescr **output_mesh);
-
-void carve_exportMesh(struct CarveMeshDescr *mesh_descr,
- CarveMeshExporter *mesh_exporter,
- struct ExportMeshData *export_data);
-
-void carve_unionIntersections(struct CarveMeshDescr **left_mesh_r, struct CarveMeshDescr **right_mesh_r);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // __CARVE_CAPI_H__
diff --git a/extern/carve/carve-util.cc b/extern/carve/carve-util.cc
deleted file mode 100644
index 78997c72e71..00000000000
--- a/extern/carve/carve-util.cc
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation,
- * Sergey Sharybin
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "carve-util.h"
-#include "carve-capi.h"
-
-#include <cfloat>
-#include <carve/csg.hpp>
-#include <carve/csg_triangulator.hpp>
-#include <carve/rtree.hpp>
-
-using carve::csg::Intersections;
-using carve::geom::aabb;
-using carve::geom::RTreeNode;
-using carve::geom3d::Vector;
-using carve::math::Matrix3;
-using carve::mesh::Face;
-using carve::mesh::MeshSet;
-using carve::triangulate::tri_idx;
-using carve::triangulate::triangulate;
-
-typedef std::map< MeshSet<3>::mesh_t*, RTreeNode<3, Face<3> *> * > RTreeCache;
-typedef std::map< MeshSet<3>::mesh_t*, bool > IntersectCache;
-
-namespace {
-
-// Functions adopted from BLI_math.h to use Carve Vector and Matrix.
-
-void transpose_m3__bli(double mat[3][3])
-{
- double t;
-
- t = mat[0][1];
- mat[0][1] = mat[1][0];
- mat[1][0] = t;
- t = mat[0][2];
- mat[0][2] = mat[2][0];
- mat[2][0] = t;
- t = mat[1][2];
- mat[1][2] = mat[2][1];
- mat[2][1] = t;
-}
-
-void ortho_basis_v3v3_v3__bli(double r_n1[3], double r_n2[3], const double n[3])
-{
- const double eps = FLT_EPSILON;
- const double f = (n[0] * n[0]) + (n[1] * n[1]);
-
- if (f > eps) {
- const double d = 1.0f / sqrt(f);
-
- r_n1[0] = n[1] * d;
- r_n1[1] = -n[0] * d;
- r_n1[2] = 0.0f;
- r_n2[0] = -n[2] * r_n1[1];
- r_n2[1] = n[2] * r_n1[0];
- r_n2[2] = n[0] * r_n1[1] - n[1] * r_n1[0];
- }
- else {
- /* degenerate case */
- r_n1[0] = (n[2] < 0.0f) ? -1.0f : 1.0f;
- r_n1[1] = r_n1[2] = r_n2[0] = r_n2[2] = 0.0f;
- r_n2[1] = 1.0f;
- }
-}
-
-void axis_dominant_v3_to_m3__bli(Matrix3 *r_mat, const Vector &normal)
-{
- memcpy(r_mat->m[2], normal.v, sizeof(double[3]));
- ortho_basis_v3v3_v3__bli(r_mat->m[0], r_mat->m[1], r_mat->m[2]);
-
- transpose_m3__bli(r_mat->m);
-}
-
-
-void meshset_minmax(const MeshSet<3> *mesh,
- Vector *min,
- Vector *max)
-{
- for (size_t i = 0; i < mesh->vertex_storage.size(); ++i) {
- min->x = std::min(min->x, mesh->vertex_storage[i].v.x);
- min->y = std::min(min->y, mesh->vertex_storage[i].v.y);
- min->z = std::min(min->z, mesh->vertex_storage[i].v.z);
- max->x = std::max(max->x, mesh->vertex_storage[i].v.x);
- max->y = std::max(max->y, mesh->vertex_storage[i].v.y);
- max->z = std::max(max->z, mesh->vertex_storage[i].v.z);
- }
-}
-
-} // namespace
-
-void carve_getRescaleMinMax(const MeshSet<3> *left,
- const MeshSet<3> *right,
- Vector *min,
- Vector *max)
-{
- min->x = max->x = left->vertex_storage[0].v.x;
- min->y = max->y = left->vertex_storage[0].v.y;
- min->z = max->z = left->vertex_storage[0].v.z;
-
- meshset_minmax(left, min, max);
- meshset_minmax(right, min, max);
-
- // Make sure we don't scale object with zero scale.
- if (std::abs(min->x - max->x) < carve::EPSILON) {
- min->x = -1.0;
- max->x = 1.0;
- }
- if (std::abs(min->y - max->y) < carve::EPSILON) {
- min->y = -1.0;
- max->y = 1.0;
- }
- if (std::abs(min->z - max->z) < carve::EPSILON) {
- min->z = -1.0;
- max->z = 1.0;
- }
-}
-
-namespace {
-
-struct UnionIntersectionContext {
- VertexAttrsCallback vertex_attr_callback;
- void *user_data;
-};
-
-void copyMeshes(const std::vector<MeshSet<3>::mesh_t*> &meshes,
- std::vector<MeshSet<3>::mesh_t*> *new_meshes)
-{
- std::vector<MeshSet<3>::mesh_t*>::const_iterator it = meshes.begin();
- new_meshes->reserve(meshes.size());
- for (; it != meshes.end(); it++) {
- MeshSet<3>::mesh_t *mesh = *it;
- MeshSet<3>::mesh_t *new_mesh = new MeshSet<3>::mesh_t(mesh->faces);
-
- new_meshes->push_back(new_mesh);
- }
-}
-
-struct NewMeshMapping {
- std::map<const MeshSet<3>::edge_t*, MeshSet<3>::vertex_t*> orig_edge_vert;
-};
-
-void prepareNewMeshMapping(const std::vector<MeshSet<3>::mesh_t*> &meshes,
- NewMeshMapping *mapping)
-{
- for (size_t m = 0; m < meshes.size(); ++m) {
- MeshSet<3>::mesh_t *mesh = meshes[m];
- for (size_t f = 0; f < mesh->faces.size(); ++f) {
- MeshSet<3>::face_t *face = mesh->faces[f];
- MeshSet<3>::edge_t *edge = face->edge;
- do {
- mapping->orig_edge_vert[edge] = edge->vert;
- edge = edge->next;
- } while (edge != face->edge);
- }
- }
-}
-
-void runNewMeshSetHooks(UnionIntersectionContext *ctx,
- NewMeshMapping *mapping,
- MeshSet<3> *mesh_set)
-{
- for (size_t m = 0; m < mesh_set->meshes.size(); ++m) {
- MeshSet<3>::mesh_t *mesh = mesh_set->meshes[m];
- for (size_t f = 0; f < mesh->faces.size(); ++f) {
- MeshSet<3>::face_t *face = mesh->faces[f];
- MeshSet<3>::edge_t *edge = face->edge;
- do {
- const MeshSet<3>::vertex_t *orig_vert = mapping->orig_edge_vert[edge];
- const MeshSet<3>::vertex_t *new_vert = edge->vert;
- ctx->vertex_attr_callback(orig_vert, new_vert, ctx->user_data);
- edge = edge->next;
- } while (edge != face->edge);
- }
- }
-}
-
-MeshSet<3> *newMeshSetFromMeshesWithAttrs(
- UnionIntersectionContext *ctx,
- std::vector<MeshSet<3>::mesh_t*> &meshes)
-{
- NewMeshMapping mapping;
- prepareNewMeshMapping(meshes, &mapping);
- MeshSet<3> *mesh_set = new MeshSet<3>(meshes);
- runNewMeshSetHooks(ctx, &mapping, mesh_set);
- return mesh_set;
-}
-
-
-MeshSet<3> *meshSetFromMeshes(UnionIntersectionContext *ctx,
- const std::vector<MeshSet<3>::mesh_t*> &meshes)
-{
- std::vector<MeshSet<3>::mesh_t*> new_meshes;
- copyMeshes(meshes, &new_meshes);
- return newMeshSetFromMeshesWithAttrs(ctx, new_meshes);
-}
-
-MeshSet<3> *meshSetFromTwoMeshes(UnionIntersectionContext *ctx,
- const std::vector<MeshSet<3>::mesh_t*> &left_meshes,
- const std::vector<MeshSet<3>::mesh_t*> &right_meshes)
-{
- std::vector<MeshSet<3>::mesh_t*> new_meshes;
- copyMeshes(left_meshes, &new_meshes);
- copyMeshes(right_meshes, &new_meshes);
- return newMeshSetFromMeshesWithAttrs(ctx, new_meshes);
-}
-
-bool checkEdgeFaceIntersections_do(Intersections &intersections,
- MeshSet<3>::face_t *face_a,
- MeshSet<3>::edge_t *edge_b)
-{
- if (intersections.intersects(edge_b, face_a))
- return true;
-
- carve::mesh::MeshSet<3>::vertex_t::vector_t _p;
- if (face_a->simpleLineSegmentIntersection(carve::geom3d::LineSegment(edge_b->v1()->v, edge_b->v2()->v), _p))
- return true;
-
- return false;
-}
-
-bool checkEdgeFaceIntersections(Intersections &intersections,
- MeshSet<3>::face_t *face_a,
- MeshSet<3>::face_t *face_b)
-{
- MeshSet<3>::edge_t *edge_b;
-
- edge_b = face_b->edge;
- do {
- if (checkEdgeFaceIntersections_do(intersections, face_a, edge_b))
- return true;
- edge_b = edge_b->next;
- } while (edge_b != face_b->edge);
-
- return false;
-}
-
-inline bool facesAreCoplanar(const MeshSet<3>::face_t *a, const MeshSet<3>::face_t *b)
-{
- carve::geom3d::Ray temp;
- // XXX: Find a better definition. This may be a source of problems
- // if floating point inaccuracies cause an incorrect answer.
- return !carve::geom3d::planeIntersection(a->plane, b->plane, temp);
-}
-
-bool checkMeshSetInterseciton_do(Intersections &intersections,
- const RTreeNode<3, Face<3> *> *a_node,
- const RTreeNode<3, Face<3> *> *b_node,
- bool descend_a = true)
-{
- if (!a_node->bbox.intersects(b_node->bbox)) {
- return false;
- }
-
- if (a_node->child && (descend_a || !b_node->child)) {
- for (RTreeNode<3, Face<3> *> *node = a_node->child; node; node = node->sibling) {
- if (checkMeshSetInterseciton_do(intersections, node, b_node, false)) {
- return true;
- }
- }
- }
- else if (b_node->child) {
- for (RTreeNode<3, Face<3> *> *node = b_node->child; node; node = node->sibling) {
- if (checkMeshSetInterseciton_do(intersections, a_node, node, true)) {
- return true;
- }
- }
- }
- else {
- for (size_t i = 0; i < a_node->data.size(); ++i) {
- MeshSet<3>::face_t *fa = a_node->data[i];
- aabb<3> aabb_a = fa->getAABB();
- if (aabb_a.maxAxisSeparation(b_node->bbox) > carve::EPSILON) {
- continue;
- }
-
- for (size_t j = 0; j < b_node->data.size(); ++j) {
- MeshSet<3>::face_t *fb = b_node->data[j];
- aabb<3> aabb_b = fb->getAABB();
- if (aabb_b.maxAxisSeparation(aabb_a) > carve::EPSILON) {
- continue;
- }
-
- std::pair<double, double> a_ra = fa->rangeInDirection(fa->plane.N, fa->edge->vert->v);
- std::pair<double, double> b_ra = fb->rangeInDirection(fa->plane.N, fa->edge->vert->v);
- if (carve::rangeSeparation(a_ra, b_ra) > carve::EPSILON) {
- continue;
- }
-
- std::pair<double, double> a_rb = fa->rangeInDirection(fb->plane.N, fb->edge->vert->v);
- std::pair<double, double> b_rb = fb->rangeInDirection(fb->plane.N, fb->edge->vert->v);
- if (carve::rangeSeparation(a_rb, b_rb) > carve::EPSILON) {
- continue;
- }
-
- if (!facesAreCoplanar(fa, fb)) {
- if (checkEdgeFaceIntersections(intersections, fa, fb)) {
- return true;
- }
- }
- }
- }
- }
-
- return false;
-}
-
-bool checkMeshSetInterseciton(RTreeNode<3, Face<3> *> *rtree_a, RTreeNode<3, Face<3> *> *rtree_b)
-{
- Intersections intersections;
- return checkMeshSetInterseciton_do(intersections, rtree_a, rtree_b);
-}
-
-void getIntersectedOperandMeshes(std::vector<MeshSet<3>::mesh_t*> *meshes,
- const MeshSet<3>::aabb_t &otherAABB,
- std::vector<MeshSet<3>::mesh_t*> *operandMeshes,
- RTreeCache *rtree_cache,
- IntersectCache *intersect_cache)
-{
- std::vector<MeshSet<3>::mesh_t*>::iterator it = meshes->begin();
- std::vector< RTreeNode<3, Face<3> *> *> meshRTree;
-
- while (it != meshes->end()) {
- MeshSet<3>::mesh_t *mesh = *it;
- bool isAdded = false;
-
- RTreeNode<3, Face<3> *> *rtree;
- bool intersects;
-
- RTreeCache::iterator rtree_found = rtree_cache->find(mesh);
- if (rtree_found != rtree_cache->end()) {
- rtree = rtree_found->second;
- }
- else {
- rtree = RTreeNode<3, Face<3> *>::construct_STR(mesh->faces.begin(), mesh->faces.end(), 4, 4);
- (*rtree_cache)[mesh] = rtree;
- }
-
- IntersectCache::iterator intersect_found = intersect_cache->find(mesh);
- if (intersect_found != intersect_cache->end()) {
- intersects = intersect_found->second;
- }
- else {
- intersects = rtree->bbox.intersects(otherAABB);
- (*intersect_cache)[mesh] = intersects;
- }
-
- if (intersects) {
- bool isIntersect = false;
-
- std::vector<MeshSet<3>::mesh_t*>::iterator operand_it = operandMeshes->begin();
- std::vector<RTreeNode<3, Face<3> *> *>::iterator tree_it = meshRTree.begin();
- for (; operand_it!=operandMeshes->end(); operand_it++, tree_it++) {
- RTreeNode<3, Face<3> *> *operandRTree = *tree_it;
-
- if (checkMeshSetInterseciton(rtree, operandRTree)) {
- isIntersect = true;
- break;
- }
- }
-
- if (!isIntersect) {
- operandMeshes->push_back(mesh);
- meshRTree.push_back(rtree);
-
- it = meshes->erase(it);
- isAdded = true;
- }
- }
-
- if (!isAdded) {
- //delete rtree;
- it++;
- }
- }
-
- std::vector<RTreeNode<3, Face<3> *> *>::iterator tree_it = meshRTree.begin();
- for (; tree_it != meshRTree.end(); tree_it++) {
- //delete *tree_it;
- }
-}
-
-MeshSet<3> *getIntersectedOperand(UnionIntersectionContext *ctx,
- std::vector<MeshSet<3>::mesh_t*> *meshes,
- const MeshSet<3>::aabb_t &otherAABB,
- RTreeCache *rtree_cache,
- IntersectCache *intersect_cache)
-{
- std::vector<MeshSet<3>::mesh_t*> operandMeshes;
- getIntersectedOperandMeshes(meshes, otherAABB, &operandMeshes, rtree_cache, intersect_cache);
-
- if (operandMeshes.size() == 0)
- return NULL;
-
- return meshSetFromMeshes(ctx, operandMeshes);
-}
-
-MeshSet<3> *unionIntersectingMeshes(carve::csg::CSG *csg,
- MeshSet<3> *poly,
- const MeshSet<3> *other_poly,
- const MeshSet<3>::aabb_t &otherAABB,
- VertexAttrsCallback vertex_attr_callback,
- UnionIntersectionsCallback callback,
- void *user_data)
-{
- if (poly->meshes.size() <= 1) {
- return poly;
- }
-
- std::vector<MeshSet<3>::mesh_t*> orig_meshes =
- std::vector<MeshSet<3>::mesh_t*>(poly->meshes.begin(), poly->meshes.end());
-
- RTreeCache rtree_cache;
- IntersectCache intersect_cache;
-
- UnionIntersectionContext ctx;
- ctx.vertex_attr_callback = vertex_attr_callback;
- ctx.user_data = user_data;
-
- MeshSet<3> *left = getIntersectedOperand(&ctx,
- &orig_meshes,
- otherAABB,
- &rtree_cache,
- &intersect_cache);
-
- if (!left) {
- // No maniforlds which intersects another object at all.
- return poly;
- }
-
- while (orig_meshes.size()) {
- MeshSet<3> *right = getIntersectedOperand(&ctx,
- &orig_meshes,
- otherAABB,
- &rtree_cache,
- &intersect_cache);
-
- if (!right) {
- // No more intersecting manifolds which intersects other object
- break;
- }
-
- try {
- if (left->meshes.size()==0) {
- delete left;
-
- left = right;
- }
- else {
- MeshSet<3> *result = csg->compute(left, right,
- carve::csg::CSG::UNION,
- NULL, carve::csg::CSG::CLASSIFY_EDGE);
-
- callback(result, other_poly, user_data);
- delete left;
- delete right;
-
- left = result;
- }
- }
- catch (carve::exception e) {
- std::cerr << "CSG failed, exception " << e.str() << std::endl;
-
- MeshSet<3> *result = meshSetFromTwoMeshes(&ctx,
- left->meshes,
- right->meshes);
-
- callback(result, other_poly, user_data);
-
- delete left;
- delete right;
-
- left = result;
- }
- catch (...) {
- delete left;
- delete right;
-
- throw "Unknown error in Carve library";
- }
- }
-
- for (RTreeCache::iterator it = rtree_cache.begin();
- it != rtree_cache.end();
- it++)
- {
- delete it->second;
- }
-
- // Append all meshes which doesn't have intersection with another operand as-is.
- if (orig_meshes.size()) {
- MeshSet<3> *result = meshSetFromTwoMeshes(&ctx,
- left->meshes,
- orig_meshes);
-
- delete left;
- left = result;
- }
-
- return left;
-}
-
-} // namespace
-
-// TODO(sergey): This function is to be totally re-implemented to make it
-// more clear what's going on and hopefully optimize it as well.
-void carve_unionIntersections(carve::csg::CSG *csg,
- MeshSet<3> **left_r,
- MeshSet<3> **right_r,
- VertexAttrsCallback vertex_attr_callback,
- UnionIntersectionsCallback callback,
- void *user_data)
-{
- MeshSet<3> *left = *left_r, *right = *right_r;
-
- if (left->meshes.size() == 1 && right->meshes.size() == 0) {
- return;
- }
-
- MeshSet<3>::aabb_t leftAABB = left->getAABB();
- MeshSet<3>::aabb_t rightAABB = right->getAABB();;
-
- left = unionIntersectingMeshes(csg, left, right, rightAABB,
- vertex_attr_callback, callback, user_data);
- right = unionIntersectingMeshes(csg, right, left, leftAABB,
- vertex_attr_callback, callback, user_data);
-
- if (left != *left_r) {
- delete *left_r;
- }
-
- if (right != *right_r) {
- delete *right_r;
- }
-
- *left_r = left;
- *right_r = right;
-}
-
-static inline void add_newell_cross_v3_v3v3(const Vector &v_prev,
- const Vector &v_curr,
- Vector *n)
-{
- (*n)[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]);
- (*n)[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]);
- (*n)[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]);
-}
-
-// Axis matrix is being set for non-flat ngons only.
-bool carve_checkPolyPlanarAndGetNormal(const std::vector<MeshSet<3>::vertex_t> &vertex_storage,
- const int verts_per_poly,
- const int *verts_of_poly,
- Matrix3 *axis_matrix_r)
-{
- if (verts_per_poly == 3) {
- // Triangles are always planar.
- return true;
- }
- else if (verts_per_poly == 4) {
- // Presumably faster than using generig n-gon check for quads.
-
- const Vector &v1 = vertex_storage[verts_of_poly[0]].v,
- &v2 = vertex_storage[verts_of_poly[1]].v,
- &v3 = vertex_storage[verts_of_poly[2]].v,
- &v4 = vertex_storage[verts_of_poly[3]].v;
-
- Vector vec1, vec2, vec3, cross;
-
- vec1 = v2 - v1;
- vec2 = v4 - v1;
- vec3 = v3 - v1;
-
- cross = carve::geom::cross(vec1, vec2);
-
- double production = carve::geom::dot(cross, vec3);
-
- // TODO(sergey): Check on whether we could have length-independent
- // magnitude here.
- double magnitude = 1e-3 * cross.length2();
-
- return fabs(production) < magnitude;
- }
- else {
- const Vector *vert_prev = &vertex_storage[verts_of_poly[verts_per_poly - 1]].v;
- const Vector *vert_curr = &vertex_storage[verts_of_poly[0]].v;
-
- Vector normal = carve::geom::VECTOR(0.0, 0.0, 0.0);
- for (int i = 0; i < verts_per_poly; i++) {
- add_newell_cross_v3_v3v3(*vert_prev, *vert_curr, &normal);
- vert_prev = vert_curr;
- vert_curr = &vertex_storage[verts_of_poly[(i + 1) % verts_per_poly]].v;
- }
-
- if (normal.length2() < FLT_EPSILON) {
- // Degenerated face, couldn't triangulate properly anyway.
- return true;
- }
- else {
- double magnitude = normal.length2();
-
- normal.normalize();
- axis_dominant_v3_to_m3__bli(axis_matrix_r, normal);
-
- Vector first_projected = *axis_matrix_r * vertex_storage[verts_of_poly[0]].v;
- double min_z = first_projected[2], max_z = first_projected[2];
-
- for (int i = 1; i < verts_per_poly; i++) {
- const Vector &vertex = vertex_storage[verts_of_poly[i]].v;
- Vector projected = *axis_matrix_r * vertex;
- if (projected[2] < min_z) {
- min_z = projected[2];
- }
- if (projected[2] > max_z) {
- max_z = projected[2];
- }
- }
-
- if (std::abs(min_z - max_z) > FLT_EPSILON * magnitude) {
- return false;
- }
- }
-
- return true;
- }
-
- return false;
-}
-
-namespace {
-
-int triangulateNGon_carveTriangulator(const std::vector<MeshSet<3>::vertex_t> &vertex_storage,
- const int verts_per_poly,
- const int *verts_of_poly,
- const Matrix3 &axis_matrix,
- std::vector<tri_idx> *triangles)
-{
- // Project vertices to 2D plane.
- Vector projected;
- std::vector<carve::geom::vector<2> > poly_2d;
- poly_2d.reserve(verts_per_poly);
- for (int i = 0; i < verts_per_poly; ++i) {
- projected = axis_matrix * vertex_storage[verts_of_poly[i]].v;
- poly_2d.push_back(carve::geom::VECTOR(projected[0], projected[1]));
- }
-
- carve::triangulate::triangulate(poly_2d, *triangles);
- carve::triangulate::improve(poly_2d, *triangles);
-
- return triangles->size();
-}
-
-int triangulateNGon_importerTriangulator(struct ImportMeshData *import_data,
- CarveMeshImporter *mesh_importer,
- const std::vector<MeshSet<3>::vertex_t> &vertex_storage,
- const int verts_per_poly,
- const int *verts_of_poly,
- const Matrix3 &axis_matrix,
- std::vector<tri_idx> *triangles)
-{
- typedef float Vector2D[2];
- typedef unsigned int Triangle[3];
-
- // Project vertices to 2D plane.
- Vector2D *poly_2d = new Vector2D[verts_per_poly];
- Vector projected;
- for (int i = 0; i < verts_per_poly; ++i) {
- projected = axis_matrix * vertex_storage[verts_of_poly[i]].v;
- poly_2d[i][0] = projected[0];
- poly_2d[i][1] = projected[1];
- }
-
- Triangle *api_triangles = new Triangle[verts_per_poly - 2];
- int num_triangles =
- mesh_importer->triangulate2DPoly(import_data,
- poly_2d,
- verts_per_poly,
- api_triangles);
-
- triangles->reserve(num_triangles);
- for (int i = 0; i < num_triangles; ++i) {
- triangles->push_back(tri_idx(api_triangles[i][0],
- api_triangles[i][1],
- api_triangles[i][2]));
- }
-
- delete [] poly_2d;
- delete [] api_triangles;
-
- return num_triangles;
-}
-
-template <typename T>
-void sortThreeNumbers(T &a, T &b, T &c)
-{
- if (a > b)
- std::swap(a, b);
- if (b > c)
- std::swap(b, c);
- if (a > b)
- std::swap(a, b);
-}
-
-bool pushTriangle(int v1, int v2, int v3,
- std::vector<int> *face_indices,
- TrianglesStorage *triangles_storage)
-{
-
- tri_idx triangle(v1, v2, v3);
- sortThreeNumbers(triangle.a, triangle.b, triangle.c);
-
- assert(triangle.a < triangle.b);
- assert(triangle.b < triangle.c);
-
- if (triangles_storage->find(triangle) == triangles_storage->end()) {
- face_indices->push_back(v1);
- face_indices->push_back(v2);
- face_indices->push_back(v3);
-
- triangles_storage->insert(triangle);
- return true;
- }
- else {
- return false;
- }
-}
-
-} // namespace
-
-int carve_triangulatePoly(struct ImportMeshData *import_data,
- CarveMeshImporter *mesh_importer,
- const std::vector<MeshSet<3>::vertex_t> &vertex_storage,
- const int verts_per_poly,
- const int *verts_of_poly,
- const Matrix3 &axis_matrix,
- std::vector<int> *face_indices,
- TrianglesStorage *triangles_storage)
-{
- int num_triangles = 0;
-
- assert(verts_per_poly > 3);
-
- if (verts_per_poly == 4) {
- // Quads we triangulate by 1-3 diagonal, it is an original behavior
- // of boolean modifier.
- //
- // TODO(sergey): Consider using shortest diagonal here. However
- // display code in Blende use static 1-3 split, so some experiments
- // are needed here.
- if (pushTriangle(verts_of_poly[0],
- verts_of_poly[1],
- verts_of_poly[2],
- face_indices,
- triangles_storage))
- {
- num_triangles++;
- }
-
- if (pushTriangle(verts_of_poly[0],
- verts_of_poly[2],
- verts_of_poly[3],
- face_indices,
- triangles_storage))
- {
- num_triangles++;
- }
- }
- else {
- std::vector<tri_idx> triangles;
- triangles.reserve(verts_per_poly - 2);
-
- // Make triangulator callback optional so we could do some tests
- // in the future.
- if (mesh_importer->triangulate2DPoly) {
- triangulateNGon_importerTriangulator(import_data,
- mesh_importer,
- vertex_storage,
- verts_per_poly,
- verts_of_poly,
- axis_matrix,
- &triangles);
- }
- else {
- triangulateNGon_carveTriangulator(vertex_storage,
- verts_per_poly,
- verts_of_poly,
- axis_matrix,
- &triangles);
- }
-
- for (int i = 0; i < triangles.size(); ++i) {
- int v1 = triangles[i].a,
- v2 = triangles[i].b,
- v3 = triangles[i].c;
-
- // Sanity check of the triangle.
- assert(v1 != v2);
- assert(v1 != v3);
- assert(v2 != v3);
- assert(v1 < verts_per_poly);
- assert(v2 < verts_per_poly);
- assert(v3 < verts_per_poly);
-
- if (pushTriangle(verts_of_poly[v1],
- verts_of_poly[v2],
- verts_of_poly[v3],
- face_indices,
- triangles_storage))
- {
- num_triangles++;
- }
- }
- }
-
- return num_triangles;
-}
diff --git a/extern/carve/carve-util.h b/extern/carve/carve-util.h
deleted file mode 100644
index e8f62cd2751..00000000000
--- a/extern/carve/carve-util.h
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation,
- * Sergey Sharybin
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __CARVE_UTIL_H__
-#define __CARVE_UTIL_H__
-
-#include <carve/csg.hpp>
-#include <carve/geom3d.hpp>
-#include <carve/interpolator.hpp>
-#include <carve/mesh.hpp>
-#include <carve/triangulator.hpp>
-
-#include "carve-capi.h"
-
-struct TriIdxCompare {
- bool operator() (const carve::triangulate::tri_idx &left,
- const carve::triangulate::tri_idx &right) const {
- if (left.a < right.a) {
- return true;
- }
- else if (left.a > right.a) {
- return false;
- }
-
- if (left.b < right.b) {
- return true;
- }
- else if (left.b > right.b) {
- return false;
- }
-
- if (left.c < right.c) {
- return true;
- }
- else if (left.c > right.c) {
- return false;
- }
-
- return false;
- }
-};
-
-typedef std::set<carve::triangulate::tri_idx, TriIdxCompare> TrianglesStorage;
-
-void carve_getRescaleMinMax(const carve::mesh::MeshSet<3> *left,
- const carve::mesh::MeshSet<3> *right,
- carve::geom3d::Vector *min,
- carve::geom3d::Vector *max);
-
-typedef void (*VertexAttrsCallback) (const carve::mesh::MeshSet<3>::vertex_t *orig_vert,
- const carve::mesh::MeshSet<3>::vertex_t *new_vert,
- void *userdata);
-
-typedef void (*UnionIntersectionsCallback) (const carve::mesh::MeshSet<3> *left,
- const carve::mesh::MeshSet<3> *right,
- void *userdata);
-
-void carve_unionIntersections(carve::csg::CSG *csg,
- carve::mesh::MeshSet<3> **left_r,
- carve::mesh::MeshSet<3> **right_r,
- VertexAttrsCallback vertex_attr_callback,
- UnionIntersectionsCallback callback,
- void *user_data);
-
-bool carve_checkPolyPlanarAndGetNormal(const std::vector<carve::mesh::MeshSet<3>::vertex_t> &vertex_storage,
- const int verts_per_poly,
- const int *verts_of_poly,
- carve::math::Matrix3 *axis_matrix_r);
-
-int carve_triangulatePoly(struct ImportMeshData *import_data,
- CarveMeshImporter *mesh_importer,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t> &vertex_storage,
- const int verts_per_poly,
- const int *verts_of_poly,
- const carve::math::Matrix3 &axis_matrix,
- std::vector<int> *face_indices,
- TrianglesStorage *triangles_storage);
-
-namespace carve {
- namespace interpolate {
-
- template<typename attr_t>
- class VertexAttr : public Interpolator {
- public:
- typedef const meshset_t::vertex_t *key_t;
-
- protected:
- typedef std::unordered_map<key_t, attr_t> attrmap_t;
-
- attrmap_t attrs;
-
- virtual void resultFace(const carve::csg::CSG &csg,
- const meshset_t::face_t *new_face,
- const meshset_t::face_t *orig_face,
- bool flipped)
- {
- typedef meshset_t::face_t::const_edge_iter_t const_edge_iter_t;
- for (const_edge_iter_t new_edge_iter = new_face->begin();
- new_edge_iter != new_face->end();
- ++new_edge_iter)
- {
- typename attrmap_t::const_iterator found =
- attrs.find(new_edge_iter->vert);
- if (found == attrs.end()) {
- for (const_edge_iter_t orig_edge_iter = orig_face->begin();
- orig_edge_iter != orig_face->end();
- ++orig_edge_iter)
- {
- if ((orig_edge_iter->vert->v - new_edge_iter->vert->v).length2() < 1e-5) {
- attrs[new_edge_iter->vert] = attrs[orig_edge_iter->vert];
- }
- }
- }
- }
- }
-
- public:
- bool hasAttribute(const meshset_t::vertex_t *v) {
- return attrs.find(v) != attrs.end();
- }
-
- const attr_t &getAttribute(const meshset_t::vertex_t *v, const attr_t &def = attr_t()) {
- typename attrmap_t::const_iterator found = attrs.find(v);
- if (found != attrs.end()) {
- return found->second;
- }
- return def;
- }
-
- void setAttribute(const meshset_t::vertex_t *v, const attr_t &attr) {
- attrs[v] = attr;
- }
-
- void removeAttribute(const meshset_t::vertex_t *v) {
- typename attrmap_t::iterator it = attrs.find(v);
- if (it != attrs.end()) {
- attrs.erase(it);
- }
- }
- };
-
- template<typename attr_t>
- class SimpleFaceEdgeAttr : public Interpolator {
- public:
- typedef std::pair<const meshset_t::face_t *, unsigned> key_t;
-
- protected:
- typedef std::pair<const meshset_t::vertex_t *, const meshset_t::vertex_t *> vpair_t;
-
- struct key_hash {
- size_t operator()(const key_t &v) const {
- return size_t(v.first) ^ size_t(v.second);
- }
- };
- struct vpair_hash {
- size_t operator()(const vpair_t &v) const {
- return size_t(v.first) ^ size_t(v.second);
- }
- };
-
- typedef std::unordered_map<key_t, attr_t, key_hash> attrmap_t;
- typedef std::unordered_map<vpair_t, key_t, vpair_hash> edgedivmap_t;
-
- attrmap_t attrs;
-
- struct Hook : public Interpolator::Hook {
- public:
- virtual unsigned hookBits() const {
- return carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT;
- }
- Hook(Interpolator *_interpolator, const carve::csg::CSG &_csg) : Interpolator::Hook(_interpolator, _csg) {
- }
- virtual ~Hook() {
- }
- };
-
- virtual Interpolator::Hook *makeHook(carve::csg::CSG &csg) {
- return new Hook(this, csg);
- }
-
- virtual void processOutputFace(const carve::csg::CSG &csg,
- std::vector<carve::mesh::MeshSet<3>::face_t *> &new_faces,
- const meshset_t::face_t *orig_face,
- bool flipped) {
- edgedivmap_t undiv;
-
- for (meshset_t::face_t::const_edge_iter_t e = orig_face->begin(); e != orig_face->end(); ++e) {
- key_t k(orig_face, e.idx());
- typename attrmap_t::const_iterator attr_i = attrs.find(k);
- if (attr_i == attrs.end()) {
- continue;
- } else {
- undiv[vpair_t(e->v1(), e->v2())] = k;
- }
- }
-
- for (size_t fnum = 0; fnum < new_faces.size(); ++fnum) {
- const carve::mesh::MeshSet<3>::face_t *new_face = new_faces[fnum];
- for (meshset_t::face_t::const_edge_iter_t e = new_face->begin(); e != new_face->end(); ++e) {
- key_t k(new_face, e.idx());
-
- vpair_t vp;
- if (!flipped) {
- vp = vpair_t(e->v1(), e->v2());
- } else {
- vp = vpair_t(e->v2(), e->v1());
- }
- typename edgedivmap_t::const_iterator vp_i;
- if ((vp_i = undiv.find(vp)) != undiv.end()) {
- attrs[k] = attrs[vp_i->second];
- }
- }
- }
- }
-
- public:
-
- bool hasAttribute(const meshset_t::face_t *f, unsigned e) {
- return attrs.find(std::make_pair(f, e)) != attrs.end();
- }
-
- attr_t getAttribute(const meshset_t::face_t *f, unsigned e, const attr_t &def = attr_t()) {
- typename attrmap_t::const_iterator fv = attrs.find(std::make_pair(f, e));
- if (fv != attrs.end()) {
- return (*fv).second;
- }
- return def;
- }
-
- void setAttribute(const meshset_t::face_t *f, unsigned e, const attr_t &attr) {
- attrs[std::make_pair(f, e)] = attr;
- }
-
- void copyAttribute(const meshset_t::face_t *face,
- unsigned edge,
- SimpleFaceEdgeAttr<attr_t> *interpolator) {
- key_t key(face, edge);
- typename attrmap_t::const_iterator fv = interpolator->attrs.find(key);
- if (fv != interpolator->attrs.end()) {
- attrs[key] = (*fv).second;
- }
- }
-
- void swapAttributes(SimpleFaceEdgeAttr<attr_t> *interpolator) {
- attrs.swap(interpolator->attrs);
- }
-
- SimpleFaceEdgeAttr() : Interpolator() {
- }
-
- virtual ~SimpleFaceEdgeAttr() {
- }
- };
-
- template<typename attr_t>
- class SwapableFaceEdgeAttr : public FaceEdgeAttr<attr_t> {
- public:
- typedef carve::mesh::MeshSet<3> meshset_t;
-
- void copyAttribute(const meshset_t::face_t *face,
- unsigned edge,
- SwapableFaceEdgeAttr<attr_t> *interpolator) {
- typename FaceEdgeAttr<attr_t>::key_t key(face, edge);
- typename FaceEdgeAttr<attr_t>::attrmap_t::const_iterator fv = interpolator->attrs.find(key);
- if (fv != interpolator->attrs.end()) {
- this->attrs[key] = (*fv).second;
- }
- }
-
- void swapAttributes(SwapableFaceEdgeAttr<attr_t> *interpolator) {
- this->attrs.swap(interpolator->attrs);
- }
- };
- } // namespace interpolate
-} // namespace carve
-
-#endif // __CARVE_UTIL_H__
diff --git a/extern/carve/files.txt b/extern/carve/files.txt
deleted file mode 100644
index 9598d07f7e8..00000000000
--- a/extern/carve/files.txt
+++ /dev/null
@@ -1,107 +0,0 @@
-include/carve/edge_impl.hpp
-include/carve/tag.hpp
-include/carve/colour.hpp
-include/carve/math_constants.hpp
-include/carve/csg.hpp
-include/carve/heap.hpp
-include/carve/vector.hpp
-include/carve/djset.hpp
-include/carve/mesh_impl.hpp
-include/carve/polyline_iter.hpp
-include/carve/input.hpp
-include/carve/geom2d.hpp
-include/carve/aabb_impl.hpp
-include/carve/geom.hpp
-include/carve/triangulator.hpp
-include/carve/pointset_iter.hpp
-include/carve/spacetree.hpp
-include/carve/vertex_impl.hpp
-include/carve/vcpp_config.h
-include/carve/octree_decl.hpp
-include/carve/rescale.hpp
-include/carve/collection_types.hpp
-include/carve/faceloop.hpp
-include/carve/polyhedron_base.hpp
-include/carve/vertex_decl.hpp
-include/carve/cbrt.h
-include/carve/matrix.hpp
-include/carve/tree.hpp
-include/carve/debug_hooks.hpp
-include/carve/rtree.hpp
-include/carve/math.hpp
-include/carve/convex_hull.hpp
-include/carve/polyline.hpp
-include/carve/geom3d.hpp
-include/carve/aabb.hpp
-include/carve/pointset_decl.hpp
-include/carve/intersection.hpp
-include/carve/face_impl.hpp
-include/carve/collection.hpp
-include/carve/poly_impl.hpp
-include/carve/exact.hpp
-include/carve/timing.hpp
-include/carve/poly.hpp
-include/carve/mesh.hpp
-include/carve/win32.h
-include/carve/mesh_simplify.hpp
-include/carve/classification.hpp
-include/carve/collection/unordered/fallback_impl.hpp
-include/carve/collection/unordered/std_impl.hpp
-include/carve/collection/unordered/vcpp_impl.hpp
-include/carve/collection/unordered/boost_impl.hpp
-include/carve/collection/unordered/libstdcpp_impl.hpp
-include/carve/collection/unordered/tr1_impl.hpp
-include/carve/collection/unordered.hpp
-include/carve/pointset.hpp
-include/carve/mesh_ops.hpp
-include/carve/triangle_intersection.hpp
-include/carve/octree_impl.hpp
-include/carve/pointset_impl.hpp
-include/carve/carve.hpp
-include/carve/kd_node.hpp
-include/carve/polyhedron_impl.hpp
-include/carve/interpolator.hpp
-include/carve/edge_decl.hpp
-include/carve/face_decl.hpp
-include/carve/geom_impl.hpp
-include/carve/util.hpp
-include/carve/random/random.h
-include/carve/gnu_cxx.h
-include/carve/polyline_decl.hpp
-include/carve/triangulator_impl.hpp
-include/carve/iobj.hpp
-include/carve/csg_triangulator.hpp
-include/carve/polyline_impl.hpp
-include/carve/poly_decl.hpp
-include/carve/polyhedron_decl.hpp
-lib/math.cpp
-lib/intersect_classify_edge.cpp
-lib/csg_detail.hpp
-lib/polyhedron.cpp
-lib/csg.cpp
-lib/intersect.cpp
-lib/csg_data.hpp
-lib/intersection.cpp
-lib/timing.cpp
-lib/intersect_classify_common_impl.hpp
-lib/geom2d.cpp
-lib/csg_collector.hpp
-lib/mesh.cpp
-lib/intersect_half_classify_group.cpp
-lib/octree.cpp
-lib/csg_collector.cpp
-lib/intersect_debug.hpp
-lib/intersect_classify_common.hpp
-lib/geom3d.cpp
-lib/intersect_face_division.cpp
-lib/face.cpp
-lib/triangulator.cpp
-lib/tag.cpp
-lib/intersect_classify_group.cpp
-lib/polyline.cpp
-lib/intersect_common.hpp
-lib/convex_hull.cpp
-lib/intersect_group.cpp
-lib/carve.cpp
-lib/pointset.cpp
-lib/intersect_debug.cpp
diff --git a/extern/carve/include/carve/aabb.hpp b/extern/carve/include/carve/aabb.hpp
deleted file mode 100644
index 9677358ff3e..00000000000
--- a/extern/carve/include/carve/aabb.hpp
+++ /dev/null
@@ -1,156 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/geom.hpp>
-
-#include <vector>
-
-namespace carve {
- namespace geom {
-
-
-
- // n-dimensional AABB
- template<unsigned ndim>
- struct aabb {
- typedef vector<ndim> vector_t;
- typedef aabb<ndim> aabb_t;
-
- vector_t pos; // the centre of the AABB
- vector_t extent; // the extent of the AABB - the vector from the centre to the maximal vertex.
-
- void empty();
-
- bool isEmpty() const;
-
- void fit(const vector_t &v1);
- void fit(const vector_t &v1, const vector_t &v2);
- void fit(const vector_t &v1, const vector_t &v2, const vector_t &v3);
-
- template<typename iter_t, typename value_type>
- void _fit(iter_t begin, iter_t end, value_type);
-
- template<typename iter_t>
- void _fit(iter_t begin, iter_t end, vector_t);
-
- template<typename iter_t>
- void _fit(iter_t begin, iter_t end, aabb_t);
-
- template<typename iter_t>
- void fit(iter_t begin, iter_t end);
-
- template<typename iter_t, typename adapt_t>
- void fit(iter_t begin, iter_t end, adapt_t adapt);
-
- void unionAABB(const aabb<ndim> &a);
-
- void expand(double pad);
-
- bool completelyContains(const aabb<ndim> &other) const;
-
- bool containsPoint(const vector_t &v) const;
-
- bool intersectsLineSegment(const vector_t &v1, const vector_t &v2) const;
-
- double axisSeparation(const aabb<ndim> &other, unsigned axis) const;
-
- double maxAxisSeparation(const aabb<ndim> &other) const;
-
- bool intersects(const aabb<ndim> &other) const;
- bool intersects(const sphere<ndim> &s) const;
- bool intersects(const plane<ndim> &plane) const;
- bool intersects(const ray<ndim> &ray) const;
- bool intersects(tri<ndim> tri) const;
- bool intersects(const linesegment<ndim> &ls) const;
-
- std::pair<double, double> rangeInDirection(const carve::geom::vector<ndim> &v) const;
-
- vector_t min() const;
- vector_t mid() const;
- vector_t max() const;
-
- double min(unsigned dim) const;
- double mid(unsigned dim) const;
- double max(unsigned dim) const;
-
- double volume() const;
-
- int compareAxis(const axis_pos &ap) const;
-
- void constrainMax(const axis_pos &ap);
- void constrainMin(const axis_pos &ap);
-
- aabb getAABB() const;
-
- aabb(const vector_t &_pos = vector_t::ZERO(),
- const vector_t &_extent = vector_t::ZERO());
-
- template<typename iter_t, typename adapt_t>
- aabb(iter_t begin, iter_t end, adapt_t adapt);
-
- template<typename iter_t>
- aabb(iter_t begin, iter_t end);
-
- aabb(const aabb<ndim> &a, const aabb<ndim> &b);
- };
-
- template<unsigned ndim>
- bool operator==(const aabb<ndim> &a, const aabb<ndim> &b);
-
- template<unsigned ndim>
- bool operator!=(const aabb<ndim> &a, const aabb<ndim> &b);
-
- template<unsigned ndim>
- std::ostream &operator<<(std::ostream &o, const aabb<ndim> &a);
-
- template<unsigned ndim>
- double distance2(const aabb<3> &a, const vector<ndim> &v);
-
- template<unsigned ndim>
- double distance(const aabb<3> &a, const vector<ndim> &v);
-
-
-
- template<unsigned ndim, typename obj_t>
- struct get_aabb {
- aabb<ndim> operator()(const obj_t &obj) const {
- return obj.getAABB();
- }
- };
-
- template<unsigned ndim, typename obj_t>
- struct get_aabb<ndim, obj_t *> {
- aabb<ndim> operator()(const obj_t *obj) const {
- return obj->getAABB();
- }
- };
-
-
-
- }
-}
-
-namespace carve {
- namespace geom3d {
- typedef carve::geom::aabb<3> AABB;
- }
-}
-
-#include <carve/aabb_impl.hpp>
diff --git a/extern/carve/include/carve/aabb_impl.hpp b/extern/carve/include/carve/aabb_impl.hpp
deleted file mode 100644
index c9028b75c84..00000000000
--- a/extern/carve/include/carve/aabb_impl.hpp
+++ /dev/null
@@ -1,440 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/vector.hpp>
-#include <carve/geom3d.hpp>
-
-#include <carve/geom.hpp>
-
-#include <vector>
-
-namespace carve {
- namespace geom {
-
- template<unsigned ndim>
- void aabb<ndim>::empty() {
- pos.setZero();
- extent.setZero();
- }
-
- template<unsigned ndim>
- bool aabb<ndim>::isEmpty() const {
- return extent.exactlyZero();
- }
-
- template<unsigned ndim>
- template<typename iter_t, typename value_type>
- void aabb<ndim>::_fit(iter_t begin, iter_t end, value_type) {
- if (begin == end) {
- empty();
- return;
- }
-
- vector_t min, max;
- aabb<ndim> a = get_aabb<ndim, value_type>()(*begin); ++begin;
- min = a.min();
- max = a.max();
- while (begin != end) {
- aabb<ndim> a = get_aabb<ndim, value_type>()(*begin); ++begin;
- assign_op(min, min, a.min(), carve::util::min_functor());
- assign_op(max, max, a.max(), carve::util::max_functor());
- }
-
- pos = (min + max) / 2.0;
- assign_op(extent, max - pos, pos - min, carve::util::max_functor());
- }
-
- template<unsigned ndim>
- template<typename iter_t>
- void aabb<ndim>::_fit(iter_t begin, iter_t end, vector_t) {
- if (begin == end) {
- empty();
- return;
- }
-
- vector_t min, max;
- bounds(begin, end, min, max);
- pos = (min + max) / 2.0;
- assign_op(extent, max - pos, pos - min, carve::util::max_functor());
- }
-
- template<unsigned ndim>
- template<typename iter_t>
- void aabb<ndim>::_fit(iter_t begin, iter_t end, aabb_t) {
- if (begin == end) {
- empty();
- return;
- }
-
- vector_t min, max;
- aabb<ndim> a = *begin++;
- min = a.min();
- max = a.max();
- while (begin != end) {
- aabb<ndim> a = *begin; ++begin;
- assign_op(min, min, a.min(), carve::util::min_functor());
- assign_op(max, max, a.max(), carve::util::max_functor());
- }
-
- pos = (min + max) / 2.0;
- assign_op(extent, max - pos, pos - min, carve::util::max_functor());
- }
-
- template<unsigned ndim>
- void aabb<ndim>::fit(const vector_t &v1) {
- pos = v1;
- extent.setZero();
- }
-
- template<unsigned ndim>
- void aabb<ndim>::fit(const vector_t &v1, const vector_t &v2) {
- vector_t min, max;
- assign_op(min, v1, v2, carve::util::min_functor());
- assign_op(max, v1, v2, carve::util::max_functor());
-
- pos = (min + max) / 2.0;
- assign_op(extent, max - pos, pos - min, carve::util::max_functor());
- }
-
- template<unsigned ndim>
- void aabb<ndim>::fit(const vector_t &v1, const vector_t &v2, const vector_t &v3) {
- vector_t min, max;
- min = max = v1;
-
- assign_op(min, min, v2, carve::util::min_functor());
- assign_op(max, max, v2, carve::util::max_functor());
- assign_op(min, min, v3, carve::util::min_functor());
- assign_op(max, max, v3, carve::util::max_functor());
-
- pos = (min + max) / 2.0;
- assign_op(extent, max - pos, pos - min, carve::util::max_functor());
- }
-
- template<unsigned ndim>
- template<typename iter_t, typename adapt_t>
- void aabb<ndim>::fit(iter_t begin, iter_t end, adapt_t adapt) {
- vector_t min, max;
-
- bounds(begin, end, adapt, min, max);
- pos = (min + max) / 2.0;
- assign_op(extent, max - pos, pos - min, carve::util::max_functor());
- }
-
- template<unsigned ndim>
- template<typename iter_t>
- void aabb<ndim>::fit(iter_t begin, iter_t end) {
- _fit(begin, end, typename std::iterator_traits<iter_t>::value_type());
- }
-
- template<unsigned ndim>
- void aabb<ndim>::expand(double pad) {
- extent += pad;
- }
-
- template<unsigned ndim>
- void aabb<ndim>::unionAABB(const aabb<ndim> &a) {
- vector_t vmin, vmax;
-
- assign_op(vmin, min(), a.min(), carve::util::min_functor());
- assign_op(vmax, max(), a.max(), carve::util::max_functor());
- pos = (vmin + vmax) / 2.0;
- assign_op(extent, vmax - pos, pos - vmin, carve::util::max_functor());
- }
-
- template<unsigned ndim>
- bool aabb<ndim>::completelyContains(const aabb<ndim> &other) const {
- for (unsigned i = 0; i < ndim; ++i) {
- if (fabs(other.pos.v[i] - pos.v[i]) + other.extent.v[i] > extent.v[i]) return false;
- }
- return true;
- }
-
- template<unsigned ndim>
- bool aabb<ndim>::containsPoint(const vector_t &v) const {
- for (unsigned i = 0; i < ndim; ++i) {
- if (fabs(v.v[i] - pos.v[i]) > extent.v[i]) return false;
- }
- return true;
- }
-
- template<unsigned ndim>
- double aabb<ndim>::axisSeparation(const aabb<ndim> &other, unsigned axis) const {
- return fabs(other.pos.v[axis] - pos.v[axis]) - extent.v[axis] - other.extent.v[axis];
- }
-
- template<unsigned ndim>
- double aabb<ndim>::maxAxisSeparation(const aabb<ndim> &other) const {
- double m = axisSeparation(other, 0);
- for (unsigned i = 1; i < ndim; ++i) {
- m = std::max(m, axisSeparation(other, i));
- }
- return m;
- }
-
- template<unsigned ndim>
- bool aabb<ndim>::intersects(const aabb<ndim> &other) const {
- return maxAxisSeparation(other) <= 0.0;
- }
-
- template<unsigned ndim>
- bool aabb<ndim>::intersects(const sphere<ndim> &s) const {
- double r = 0.0;
- for (unsigned i = 0; i < ndim; ++i) {
- double t = fabs(s.C[i] - pos[i]) - extent[i]; if (t > 0.0) r += t*t;
- }
- return r <= s.r*s.r;
- }
-
- template<unsigned ndim>
- bool aabb<ndim>::intersects(const plane<ndim> &plane) const {
- double d1 = fabs(distance(plane, pos));
- double d2 = dot(abs(plane.N), extent);
- return d1 <= d2;
- }
-
- template<unsigned ndim>
- bool aabb<ndim>::intersects(const linesegment<ndim> &ls) const {
- return intersectsLineSegment(ls.v1, ls.v2);
- }
-
- template<unsigned ndim>
- std::pair<double, double> aabb<ndim>::rangeInDirection(const carve::geom::vector<ndim> &v) const {
- double d1 = dot(v, pos);
- double d2 = dot(abs(v), extent);
-
- return std::make_pair(d1 - d2, d1 + d2);
- }
-
- template<unsigned ndim>
- typename aabb<ndim>::vector_t aabb<ndim>::min() const { return pos - extent; }
-
- template<unsigned ndim>
- typename aabb<ndim>::vector_t aabb<ndim>::mid() const { return pos; }
-
- template<unsigned ndim>
- typename aabb<ndim>::vector_t aabb<ndim>::max() const { return pos + extent; }
-
- template<unsigned ndim>
- double aabb<ndim>::min(unsigned dim) const { return pos.v[dim] - extent.v[dim]; }
-
- template<unsigned ndim>
- double aabb<ndim>::mid(unsigned dim) const { return pos.v[dim]; }
-
- template<unsigned ndim>
- double aabb<ndim>::max(unsigned dim) const { return pos.v[dim] + extent.v[dim]; }
-
- template<unsigned ndim>
- double aabb<ndim>::volume() const {
- double v = 1.0;
- for (size_t dim = 0; dim < ndim; ++dim) { v *= 2.0 * extent.v[dim]; }
- return v;
- }
-
- template<unsigned ndim>
- int aabb<ndim>::compareAxis(const axis_pos &ap) const {
- double p = ap.pos - pos[ap.axis];
- if (p > extent[ap.axis]) return -1;
- if (p < -extent[ap.axis]) return +1;
- return 0;
- }
-
- template<unsigned ndim>
- void aabb<ndim>::constrainMax(const axis_pos &ap) {
- if (pos[ap.axis] + extent[ap.axis] > ap.pos) {
- double min = std::min(ap.pos, pos[ap.axis] - extent[ap.axis]);
- pos[ap.axis] = (min + ap.pos) / 2.0;
- extent[ap.axis] = ap.pos - pos[ap.axis];
- }
- }
-
- template<unsigned ndim>
- void aabb<ndim>::constrainMin(const axis_pos &ap) {
- if (pos[ap.axis] - extent[ap.axis] < ap.pos) {
- double max = std::max(ap.pos, pos[ap.axis] + extent[ap.axis]);
- pos[ap.axis] = (ap.pos + max) / 2.0;
- extent[ap.axis] = pos[ap.axis] - ap.pos;
- }
- }
-
- template<unsigned ndim>
- aabb<ndim> aabb<ndim>::getAABB() const {
- return *this;
- }
-
- template<unsigned ndim>
- aabb<ndim>::aabb(const vector_t &_pos,
- const vector_t &_extent) : pos(_pos), extent(_extent) {
- }
-
- template<unsigned ndim>
- template<typename iter_t, typename adapt_t>
- aabb<ndim>::aabb(iter_t begin, iter_t end, adapt_t adapt) {
- fit(begin, end, adapt);
- }
-
- template<unsigned ndim>
- template<typename iter_t>
- aabb<ndim>::aabb(iter_t begin, iter_t end) {
- fit(begin, end);
- }
-
- template<unsigned ndim>
- aabb<ndim>::aabb(const aabb<ndim> &a, const aabb<ndim> &b) {
- fit(a, b);
- }
-
- template<unsigned ndim>
- bool operator==(const aabb<ndim> &a, const aabb<ndim> &b) {
- return a.pos == b.pos && a.extent == b.extent;
- }
-
- template<unsigned ndim>
- bool operator!=(const aabb<ndim> &a, const aabb<ndim> &b) {
- return a.pos != b.pos || a.extent != b.extent;
- }
-
- template<unsigned ndim>
- std::ostream &operator<<(std::ostream &o, const aabb<ndim> &a) {
- o << (a.pos - a.extent) << "--" << (a.pos + a.extent);
- return o;
- }
-
- template<unsigned ndim>
- double distance2(const aabb<3> &a, const vector<ndim> &v) {
- double d2 = 0.0;
- for (unsigned i = 0; i < ndim; ++i) {
- double d = ::fabs(v.v[i] - a.pos.v[i]) - a.extent.v[i];
- if (d > 0.0) {
- d2 += d * d;
- }
- }
- return d2;
- }
-
- template<unsigned ndim>
- double distance(const aabb<3> &a, const vector<ndim> &v) {
- return ::sqrt(distance2(a, v));
- }
-
- template<>
- inline bool aabb<3>::intersects(const ray<3> &ray) const {
- vector<3> t = pos - ray.v;
- double r;
-
- //l.cross(x-axis)?
- r = extent.y * fabs(ray.D.z) + extent.z * fabs(ray.D.y);
- if (fabs(t.y * ray.D.z - t.z * ray.D.y) > r) return false;
-
- //ray.D.cross(y-axis)?
- r = extent.x * fabs(ray.D.z) + extent.z * fabs(ray.D.x);
- if (fabs(t.z * ray.D.x - t.x * ray.D.z) > r) return false;
-
- //ray.D.cross(z-axis)?
- r = extent.x*fabs(ray.D.y) + extent.y*fabs(ray.D.x);
- if (fabs(t.x * ray.D.y - t.y * ray.D.x) > r) return false;
-
- return true;
- }
-
- template<>
- inline bool aabb<3>::intersectsLineSegment(const vector<3> &v1, const vector<3> &v2) const {
- vector<3> half_length = 0.5 * (v2 - v1);
- vector<3> t = pos - half_length - v1;
- double r;
-
- //do any of the principal axes form a separating axis?
- if(fabs(t.x) > extent.x + fabs(half_length.x)) return false;
- if(fabs(t.y) > extent.y + fabs(half_length.y)) return false;
- if(fabs(t.z) > extent.z + fabs(half_length.z)) return false;
-
- // NOTE: Since the separating axis is perpendicular to the line in
- // these last four cases, the line does not contribute to the
- // projection.
-
- //line.cross(x-axis)?
- r = extent.y * fabs(half_length.z) + extent.z * fabs(half_length.y);
- if (fabs(t.y * half_length.z - t.z * half_length.y) > r) return false;
-
- //half_length.cross(y-axis)?
- r = extent.x * fabs(half_length.z) + extent.z * fabs(half_length.x);
- if (fabs(t.z * half_length.x - t.x * half_length.z) > r) return false;
-
- //half_length.cross(z-axis)?
- r = extent.x*fabs(half_length.y) + extent.y*fabs(half_length.x);
- if (fabs(t.x * half_length.y - t.y * half_length.x) > r) return false;
-
- return true;
- }
-
- template<int Ax, int Ay, int Az, int c>
- static inline bool intersectsTriangle_axisTest_3(const aabb<3> &aabb, const tri<3> &tri) {
- const int d = (c+1) % 3, e = (c+2) % 3;
- const vector<3> a = cross(VECTOR(Ax, Ay, Az), tri.v[d] - tri.v[c]);
- double p1 = dot(a, tri.v[c]), p2 = dot(a, tri.v[e]);
- if (p1 > p2) std::swap(p1, p2);
- const double r = dot(abs(a), aabb.extent);
- return !(p1 > r || p2 < -r);
- }
-
- template<int c>
- static inline bool intersectsTriangle_axisTest_2(const aabb<3> &aabb, const tri<3> &tri) {
- double vmin = std::min(std::min(tri.v[0][c], tri.v[1][c]), tri.v[2][c]),
- vmax = std::max(std::max(tri.v[0][c], tri.v[1][c]), tri.v[2][c]);
- return !(vmin > aabb.extent[c] || vmax < -aabb.extent[c]);
- }
-
- static inline bool intersectsTriangle_axisTest_1(const aabb<3> &aabb, const tri<3> &tri) {
- vector<3> n = cross(tri.v[1] - tri.v[0], tri.v[2] - tri.v[0]);
- double d1 = fabs(dot(n, tri.v[0]));
- double d2 = dot(abs(n), aabb.extent);
- return d1 <= d2;
- }
-
- template<>
- inline bool aabb<3>::intersects(tri<3> tri) const {
- tri.v[0] -= pos;
- tri.v[1] -= pos;
- tri.v[2] -= pos;
-
- if (!intersectsTriangle_axisTest_2<0>(*this, tri)) return false;
- if (!intersectsTriangle_axisTest_2<1>(*this, tri)) return false;
- if (!intersectsTriangle_axisTest_2<2>(*this, tri)) return false;
-
- if (!intersectsTriangle_axisTest_3<1,0,0,0>(*this, tri)) return false;
- if (!intersectsTriangle_axisTest_3<1,0,0,1>(*this, tri)) return false;
- if (!intersectsTriangle_axisTest_3<1,0,0,2>(*this, tri)) return false;
-
- if (!intersectsTriangle_axisTest_3<0,1,0,0>(*this, tri)) return false;
- if (!intersectsTriangle_axisTest_3<0,1,0,1>(*this, tri)) return false;
- if (!intersectsTriangle_axisTest_3<0,1,0,2>(*this, tri)) return false;
-
- if (!intersectsTriangle_axisTest_3<0,0,1,0>(*this, tri)) return false;
- if (!intersectsTriangle_axisTest_3<0,0,1,1>(*this, tri)) return false;
- if (!intersectsTriangle_axisTest_3<0,0,1,2>(*this, tri)) return false;
-
- if (!intersectsTriangle_axisTest_1(*this, tri)) return false;
-
- return true;
- }
-
-
-
- }
-}
diff --git a/extern/carve/include/carve/carve.hpp b/extern/carve/include/carve/carve.hpp
deleted file mode 100644
index 5f8d76e320c..00000000000
--- a/extern/carve/include/carve/carve.hpp
+++ /dev/null
@@ -1,238 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
-#if defined(CMAKE_BUILD)
-# include <carve/config.h>
-#elif defined(XCODE_BUILD)
-# include <carve/xcode_config.h>
-#elif defined(_MSC_VER)
-# include <carve/vcpp_config.h>
-#else
-# include <carve/config.h>
-#endif
-
-#if defined(WIN32)
-# include <carve/win32.h>
-#elif defined(__GNUC__)
-# include <carve/gnu_cxx.h>
-#endif
-
-#if defined(CARVE_SYSTEM_BOOST)
-# define BOOST_INCLUDE(x) <boost/x>
-#else
-# define BOOST_INCLUDE(x) <carve/external/boost/x>
-#endif
-
-#include <math.h>
-
-#include <string>
-#include <set>
-#include <map>
-#include <vector>
-#include <list>
-#include <sstream>
-#include <iomanip>
-
-#include <carve/collection.hpp>
-
-#include <carve/util.hpp>
-
-#include <stdarg.h>
-
-#define STR(x) #x
-#define XSTR(x) STR(x)
-
-/**
- * \brief Top level Carve namespace.
- */
-namespace carve {
- static struct noinit_t {} NOINIT;
-
- inline std::string fmtstring(const char *fmt, ...);
-
- /**
- * \brief Base class for all Carve exceptions.
- */
- struct exception {
- private:
- mutable std::string err;
- mutable std::ostringstream accum;
-
- public:
- exception(const std::string &e) : err(e), accum() { }
- exception() : err(), accum() { }
- exception(const exception &e) : err(e.str()), accum() { }
- exception &operator=(const exception &e) {
- if (this != &e) {
- err = e.str();
- accum.str("");
- }
- return *this;
- }
-
- const std::string &str() const {
- if (accum.str().size() > 0) {
- err += accum.str();
- accum.str("");
- }
- return err;
- }
-
- template<typename T>
- exception &operator<<(const T &t) {
- accum << t;
- return *this;
- }
- };
-
- template<typename iter_t, typename order_t = std::less<typename std::iterator_traits<iter_t>::value_type > >
- struct index_sort {
- iter_t base;
- order_t order;
- index_sort(const iter_t &_base) : base(_base), order() { }
- index_sort(const iter_t &_base, const order_t &_order) : base(_base), order(_order) { }
- template<typename U>
- bool operator()(const U &a, const U &b) {
- return order(*(base + a), *(base + b));
- }
- };
-
- template<typename iter_t, typename order_t>
- index_sort<iter_t, order_t> make_index_sort(const iter_t &base, const order_t &order) {
- return index_sort<iter_t, order_t>(base, order);
- }
-
- template<typename iter_t>
- index_sort<iter_t> make_index_sort(const iter_t &base) {
- return index_sort<iter_t>(base);
- }
-
-
- enum RayIntersectionClass {
- RR_DEGENERATE = -2,
- RR_PARALLEL = -1,
- RR_NO_INTERSECTION = 0,
- RR_INTERSECTION = 1
- };
-
- enum LineIntersectionClass {
- COLINEAR = -1,
- NO_INTERSECTION = 0,
- INTERSECTION_LL = 1,
- INTERSECTION_PL = 2,
- INTERSECTION_LP = 3,
- INTERSECTION_PP = 4
- };
-
- enum PointClass {
- POINT_UNK = -2,
- POINT_OUT = -1,
- POINT_ON = 0,
- POINT_IN = 1,
- POINT_VERTEX = 2,
- POINT_EDGE = 3
- };
-
- enum IntersectionClass {
- INTERSECT_BAD = -1,
- INTERSECT_NONE = 0,
- INTERSECT_FACE = 1,
- INTERSECT_VERTEX = 2,
- INTERSECT_EDGE = 3,
- INTERSECT_PLANE = 4,
- };
-
-
-
- extern double EPSILON;
- extern double EPSILON2;
-
- static inline void setEpsilon(double ep) { EPSILON = ep; EPSILON2 = ep * ep; }
-
-
-
- template<typename T>
- struct identity_t {
- typedef T argument_type;
- typedef T result_type;
- const T &operator()(const T &t) const { return t; }
- };
-
-
-
- template<typename iter_t>
- inline bool is_sorted(iter_t first, iter_t last) {
- if (first == last) return true;
-
- iter_t iter = first;
- iter_t next = first; ++next;
- for (; next != last; iter = next, ++next) {
- if (*next < *iter) {
- return false;
- }
- }
- return true;
- }
-
-
-
- template<typename iter_t,
- typename pred_t>
- inline bool is_sorted(iter_t first, iter_t last, pred_t pred) {
- if (first == last) return true;
-
- iter_t iter = first;
- iter_t next = first; ++next;
- for (; next != last; iter = next, ++next) {
- if (pred(*next, *iter)) {
- return false;
- }
- }
- return true;
- }
-
-
-
- inline double rangeSeparation(const std::pair<double, double> &a,
- const std::pair<double, double> &b) {
- if (a.second < b.first) {
- return b.first - a.second;
- } else if (b.second < a.first) {
- return a.first - b.second;
- } else {
- return 0.0;
- }
- }
-}
-
-
-#if defined(_MSC_VER)
-# define MACRO_BEGIN do {
-# define MACRO_END __pragma(warning(push)) __pragma(warning(disable:4127)) } while(0) __pragma(warning(pop))
-#else
-# define MACRO_BEGIN do {
-# define MACRO_END } while(0)
-#endif
-
-#if !defined(CARVE_NODEBUG)
-# define CARVE_ASSERT(x) MACRO_BEGIN if (!(x)) throw carve::exception() << __FILE__ << ":" << __LINE__ << " " << #x; MACRO_END
-#else
-# define CARVE_ASSERT(X)
-#endif
-
-#define CARVE_FAIL(x) MACRO_BEGIN throw carve::exception() << __FILE__ << ":" << __LINE__ << " " << #x; MACRO_END
diff --git a/extern/carve/include/carve/cbrt.h b/extern/carve/include/carve/cbrt.h
deleted file mode 100644
index aeceab01426..00000000000
--- a/extern/carve/include/carve/cbrt.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// N.B. only appropriate for IEEE doubles.
-// Cube root implementation obtained from code with the following notice:
-
-/* @(#)s_cbrt.c 1.3 95/01/18 */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunSoft, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- *
- */
-
-/* Sometimes it's necessary to define __LITTLE_ENDIAN explicitly
- but these catch some common cases. */
-
-#if defined(i386) || defined(i486) || \
- defined(intel) || defined(x86) || defined(i86pc) || \
- defined(__alpha) || defined(__osf__)
-#define __LITTLE_ENDIAN
-#endif
-
-#ifdef __LITTLE_ENDIAN
-#define __HI(x) *(1+(int*)&x)
-#define __LO(x) *(int*)&x
-#define __HIp(x) *(1+(int*)x)
-#define __LOp(x) *(int*)x
-#else
-#define __HI(x) *(int*)&x
-#define __LO(x) *(1+(int*)&x)
-#define __HIp(x) *(int*)x
-#define __LOp(x) *(1+(int*)x)
-#endif
-
-/* cbrt(x)
- * Return cube root of x
- */
-
-inline double cbrt(double x) {
-
- static const unsigned
- B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */
- B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
- static const double
- C = 5.42857142857142815906e-01, /* 19/35 = 0x3FE15F15, 0xF15F15F1 */
- D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */
- E = 1.41428571428571436819e+00, /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */
- F = 1.60714285714285720630e+00, /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */
- G = 3.57142857142857150787e-01; /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */
-
- int hx;
- double r,s,t=0.0,w;
- unsigned sign;
-
- hx = __HI(x); /* high word of x */
- sign=hx&0x80000000; /* sign= sign(x) */
- hx ^=sign;
- if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */
- if((hx|__LO(x))==0)
- return(x); /* cbrt(0) is itself */
-
- __HI(x) = hx; /* x <- |x| */
- /* rough cbrt to 5 bits */
- if(hx<0x00100000) /* subnormal number */
- {__HI(t)=0x43500000; /* set t= 2**54 */
- t*=x; __HI(t)=__HI(t)/3+B2;
- }
- else
- __HI(t)=hx/3+B1;
-
-
- /* new cbrt to 23 bits, may be implemented in single precision */
- r=t*t/x;
- s=C+r*t;
- t*=G+F/(s+E+D/s);
-
- /* chopped to 20 bits and make it larger than cbrt(x) */
- __LO(t)=0; __HI(t)+=0x00000001;
-
- /* one step newton iteration to 53 bits with error less than 0.667 ulps */
- s=t*t; /* t*t is exact */
- r=x/s;
- w=t+t;
- r=(r-t)/(w+r); /* r-s is exact */
- t=t+t*r;
-
- /* retore the sign bit */
- __HI(t) |= sign;
- return(t);
-}
diff --git a/extern/carve/include/carve/classification.hpp b/extern/carve/include/carve/classification.hpp
deleted file mode 100644
index ebda48e61a5..00000000000
--- a/extern/carve/include/carve/classification.hpp
+++ /dev/null
@@ -1,115 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-#include <carve/collection_types.hpp>
-
-namespace carve {
- namespace csg {
-
- enum FaceClass {
- FACE_UNCLASSIFIED = -3,
- FACE_ON_ORIENT_OUT = -2,
- FACE_OUT = -1,
- FACE_ON = 0,
- FACE_IN = +1,
- FACE_ON_ORIENT_IN = +2
- };
-
- enum FaceClassBit {
- FACE_ON_ORIENT_OUT_BIT = 0x01,
- FACE_OUT_BIT = 0x02,
- FACE_IN_BIT = 0x04,
- FACE_ON_ORIENT_IN_BIT = 0x08,
-
- FACE_ANY_BIT = 0x0f,
- FACE_ON_BIT = 0x09,
- FACE_NOT_ON_BIT = 0x06
- };
-
- static inline FaceClass class_bit_to_class(unsigned i) {
- if (i & FACE_ON_ORIENT_OUT_BIT) return FACE_ON_ORIENT_OUT;
- if (i & FACE_OUT_BIT) return FACE_OUT;
- if (i & FACE_IN_BIT) return FACE_IN;
- if (i & FACE_ON_ORIENT_IN_BIT) return FACE_ON_ORIENT_IN;
- return FACE_UNCLASSIFIED;
- }
-
- static inline unsigned class_to_class_bit(FaceClass f) {
- switch (f) {
- case FACE_ON_ORIENT_OUT: return FACE_ON_ORIENT_OUT_BIT;
- case FACE_OUT: return FACE_OUT_BIT;
- case FACE_ON: return FACE_ON_BIT;
- case FACE_IN: return FACE_IN_BIT;
- case FACE_ON_ORIENT_IN: return FACE_ON_ORIENT_IN_BIT;
- case FACE_UNCLASSIFIED: return FACE_ANY_BIT;
- default: return 0;
- }
- }
-
- enum EdgeClass {
- EDGE_UNK = -2,
- EDGE_OUT = -1,
- EDGE_ON = 0,
- EDGE_IN = 1
- };
-
-
-
- const char *ENUM(FaceClass f);
- const char *ENUM(PointClass p);
-
-
-
- struct ClassificationInfo {
- const carve::mesh::Mesh<3> *intersected_mesh;
- FaceClass classification;
-
- ClassificationInfo() : intersected_mesh(NULL), classification(FACE_UNCLASSIFIED) { }
- ClassificationInfo(const carve::mesh::Mesh<3> *_intersected_mesh,
- FaceClass _classification) :
- intersected_mesh(_intersected_mesh),
- classification(_classification) {
- }
- bool intersectedMeshIsClosed() const {
- return intersected_mesh->isClosed();
- }
- };
-
-
-
- struct EC2 {
- EdgeClass cls[2];
- EC2() { cls[0] = cls[1] = EDGE_UNK; }
- EC2(EdgeClass a, EdgeClass b) { cls[0] = a; cls[1] = b; }
- };
-
- struct PC2 {
- PointClass cls[2];
- PC2() { cls[0] = cls[1] = POINT_UNK; }
- PC2(PointClass a, PointClass b) { cls[0] = a; cls[1] = b; }
- };
-
- typedef std::unordered_map<std::pair<const carve::mesh::MeshSet<3>::vertex_t *, const carve::mesh::MeshSet<3>::vertex_t *>,
- EC2> EdgeClassification;
-
- typedef std::unordered_map<const carve::mesh::Vertex<3> *, PC2> VertexClassification;
-
- }
-}
diff --git a/extern/carve/include/carve/collection.hpp b/extern/carve/include/carve/collection.hpp
deleted file mode 100644
index 8104d20f9c9..00000000000
--- a/extern/carve/include/carve/collection.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/collection/unordered.hpp>
-
-namespace carve {
-
- template<typename set_t>
- class set_insert_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void> {
-
- protected:
- set_t *set;
- public:
-
- set_insert_iterator(set_t &s) : set(&s) {
- }
-
- set_insert_iterator &
- operator=(typename set_t::const_reference value) {
- set->insert(value);
- return *this;
- }
-
- set_insert_iterator &operator*() { return *this; }
- set_insert_iterator &operator++() { return *this; }
- set_insert_iterator &operator++(int) { return *this; }
- };
-
- template<typename set_t>
- inline set_insert_iterator<set_t>
- set_inserter(set_t &s) {
- return set_insert_iterator<set_t>(s);
- }
-
-}
diff --git a/extern/carve/include/carve/collection/unordered.hpp b/extern/carve/include/carve/collection/unordered.hpp
deleted file mode 100644
index e89022b4141..00000000000
--- a/extern/carve/include/carve/collection/unordered.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
-#if defined(HAVE_STD_UNORDERED_COLLECTIONS)
-
-# include <carve/collection/unordered/std_impl.hpp>
-
-#elif defined(HAVE_TR1_UNORDERED_COLLECTIONS)
-
-# include <carve/collection/unordered/tr1_impl.hpp>
-
-#elif defined(HAVE_BOOST_UNORDERED_COLLECTIONS)
-
-# include <carve/collection/unordered/boost_impl.hpp>
-
-#elif defined(HAVE_LIBSTDCPP_UNORDERED_COLLECTIONS)
-
-# include <carve/collection/unordered/libstdcpp_impl.hpp>
-
-#elif defined(_MSC_VER) && _MSC_VER >= 1300
-
-# include <carve/collection/unordered/vcpp_impl.hpp>
-
-#else
-
-# include <carve/collection/unordered/fallback_impl.hpp>
-
-#endif
diff --git a/extern/carve/include/carve/collection/unordered/boost_impl.hpp b/extern/carve/include/carve/collection/unordered/boost_impl.hpp
deleted file mode 100644
index 7247dce8240..00000000000
--- a/extern/carve/include/carve/collection/unordered/boost_impl.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include BOOST_INCLUDE(unordered_set.hpp)
-#include BOOST_INCLUDE(unordered_map.hpp)
-
-#include <functional>
-
-namespace std {
- template <typename Key, typename T, typename Hash = boost::hash<Key>,
- typename Pred = std::equal_to<Key> >
- class unordered_map : public boost::unordered_map<Key, T, Hash, Pred> {
-
- public:
- typedef T data_type;
- };
-
- template <typename Key, typename T, typename Hash = boost::hash<Key>,
- typename Pred = std::equal_to<Key> >
- class unordered_multimap : public boost::unordered_multimap<Key, T, Hash, Pred> {
- };
-
- template <typename Value, typename Hash = boost::hash<Value>,
- typename Pred = std::equal_to<Value> >
- class unordered_set : public boost::unordered_set<Value, Hash, Pred> {
- };
-}
-
-#undef UNORDERED_COLLECTIONS_SUPPORT_RESIZE
diff --git a/extern/carve/include/carve/collection/unordered/fallback_impl.hpp b/extern/carve/include/carve/collection/unordered/fallback_impl.hpp
deleted file mode 100644
index 98dd19f4a1d..00000000000
--- a/extern/carve/include/carve/collection/unordered/fallback_impl.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <set>
-#include <map>
-
-namespace std {
-
- template<typename K, typename T, typename H = int>
- class unordered_map : public std::map<K, T> {
- typedef std::map<K, T> super;
- public:
- typedef T data_type;
- };
-
- template<typename K, typename H = int>
- class unordered_set : public std::set<K> {
- typedef std::set<K> super;
- public:
- };
-
-}
-
-#undef UNORDERED_COLLECTIONS_SUPPORT_RESIZE
diff --git a/extern/carve/include/carve/collection/unordered/libstdcpp_impl.hpp b/extern/carve/include/carve/collection/unordered/libstdcpp_impl.hpp
deleted file mode 100644
index 6a61abb6829..00000000000
--- a/extern/carve/include/carve/collection/unordered/libstdcpp_impl.hpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
-#include <ext/hash_map>
-#include <ext/hash_set>
-
-namespace __gnu_cxx {
- template <typename T>
- struct hash<T *> : public std::unary_function<T *, size_t> {
- size_t operator()(T *v) const {
- size_t x = (size_t)(v);
- return x + (x>>3);
- }
- };
-
- template <typename A, typename B>
- struct hash<std::pair<A, B> > : public std::unary_function<std::pair<A, B>, size_t> {
- size_t operator()(const std::pair<A, B> &v) const {
- std::size_t seed = 0;
-
- seed ^= hash<A>()(v.first);
- seed ^= hash<B>()(v.second) + (seed<<6) + (seed>>2);
-
- return seed;
- }
- };
-}
-
-namespace std {
-
- template<typename K, typename V, typename H = __gnu_cxx::hash<K> >
- class unordered_map : public __gnu_cxx::hash_map<K, V, H> {
- typedef __gnu_cxx::hash_map<K, V, H> super;
- public:
- typedef typename super::mapped_type data_type;
- };
-
- template<typename K, typename H = __gnu_cxx::hash<K> >
- class unordered_set : public __gnu_cxx::hash_set<K, H> {
- typedef __gnu_cxx::hash_set<K, H> super;
- public:
- };
-
-}
-
-#define UNORDERED_COLLECTIONS_SUPPORT_RESIZE 1
diff --git a/extern/carve/include/carve/collection/unordered/std_impl.hpp b/extern/carve/include/carve/collection/unordered/std_impl.hpp
deleted file mode 100644
index 1d3d4f810bd..00000000000
--- a/extern/carve/include/carve/collection/unordered/std_impl.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <unordered_map>
-#include <unordered_set>
-
-#undef UNORDERED_COLLECTIONS_SUPPORT_RESIZE
diff --git a/extern/carve/include/carve/collection/unordered/tr1_impl.hpp b/extern/carve/include/carve/collection/unordered/tr1_impl.hpp
deleted file mode 100644
index 64789d24ac8..00000000000
--- a/extern/carve/include/carve/collection/unordered/tr1_impl.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <tr1/unordered_map>
-#include <tr1/unordered_set>
-#include <tr1/functional>
-
-namespace std {
- namespace tr1 {
- template <typename A, typename B>
- struct hash<std::pair<A, B> > : public std::unary_function<std::pair<A, B>, size_t> {
- size_t operator()(const std::pair<A, B> &v) const {
- std::size_t seed = 0;
-
- seed ^= hash<A>()(v.first);
- seed ^= hash<B>()(v.second) + (seed<<6) + (seed>>2);
-
- return seed;
- }
- };
- }
-
-
-
- template <typename Key, typename T,
- typename Hash = tr1::hash<Key>,
- typename Pred = std::equal_to<Key> >
- class unordered_map : public std::tr1::unordered_map<Key, T, Hash, Pred> {
- public:
- typedef T data_type;
- };
-
- template <typename Value,
- typename Hash = tr1::hash<Value>,
- typename Pred = std::equal_to<Value> >
- class unordered_set : public std::tr1::unordered_set<Value, Hash, Pred> {
- public:
- };
-
-}
-
-#undef UNORDERED_COLLECTIONS_SUPPORT_RESIZE
diff --git a/extern/carve/include/carve/collection/unordered/vcpp_impl.hpp b/extern/carve/include/carve/collection/unordered/vcpp_impl.hpp
deleted file mode 100644
index eaa1f756126..00000000000
--- a/extern/carve/include/carve/collection/unordered/vcpp_impl.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <hash_map>
-#include <hash_set>
-
-namespace std {
-
- namespace {
-
- template<class Value, class Hash> class hash_traits {
- Hash hash_value;
- std::less<Value> comp;
- public:
- enum {
- bucket_size = 4,
- min_buckets = 8
- };
- // hash _Keyval to size_t value
- size_t operator()(const Value& v) const {
- return ((size_t)hash_value(v));
- }
- // test if _Keyval1 ordered before _Keyval2
- bool operator()(const Value& v1, const Value& v2) const {
- return (comp(v1, v2));
- }
- };
-
- }
-
- template <typename Key, typename T, typename Hash = stdext::hash_compare<Key, less<Key> >, typename Pred = std::equal_to<Key> >
- class unordered_map
- : public stdext::hash_map<Key, T, hash_traits<Key, Hash> > {
- typedef stdext::hash_map<Key, T, hash_traits<Key, Hash> > super;
- public:
- unordered_map() : super() {}
- };
-
- template <typename Value, typename Hash = stdext::hash_compare<Key, less<Key> >, typename Pred = std::equal_to<Value> >
- class unordered_set
- : public stdext::hash_set<Value, hash_traits<Value, Hash> > {
- typedef stdext::hash_set<Value, hash_traits<Value, Hash> > super;
- public:
- unordered_set() : super() {}
- };
-
-}
-
-#undef UNORDERED_COLLECTIONS_SUPPORT_RESIZE
diff --git a/extern/carve/include/carve/collection_types.hpp b/extern/carve/include/carve/collection_types.hpp
deleted file mode 100644
index 8c81737087a..00000000000
--- a/extern/carve/include/carve/collection_types.hpp
+++ /dev/null
@@ -1,63 +0,0 @@
-
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/mesh.hpp>
-
-namespace carve {
- namespace csg {
-
- typedef std::pair<
- carve::mesh::MeshSet<3>::vertex_t *,
- carve::mesh::MeshSet<3>::vertex_t *> V2;
-
- typedef std::pair<
- carve::mesh::MeshSet<3>::face_t *,
- carve::mesh::MeshSet<3>::face_t *> F2;
-
- static inline V2 ordered_edge(
- carve::mesh::MeshSet<3>::vertex_t *a,
- carve::mesh::MeshSet<3>::vertex_t *b) {
- return V2(std::min(a, b), std::max(a, b));
- }
-
- static inline V2 flip(const V2 &v) {
- return V2(v.second, v.first);
- }
-
- // include/carve/csg.hpp include/carve/faceloop.hpp
- // lib/intersect.cpp lib/intersect_classify_common_impl.hpp
- // lib/intersect_classify_edge.cpp
- // lib/intersect_classify_group.cpp
- // lib/intersect_classify_simple.cpp
- // lib/intersect_face_division.cpp lib/intersect_group.cpp
- // lib/intersect_half_classify_group.cpp
- typedef std::unordered_set<V2> V2Set;
-
- // include/carve/csg.hpp include/carve/polyhedron_decl.hpp
- // lib/csg_collector.cpp lib/intersect.cpp
- // lib/intersect_common.hpp lib/intersect_face_division.cpp
- // lib/polyhedron.cpp
- typedef std::unordered_map<
- carve::mesh::MeshSet<3>::vertex_t *,
- carve::mesh::MeshSet<3>::vertex_t *> VVMap;
- }
-}
diff --git a/extern/carve/include/carve/colour.hpp b/extern/carve/include/carve/colour.hpp
deleted file mode 100644
index e21b8f4e4a7..00000000000
--- a/extern/carve/include/carve/colour.hpp
+++ /dev/null
@@ -1,47 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-#include <carve/geom.hpp>
-
-namespace carve {
- namespace colour {
- static inline void HSV2RGB(float H, float S, float V, float &r, float &g, float &b) {
- H = 6.0f * H;
- if (S < 5.0e-6) {
- r = g = b = V; return;
- } else {
- int i = (int)H;
- float f = H - i;
- float p1 = V * (1.0f - S);
- float p2 = V * (1.0f - S * f);
- float p3 = V * (1.0f - S * (1.0f - f));
- switch (i) {
- case 0: r = V; g = p3; b = p1; return;
- case 1: r = p2; g = V; b = p1; return;
- case 2: r = p1; g = V; b = p3; return;
- case 3: r = p1; g = p2; b = V; return;
- case 4: r = p3; g = p1; b = V; return;
- case 5: r = V; g = p1; b = p2; return;
- }
- }
- r = g = b = 0.0;
- }
- }
-}
diff --git a/extern/carve/include/carve/config.h b/extern/carve/include/carve/config.h
deleted file mode 100644
index 3533c1a6710..00000000000
--- a/extern/carve/include/carve/config.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#define CARVE_VERSION "2.0.0a"
-
-#undef CARVE_DEBUG
-#undef CARVE_DEBUG_WRITE_PLY_DATA
-
-#if defined(__GNUC__)
-# if !defined(HAVE_BOOST_UNORDERED_COLLECTIONS)
-# define HAVE_TR1_UNORDERED_COLLECTIONS
-# endif
-
-# define HAVE_STDINT_H
-#endif
-
-// Support for latest Clang/LLVM on FreeBSD which does have different libcxx.
-//
-// TODO(sergey): Move it some some more generic header with platform-specific
-// declarations.
-
-// Indicates whether __is_heap is available
-#undef HAVE_IS_HEAP
-
-#ifdef __GNUC__
-// NeyBSD doesn't have __is_heap
-# ifndef __NetBSD__
-# define HAVE_IS_HEAP
-# ifdef _LIBCPP_VERSION
-# define __is_heap is_heap
-# endif // _LIBCPP_VERSION
-# endif // !__NetBSD__
-#endif // __GNUC__
diff --git a/extern/carve/include/carve/convex_hull.hpp b/extern/carve/include/carve/convex_hull.hpp
deleted file mode 100644
index b7296ca1164..00000000000
--- a/extern/carve/include/carve/convex_hull.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <list>
-#include <vector>
-#include <algorithm>
-
-#include <carve/carve.hpp>
-
-#include <carve/geom2d.hpp>
-
-namespace carve {
- namespace geom {
- std::vector<int> convexHull(const std::vector<carve::geom2d::P2> &points);
-
- template<typename project_t, typename polygon_container_t>
- std::vector<int> convexHull(const project_t &project, const polygon_container_t &points) {
- std::vector<carve::geom2d::P2> proj;
- proj.reserve(points.size());
- for (typename polygon_container_t::const_iterator i = points.begin(); i != points.end(); ++i) {
- proj.push_back(project(*i));
- }
- return convexHull(proj);
- }
-
- template<typename project_t, typename iter_t>
- std::vector<int> convexHull(const project_t &project, iter_t beg, iter_t end, size_t size_hint = 0) {
- std::vector<carve::geom2d::P2> proj;
- if (size_hint) proj.reserve(size_hint);
- for (; beg != end; ++beg) {
- proj.push_back(project(*beg));
- }
- return convexHull(proj);
- }
- }
-}
diff --git a/extern/carve/include/carve/csg.hpp b/extern/carve/include/carve/csg.hpp
deleted file mode 100644
index 6ecfca0d4cb..00000000000
--- a/extern/carve/include/carve/csg.hpp
+++ /dev/null
@@ -1,510 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <list>
-#include <vector>
-#include <algorithm>
-
-#include <carve/carve.hpp>
-
-#include <carve/geom3d.hpp>
-
-#include <carve/mesh.hpp>
-
-#include <carve/collection_types.hpp>
-#include <carve/classification.hpp>
-#include <carve/iobj.hpp>
-#include <carve/faceloop.hpp>
-#include <carve/intersection.hpp>
-#include <carve/rtree.hpp>
-
-namespace carve {
- namespace csg {
-
- class VertexPool {
- typedef carve::mesh::MeshSet<3>::vertex_t vertex_t;
-
- const static unsigned blocksize = 1024;
- typedef std::list<std::vector<vertex_t> > pool_t;
- pool_t pool;
- public:
- void reset();
- vertex_t *get(const vertex_t::vector_t &v = vertex_t::vector_t::ZERO());
- bool inPool(vertex_t *v) const;
-
- VertexPool();
- ~VertexPool();
- };
-
-
-
- namespace detail {
- struct Data;
- class LoopEdges;
- }
-
- /**
- * \class CSG
- * \brief The class responsible for the computation of CSG operations.
- *
- */
- class CSG {
- private:
-
- public:
- typedef carve::mesh::MeshSet<3> meshset_t;
-
- struct Hook {
- /**
- * \class Hook
- * \brief Provides API access to intermediate steps in CSG calculation.
- *
- */
- virtual void intersectionVertex(const meshset_t::vertex_t * /* vertex */,
- const IObjPairSet & /* intersections */) {
- }
- virtual void processOutputFace(std::vector<meshset_t::face_t *> & /* faces */,
- const meshset_t::face_t * /* orig_face */,
- bool /* flipped */) {
- }
- virtual void resultFace(const meshset_t::face_t * /* new_face */,
- const meshset_t::face_t * /* orig_face */,
- bool /* flipped */) {
- }
- virtual void edgeDivision(const meshset_t::edge_t * /* orig_edge */,
- size_t /* orig_edge_idx */,
- const meshset_t::vertex_t * /* v1 */,
- const meshset_t::vertex_t * /* v2 */) {
- }
-
- virtual ~Hook() {
- }
- };
-
- /**
- * \class Hooks
- * \brief Management of API hooks.
- *
- */
- class Hooks {
- public:
- enum {
- RESULT_FACE_HOOK = 0,
- PROCESS_OUTPUT_FACE_HOOK = 1,
- INTERSECTION_VERTEX_HOOK = 2,
- EDGE_DIVISION_HOOK = 3,
- HOOK_MAX = 4,
-
- RESULT_FACE_BIT = 0x0001,
- PROCESS_OUTPUT_FACE_BIT = 0x0002,
- INTERSECTION_VERTEX_BIT = 0x0004,
- EDGE_DIVISION_BIT = 0x0008
- };
-
- std::vector<std::list<Hook *> > hooks;
-
- bool hasHook(unsigned hook_num);
-
- void intersectionVertex(const meshset_t::vertex_t *vertex,
- const IObjPairSet &intersections);
-
- void processOutputFace(std::vector<meshset_t::face_t *> &faces,
- const meshset_t::face_t *orig_face,
- bool flipped);
-
- void resultFace(const meshset_t::face_t *new_face,
- const meshset_t::face_t *orig_face,
- bool flipped);
-
- void edgeDivision(const meshset_t::edge_t *orig_edge,
- size_t orig_edge_idx,
- const meshset_t::vertex_t *v1,
- const meshset_t::vertex_t *v2);
-
- void registerHook(Hook *hook, unsigned hook_bits);
- void unregisterHook(Hook *hook);
-
- void reset();
-
- Hooks();
- ~Hooks();
- };
-
- /**
- * \class Collector
- * \brief Base class for objects responsible for selecting result from which form the result polyhedron.
- *
- */
- class Collector {
- Collector(const Collector &);
- Collector &operator=(const Collector &);
-
- protected:
-
- public:
- virtual void collect(FaceLoopGroup *group, CSG::Hooks &) =0;
- virtual meshset_t *done(CSG::Hooks &) =0;
-
- Collector() {}
- virtual ~Collector() {}
- };
-
- private:
- typedef carve::geom::RTreeNode<3, carve::mesh::Face<3> *> face_rtree_t;
- typedef std::unordered_map<carve::mesh::Face<3> *, std::vector<carve::mesh::Face<3> *> > face_pairs_t;
-
- /// The computed intersection data.
- Intersections intersections;
-
- /// A map from intersection point to a set of intersections
- /// represented by pairs of intersection objects.
- VertexIntersections vertex_intersections;
-
- /// A pool from which temporary vertices are allocated. Also
- /// provides testing for pool membership.
- VertexPool vertex_pool;
-
- void init();
-
- void makeVertexIntersections();
-
- void groupIntersections();
-
- void _generateVertexVertexIntersections(meshset_t::vertex_t *va,
- meshset_t::edge_t *eb);
- void generateVertexVertexIntersections(meshset_t::face_t *a,
- const std::vector<meshset_t::face_t *> &b);
-
- void _generateVertexEdgeIntersections(meshset_t::vertex_t *va,
- meshset_t::edge_t *eb);
- void generateVertexEdgeIntersections(meshset_t::face_t *a,
- const std::vector<meshset_t::face_t *> &b);
-
- void _generateEdgeEdgeIntersections(meshset_t::edge_t *ea,
- meshset_t::edge_t *eb);
- void generateEdgeEdgeIntersections(meshset_t::face_t *a,
- const std::vector<meshset_t::face_t *> &b);
-
- void _generateVertexFaceIntersections(meshset_t::face_t *fa,
- meshset_t::edge_t *eb);
- void generateVertexFaceIntersections(meshset_t::face_t *a,
- const std::vector<meshset_t::face_t *> &b);
-
- void _generateEdgeFaceIntersections(meshset_t::face_t *fa,
- meshset_t::edge_t *eb);
- void generateEdgeFaceIntersections(meshset_t::face_t *a,
- const std::vector<meshset_t::face_t *> &b);
-
- void generateIntersectionCandidates(meshset_t *a,
- const face_rtree_t *a_node,
- meshset_t *b,
- const face_rtree_t *b_node,
- face_pairs_t &face_pairs,
- bool descend_a = true);
- /**
- * \brief Compute all points of intersection between poly \a a and poly \a b
- *
- * @param a Polyhedron a.
- * @param b Polyhedron b.
- */
- void generateIntersections(meshset_t *a,
- const face_rtree_t *a_node,
- meshset_t *b,
- const face_rtree_t *b_node,
- detail::Data &data);
-
- /**
- * \brief Generate tables of intersecting pairs of faces.
- *
- * @param[out] data Internal data-structure holding intersection info.
- */
- void intersectingFacePairs(detail::Data &data);
-
- /**
- * \brief Divide edges in \a edges that are intersected by polyhedron \a poly
- *
- * @param edges The edges to divide.
- * @param[in] poly The polyhedron to divide against.
- * @param[in,out] data Intersection information.
- */
- void divideEdges(
- const std::vector<meshset_t::edge_t> &edges,
- meshset_t *poly,
- detail::Data &data);
-
- void divideIntersectedEdges(detail::Data &data);
-
- /**
- * \brief From the intersection points of pairs of intersecting faces, compute intersection edges.
- *
- * @param[out] eclass Classification information about created edges.
- * @param[in,out] data Intersection information.
- */
- void makeFaceEdges(
- EdgeClassification &eclass,
- detail::Data &data);
-
- friend void classifyEasyFaces(
- FaceLoopList &face_loops,
- VertexClassification &vclass,
- meshset_t *other_poly,
- int other_poly_num,
- CSG &csg,
- CSG::Collector &collector);
-
- size_t generateFaceLoops(
- meshset_t *poly,
- const detail::Data &data,
- FaceLoopList &face_loops_out);
-
-
-
- // intersect_group.cpp
-
- /**
- * \brief Build a loop edge mapping from a list of face loops.
- *
- * @param[in] loops A list of face loops.
- * @param[in] edge_count A hint as to the number of edges in \a loops.
- * @param[out] edge_map The calculated map of edges to loops.
- */
- void makeEdgeMap(
- const FaceLoopList &loops,
- size_t edge_count,
- detail::LoopEdges &edge_map);
-
- /**
- * \brief Divide a list of face loops into groups that are connected by at least one edge not present in \a no_cross.
- *
- * @param[in] src The source mesh from which these loops derive.
- * @param[in,out] face_loops The list of loops (will be emptied as a side effect)
- * @param[in] loop_edges A loop edge map used for traversing connected loops.
- * @param[in] no_cross A set of edges not to cross.
- * @param[out] out_loops A list of grouped face loops.
- */
- void groupFaceLoops(
- meshset_t *src,
- FaceLoopList &face_loops,
- const detail::LoopEdges &loop_edges,
- const V2Set &no_cross,
- FLGroupList &out_loops);
-
- /**
- * \brief Find the set of edges shared between two edge maps.
- *
- * @param[in] edge_map_a The first edge map.
- * @param[in] edge_map_b The second edge map.
- * @param[out] shared_edges The resulting set of common edges.
- */
- void findSharedEdges(
- const detail::LoopEdges &edge_map_a,
- const detail::LoopEdges &edge_map_b,
- V2Set &shared_edges);
-
-
- // intersect_classify_edge.cpp
-
- /**
- *
- *
- * @param shared_edges
- * @param vclass
- * @param poly_a
- * @param a_loops_grouped
- * @param a_edge_map
- * @param poly_b
- * @param b_loops_grouped
- * @param b_edge_map
- * @param collector
- */
- void classifyFaceGroupsEdge(
- const V2Set &shared_edges,
- VertexClassification &vclass,
- meshset_t *poly_a,
- const face_rtree_t *poly_a_rtree,
- FLGroupList &a_loops_grouped,
- const detail::LoopEdges &a_edge_map,
- meshset_t *poly_b,
- const face_rtree_t *poly_b_rtree,
- FLGroupList &b_loops_grouped,
- const detail::LoopEdges &b_edge_map,
- CSG::Collector &collector);
-
- // intersect_classify_group.cpp
-
- /**
- *
- *
- * @param shared_edges
- * @param vclass
- * @param poly_a
- * @param a_loops_grouped
- * @param a_edge_map
- * @param poly_b
- * @param b_loops_grouped
- * @param b_edge_map
- * @param collector
- */
- void classifyFaceGroups(
- const V2Set &shared_edges,
- VertexClassification &vclass,
- meshset_t *poly_a,
- const face_rtree_t *poly_a_rtree,
- FLGroupList &a_loops_grouped,
- const detail::LoopEdges &a_edge_map,
- meshset_t *poly_b,
- const face_rtree_t *poly_b_rtree,
- FLGroupList &b_loops_grouped,
- const detail::LoopEdges &b_edge_map,
- CSG::Collector &collector);
-
- // intersect_half_classify_group.cpp
-
- /**
- *
- *
- * @param shared_edges
- * @param vclass
- * @param poly_a
- * @param a_loops_grouped
- * @param a_edge_map
- * @param poly_b
- * @param b_loops_grouped
- * @param b_edge_map
- * @param FaceClass
- * @param b_out
- */
- void halfClassifyFaceGroups(
- const V2Set &shared_edges,
- VertexClassification &vclass,
- meshset_t *poly_a,
- const face_rtree_t *poly_a_rtree,
- FLGroupList &a_loops_grouped,
- const detail::LoopEdges &a_edge_map,
- meshset_t *poly_b,
- const face_rtree_t *poly_b_rtree,
- FLGroupList &b_loops_grouped,
- const detail::LoopEdges &b_edge_map,
- std::list<std::pair<FaceClass, meshset_t *> > &b_out);
-
- // intersect.cpp
-
- /**
- * \brief The main calculation method for CSG.
- *
- * @param[in] a Polyhedron a
- * @param[in] b Polyhedron b
- * @param[out] vclass
- * @param[out] eclass
- * @param[out] a_face_loops
- * @param[out] b_face_loops
- * @param[out] a_edge_count
- * @param[out] b_edge_count
- */
- void calc(
- meshset_t *a,
- const face_rtree_t *a_rtree,
- meshset_t *b,
- const face_rtree_t *b_rtree,
- VertexClassification &vclass,
- EdgeClassification &eclass,
- FaceLoopList &a_face_loops,
- FaceLoopList &b_face_loops,
- size_t &a_edge_count,
- size_t &b_edge_count);
-
- public:
- /**
- * \enum OP
- * \brief Enumeration of the supported CSG operations.
- */
- enum OP {
- UNION, /**< in a or b. */
- INTERSECTION, /**< in a and b. */
- A_MINUS_B, /**< in a, but not b. */
- B_MINUS_A, /**< in b, but not a. */
- SYMMETRIC_DIFFERENCE, /**< in a or b, but not both. */
- ALL /**< all split faces from a and b */
- };
-
- /**
- * \enum CLASSIFY_TYPE
- * \brief The type of classification algorithm to use.
- */
- enum CLASSIFY_TYPE {
- CLASSIFY_NORMAL, /**< Normal (group) classifier. */
- CLASSIFY_EDGE /**< Edge classifier. */
- };
-
- CSG::Hooks hooks; /**< The manager for calculation hooks. */
-
- CSG();
- ~CSG();
-
- /**
- * \brief Compute a CSG operation between two polyhedra, \a a and \a b.
- *
- * @param a Polyhedron a
- * @param b Polyhedron b
- * @param collector The collector (determines the CSG operation performed)
- * @param shared_edges A pointer to a set that will be populated with shared edges (if not NULL).
- * @param classify_type The type of classifier to use.
- *
- * @return
- */
- meshset_t *compute(
- meshset_t *a,
- meshset_t *b,
- CSG::Collector &collector,
- V2Set *shared_edges = NULL,
- CLASSIFY_TYPE classify_type = CLASSIFY_NORMAL);
-
- /**
- * \brief Compute a CSG operation between two closed polyhedra, \a a and \a b.
- *
- * @param a Polyhedron a
- * @param b Polyhedron b
- * @param op The CSG operation (A collector is created automatically).
- * @param shared_edges A pointer to a set that will be populated with shared edges (if not NULL).
- * @param classify_type The type of classifier to use.
- *
- * @return
- */
- meshset_t *compute(
- meshset_t *a,
- meshset_t *b,
- OP op,
- V2Set *shared_edges = NULL,
- CLASSIFY_TYPE classify_type = CLASSIFY_NORMAL);
-
- void slice(
- meshset_t *a,
- meshset_t *b,
- std::list<meshset_t *> &a_sliced,
- std::list<meshset_t *> &b_sliced,
- V2Set *shared_edges = NULL);
-
- bool sliceAndClassify(
- meshset_t *closed,
- meshset_t *open,
- std::list<std::pair<FaceClass, meshset_t *> > &result,
- V2Set *shared_edges = NULL);
- };
- }
-}
diff --git a/extern/carve/include/carve/csg_triangulator.hpp b/extern/carve/include/carve/csg_triangulator.hpp
deleted file mode 100644
index 4765d0b6703..00000000000
--- a/extern/carve/include/carve/csg_triangulator.hpp
+++ /dev/null
@@ -1,435 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#include <carve/csg.hpp>
-#include <carve/tag.hpp>
-#include <carve/poly.hpp>
-#include <carve/triangulator.hpp>
-#include <deque>
-
-namespace carve {
- namespace csg {
-
- namespace detail {
- template<bool with_improvement>
- class CarveTriangulator : public csg::CSG::Hook {
-
- public:
- CarveTriangulator() {
- }
-
- virtual ~CarveTriangulator() {
- }
-
- virtual void processOutputFace(std::vector<carve::mesh::MeshSet<3>::face_t *> &faces,
- const carve::mesh::MeshSet<3>::face_t *orig,
- bool flipped) {
- std::vector<carve::mesh::MeshSet<3>::face_t *> out_faces;
-
- size_t n_tris = 0;
- for (size_t f = 0; f < faces.size(); ++f) {
- CARVE_ASSERT(faces[f]->nVertices() >= 3);
- n_tris += faces[f]->nVertices() - 2;
- }
-
- out_faces.reserve(n_tris);
-
- for (size_t f = 0; f < faces.size(); ++f) {
- carve::mesh::MeshSet<3>::face_t *face = faces[f];
-
- if (face->nVertices() == 3) {
- out_faces.push_back(face);
- continue;
- }
-
- std::vector<triangulate::tri_idx> result;
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> vloop;
- face->getVertices(vloop);
-
- triangulate::triangulate(
- carve::mesh::MeshSet<3>::face_t::projection_mapping(face->project),
- vloop,
- result);
-
- if (with_improvement) {
- triangulate::improve(
- carve::mesh::MeshSet<3>::face_t::projection_mapping(face->project),
- vloop,
- carve::mesh::vertex_distance(),
- result);
- }
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> fv;
- fv.resize(3);
- for (size_t i = 0; i < result.size(); ++i) {
- fv[0] = vloop[result[i].a];
- fv[1] = vloop[result[i].b];
- fv[2] = vloop[result[i].c];
- out_faces.push_back(face->create(fv.begin(), fv.end(), false));
- }
- delete face;
- }
- std::swap(faces, out_faces);
- }
- };
- }
-
- typedef detail::CarveTriangulator<false> CarveTriangulator;
- typedef detail::CarveTriangulator<true> CarveTriangulatorWithImprovement;
-
- class CarveTriangulationImprover : public csg::CSG::Hook {
- public:
- CarveTriangulationImprover() {
- }
-
- virtual ~CarveTriangulationImprover() {
- }
-
- virtual void processOutputFace(std::vector<carve::mesh::MeshSet<3>::face_t *> &faces,
- const carve::mesh::MeshSet<3>::face_t *orig,
- bool flipped) {
- if (faces.size() == 1) return;
-
- // doing improvement as a separate hook is much messier than
- // just incorporating it into the triangulation hook.
-
- typedef std::map<carve::mesh::MeshSet<3>::vertex_t *, size_t> vert_map_t;
- std::vector<carve::mesh::MeshSet<3>::face_t *> out_faces;
- vert_map_t vert_map;
-
- out_faces.reserve(faces.size());
-
-
- carve::mesh::MeshSet<3>::face_t::projection_mapping projector(faces[0]->project);
-
- std::vector<triangulate::tri_idx> result;
-
- for (size_t f = 0; f < faces.size(); ++f) {
- carve::mesh::MeshSet<3>::face_t *face = faces[f];
- if (face->nVertices() != 3) {
- out_faces.push_back(face);
- } else {
- triangulate::tri_idx tri;
- for (carve::mesh::MeshSet<3>::face_t::edge_iter_t i = face->begin(); i != face->end(); ++i) {
- size_t v = 0;
- vert_map_t::iterator j = vert_map.find(i->vert);
- if (j == vert_map.end()) {
- v = vert_map.size();
- vert_map[i->vert] = v;
- } else {
- v = (*j).second;
- }
- tri.v[i.idx()] = v;
- }
- result.push_back(tri);
- delete face;
- }
- }
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> verts;
- verts.resize(vert_map.size());
- for (vert_map_t::iterator i = vert_map.begin(); i != vert_map.end(); ++i) {
- verts[(*i).second] = (*i).first;
- }
-
- triangulate::improve(projector, verts, carve::mesh::vertex_distance(), result);
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> fv;
- fv.resize(3);
- for (size_t i = 0; i < result.size(); ++i) {
- fv[0] = verts[result[i].a];
- fv[1] = verts[result[i].b];
- fv[2] = verts[result[i].c];
- out_faces.push_back(orig->create(fv.begin(), fv.end(), false));
- }
-
- std::swap(faces, out_faces);
- }
- };
-
- class CarveTriangulationQuadMerger : public csg::CSG::Hook {
- // this code is incomplete.
- typedef std::map<V2, F2> edge_map_t;
-
- public:
- CarveTriangulationQuadMerger() {
- }
-
- virtual ~CarveTriangulationQuadMerger() {
- }
-
- double scoreQuad(edge_map_t::iterator i, edge_map_t &edge_map) {
- if (!(*i).second.first || !(*i).second.second) return -1;
- return -1;
- }
-
- carve::mesh::MeshSet<3>::face_t *mergeQuad(edge_map_t::iterator i, edge_map_t &edge_map) {
- return NULL;
- }
-
- void recordEdge(carve::mesh::MeshSet<3>::vertex_t *v1,
- carve::mesh::MeshSet<3>::vertex_t *v2,
- carve::mesh::MeshSet<3>::face_t *f,
- edge_map_t &edge_map) {
- if (v1 < v2) {
- edge_map[V2(v1, v2)].first = f;
- } else {
- edge_map[V2(v2, v1)].second = f;
- }
- }
-
- virtual void processOutputFace(std::vector<carve::mesh::MeshSet<3>::face_t *> &faces,
- const carve::mesh::MeshSet<3>::face_t *orig,
- bool flipped) {
- if (faces.size() == 1) return;
-
- std::vector<carve::mesh::MeshSet<3>::face_t *> out_faces;
- edge_map_t edge_map;
-
- out_faces.reserve(faces.size());
-
- poly::p2_adapt_project<3> projector(faces[0]->project);
-
- for (size_t f = 0; f < faces.size(); ++f) {
- carve::mesh::MeshSet<3>::face_t *face = faces[f];
- if (face->nVertices() != 3) {
- out_faces.push_back(face);
- } else {
- carve::mesh::MeshSet<3>::face_t::vertex_t *v1, *v2, *v3;
- v1 = face->edge->vert;
- v2 = face->edge->next->vert;
- v3 = face->edge->next->next->vert;
- recordEdge(v1, v2, face, edge_map);
- recordEdge(v2, v3, face, edge_map);
- recordEdge(v3, v1, face, edge_map);
- }
- }
-
- for (edge_map_t::iterator i = edge_map.begin(); i != edge_map.end();) {
- if ((*i).second.first && (*i).second.second) {
- ++i;
- } else {
- edge_map.erase(i++);
- }
- }
-
- while (edge_map.size()) {
- edge_map_t::iterator i = edge_map.begin();
- edge_map_t::iterator best = i;
- double best_score = scoreQuad(i, edge_map);
- for (++i; i != edge_map.end(); ++i) {
- double score = scoreQuad(i, edge_map);
- if (score > best_score) best = i;
- }
- if (best_score < 0) break;
- out_faces.push_back(mergeQuad(best, edge_map));
- }
-
- if (edge_map.size()) {
- tagable::tag_begin();
- for (edge_map_t::iterator i = edge_map.begin(); i != edge_map.end(); ++i) {
- carve::mesh::MeshSet<3>::face_t *a = const_cast<carve::mesh::MeshSet<3>::face_t *>((*i).second.first);
- carve::mesh::MeshSet<3>::face_t *b = const_cast<carve::mesh::MeshSet<3>::face_t *>((*i).second.first);
- if (a && a->tag_once()) out_faces.push_back(a);
- if (b && b->tag_once()) out_faces.push_back(b);
- }
- }
-
- std::swap(faces, out_faces);
- }
- };
-
- class CarveHoleResolver : public csg::CSG::Hook {
-
- public:
- CarveHoleResolver() {
- }
-
- virtual ~CarveHoleResolver() {
- }
-
- bool findRepeatedEdges(const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &vertices,
- std::list<std::pair<size_t, size_t> > &edge_pos) {
- std::map<V2, size_t> edges;
- for (size_t i = 0; i < vertices.size() - 1; ++i) {
- edges[std::make_pair(vertices[i], vertices[i+1])] = i;
- }
- edges[std::make_pair(vertices[vertices.size()-1], vertices[0])] = vertices.size() - 1;
-
- for (std::map<V2, size_t>::iterator i = edges.begin(); i != edges.end(); ++i) {
- V2 rev = V2((*i).first.second, (*i).first.first);
- std::map<V2, size_t>::iterator j = edges.find(rev);
- if (j != edges.end()) {
- edge_pos.push_back(std::make_pair((*i).second, (*j).second));
- }
- }
- return edge_pos.size() > 0;
- }
-
- void flood(size_t t1,
- size_t t2,
- size_t old_grp,
- size_t new_grp_1,
- size_t new_grp_2,
- std::vector<size_t> &grp,
- const std::vector<triangulate::tri_idx> &tris,
- const std::map<std::pair<size_t, size_t>, size_t> &tri_edge) {
- grp[t1] = new_grp_1;
- grp[t2] = new_grp_2;
-
- std::deque<size_t> to_visit;
- to_visit.push_back(t1);
- to_visit.push_back(t2);
- std::vector<std::pair<size_t, size_t> > rev;
- rev.resize(3);
- while (to_visit.size()) {
- size_t curr = to_visit.front();
- to_visit.pop_front();
- triangulate::tri_idx ct = tris[curr];
- rev[0] = std::make_pair(ct.b, ct.a);
- rev[1] = std::make_pair(ct.c, ct.b);
- rev[2] = std::make_pair(ct.a, ct.c);
-
- for (size_t i = 0; i < 3; ++i) {
- std::map<std::pair<size_t, size_t>, size_t>::const_iterator adj = tri_edge.find(rev[i]);
- if (adj == tri_edge.end()) continue;
- size_t next = (*adj).second;
- if (grp[next] != old_grp) continue;
- grp[next] = grp[curr];
- to_visit.push_back(next);
- }
- }
- }
-
- void findPerimeter(const std::vector<triangulate::tri_idx> &tris,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &verts,
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &out) {
- std::map<std::pair<size_t, size_t>, size_t> edges;
- for (size_t i = 0; i < tris.size(); ++i) {
- edges[std::make_pair(tris[i].a, tris[i].b)] = i;
- edges[std::make_pair(tris[i].b, tris[i].c)] = i;
- edges[std::make_pair(tris[i].c, tris[i].a)] = i;
- }
- std::map<size_t, size_t> unpaired;
- for (std::map<std::pair<size_t, size_t>, size_t>::iterator i = edges.begin(); i != edges.end(); ++i) {
- if (edges.find(std::make_pair((*i).first.second, (*i).first.first)) == edges.end()) {
- CARVE_ASSERT(unpaired.find((*i).first.first) == unpaired.end());
- unpaired[(*i).first.first] = (*i).first.second;
- }
- }
- out.clear();
- out.reserve(unpaired.size());
- size_t start = (*unpaired.begin()).first;
- size_t vert = start;
- do {
- out.push_back(verts[vert]);
- CARVE_ASSERT(unpaired.find(vert) != unpaired.end());
- vert = unpaired[vert];
- } while (vert != start);
- }
-
- virtual void processOutputFace(std::vector<carve::mesh::MeshSet<3>::face_t *> &faces,
- const carve::mesh::MeshSet<3>::face_t *orig,
- bool flipped) {
- std::vector<carve::mesh::MeshSet<3>::face_t *> out_faces;
-
- for (size_t f = 0; f < faces.size(); ++f) {
- carve::mesh::MeshSet<3>::face_t *face = faces[f];
-
- if (face->nVertices() == 3) {
- out_faces.push_back(face);
- continue;
- }
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> vloop;
- face->getVertices(vloop);
-
- std::list<std::pair<size_t, size_t> > rep_edges;
- if (!findRepeatedEdges(vloop, rep_edges)) {
- out_faces.push_back(face);
- continue;
- }
-
- std::vector<triangulate::tri_idx> result;
- triangulate::triangulate(
- carve::mesh::MeshSet<3>::face_t::projection_mapping(face->project),
- vloop,
- result);
-
- std::map<std::pair<size_t, size_t>, size_t> tri_edge;
- for (size_t i = 0; i < result.size(); ++i) {
- tri_edge[std::make_pair(result[i].a, result[i].b)] = i;
- tri_edge[std::make_pair(result[i].b, result[i].c)] = i;
- tri_edge[std::make_pair(result[i].c, result[i].a)] = i;
- }
-
- std::vector<size_t> grp;
- grp.resize(result.size(), 0);
-
- size_t grp_max = 0;
-
- while (rep_edges.size()) {
- std::pair<size_t, size_t> e1, e2;
-
- e1.first = rep_edges.front().first;
- e1.second = (e1.first + 1) % vloop.size();
-
- e2.first = rep_edges.front().second;
- e2.second = (e2.first + 1) % vloop.size();
-
- rep_edges.pop_front();
-
- CARVE_ASSERT(tri_edge.find(e1) != tri_edge.end());
- size_t t1 = tri_edge[e1];
- CARVE_ASSERT(tri_edge.find(e2) != tri_edge.end());
- size_t t2 = tri_edge[e2];
-
- if (grp[t1] != grp[t2]) {
- continue;
- }
-
- size_t t1g = ++grp_max;
- size_t t2g = ++grp_max;
-
- flood(t1, t2, grp[t1], t1g, t2g, grp, result, tri_edge);
- }
-
- std::set<size_t> groups;
- std::copy(grp.begin(), grp.end(), std::inserter(groups, groups.begin()));
-
- // now construct perimeters for each group.
- std::vector<triangulate::tri_idx> grp_tris;
- grp_tris.reserve(result.size());
- for (std::set<size_t>::iterator i = groups.begin(); i != groups.end(); ++i) {
- size_t grp_id = *i;
- grp_tris.clear();
- for (size_t j = 0; j < grp.size(); ++j) {
- if (grp[j] == grp_id) {
- grp_tris.push_back(result[j]);
- }
- }
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> grp_perim;
- findPerimeter(grp_tris, vloop, grp_perim);
- out_faces.push_back(face->create(grp_perim.begin(), grp_perim.end(), false));
- }
- delete face;
- }
- std::swap(faces, out_faces);
- }
- };
- }
-}
diff --git a/extern/carve/include/carve/debug_hooks.hpp b/extern/carve/include/carve/debug_hooks.hpp
deleted file mode 100644
index 53de8634e0d..00000000000
--- a/extern/carve/include/carve/debug_hooks.hpp
+++ /dev/null
@@ -1,97 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/vector.hpp>
-#include <carve/geom3d.hpp>
-#include <carve/csg.hpp>
-
-#include <iomanip>
-
-template<typename MAP>
-void map_histogram(std::ostream &out, const MAP &map) {
- std::vector<int> hist;
- for (typename MAP::const_iterator i = map.begin(); i != map.end(); ++i) {
- size_t n = (*i).second.size();
- if (hist.size() <= n) {
- hist.resize(n + 1);
- }
- hist[n]++;
- }
- int total = (int)map.size();
- std::string bar(50, '*');
- for (size_t i = 0; i < hist.size(); i++) {
- if (hist[i] > 0) {
- out << std::setw(5) << i << " : " << std::setw(5) << hist[i] << " " << bar.substr((size_t)(50 - hist[i] * 50 / total)) << std::endl;
- }
- }
-}
-
-namespace carve {
- namespace csg {
- class IntersectDebugHooks {
- public:
- virtual void drawIntersections(const VertexIntersections & /* vint */) {
- }
-
- virtual void drawPoint(const carve::mesh::MeshSet<3>::vertex_t * /* v */,
- float /* r */,
- float /* g */,
- float /* b */,
- float /* a */,
- float /* rad */) {
- }
- virtual void drawEdge(const carve::mesh::MeshSet<3>::vertex_t * /* v1 */,
- const carve::mesh::MeshSet<3>::vertex_t * /* v2 */,
- float /* rA */, float /* gA */, float /* bA */, float /* aA */,
- float /* rB */, float /* gB */, float /* bB */, float /* aB */,
- float /* thickness */ = 1.0) {
- }
-
- virtual void drawFaceLoopWireframe(const std::vector<carve::mesh::MeshSet<3>::vertex_t *> & /* face_loop */,
- const carve::mesh::MeshSet<3>::vertex_t & /* normal */,
- float /* r */, float /* g */, float /* b */, float /* a */,
- bool /* inset */ = true) {
- }
-
- virtual void drawFaceLoop(const std::vector<carve::mesh::MeshSet<3>::vertex_t *> & /* face_loop */,
- const carve::mesh::MeshSet<3>::vertex_t & /* normal */,
- float /* r */, float /* g */, float /* b */, float /* a */,
- bool /* offset */ = true,
- bool /* lit */ = true) {
- }
-
- virtual void drawFaceLoop2(const std::vector<carve::mesh::MeshSet<3>::vertex_t *> & /* face_loop */,
- const carve::mesh::MeshSet<3>::vertex_t & /* normal */,
- float /* rF */, float /* gF */, float /* bF */, float /* aF */,
- float /* rB */, float /* gB */, float /* bB */, float /* aB */,
- bool /* offset */ = true,
- bool /* lit */ = true) {
- }
-
- virtual ~IntersectDebugHooks() {
- }
- };
-
- IntersectDebugHooks *intersect_installDebugHooks(IntersectDebugHooks *hooks);
- bool intersect_debugEnabled();
-
- }
-}
diff --git a/extern/carve/include/carve/djset.hpp b/extern/carve/include/carve/djset.hpp
deleted file mode 100644
index 90f50923928..00000000000
--- a/extern/carve/include/carve/djset.hpp
+++ /dev/null
@@ -1,134 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-#include <vector>
-
-
-
-namespace carve {
-namespace djset {
-
-
-
- class djset {
-
- protected:
- struct elem {
- size_t parent, rank;
- elem(size_t p, size_t r) : parent(p), rank(r) {}
- elem() {}
- };
-
- std::vector<elem> set;
- size_t n_sets;
-
- public:
- djset() : set(), n_sets(0) {
- }
-
- djset(size_t N) {
- n_sets = N;
- set.reserve(N);
- for (size_t i = 0; i < N; ++i) {
- set.push_back(elem(i,0));
- }
- }
-
- void init(size_t N) {
- if (N == set.size()) {
- for (size_t i = 0; i < N; ++i) {
- set[i] = elem(i,0);
- }
- n_sets = N;
- } else {
- djset temp(N);
- std::swap(set, temp.set);
- std::swap(n_sets, temp.n_sets);
- }
- }
-
- size_t count() const {
- return n_sets;
- }
-
- size_t find_set_head(size_t a) {
- if (a == set[a].parent) return a;
-
- size_t a_head = a;
- while (set[a_head].parent != a_head) a_head = set[a_head].parent;
- set[a].parent = a_head;
- return a_head;
- }
-
- bool same_set(size_t a, size_t b) {
- return find_set_head(a) == find_set_head(b);
- }
-
- void merge_sets(size_t a, size_t b) {
- a = find_set_head(a);
- b = find_set_head(b);
- if (a != b) {
- n_sets--;
- if (set[a].rank < set[b].rank) {
- set[a].parent = b;
- } else if (set[b].rank < set[a].rank) {
- set[b].parent = a;
- } else {
- set[a].rank++;
- set[b].parent = a;
- }
- }
- }
-
- void get_index_to_set(std::vector<size_t> &index_set, std::vector<size_t> &set_size) {
- index_set.clear();
- index_set.resize(set.size(), n_sets);
- set_size.clear();
- set_size.resize(n_sets, 0);
-
- size_t c = 0;
- for (size_t i = 0; i < set.size(); ++i) {
- size_t s = find_set_head(i);
- if (index_set[s] == n_sets) index_set[s] = c++;
- index_set[i] = index_set[s];
- set_size[index_set[s]]++;
- }
- }
-
- template<typename in_iter_t, typename out_collection_t>
- void collate(in_iter_t in, out_collection_t &out) {
- std::vector<size_t> set_id(set.size(), n_sets);
- out.clear();
- out.resize(n_sets);
- size_t c = 0;
- for (size_t i = 0; i < set.size(); ++i) {
- size_t s = find_set_head(i);
- if (set_id[s] == n_sets) set_id[s] = c++;
- s = set_id[s];
- std::insert_iterator<typename out_collection_t::value_type> j(out[s], out[s].end());
- *j = *in++;
- }
- }
- };
-
-
-
-}
-}
diff --git a/extern/carve/include/carve/edge_decl.hpp b/extern/carve/include/carve/edge_decl.hpp
deleted file mode 100644
index 1fde265cf75..00000000000
--- a/extern/carve/include/carve/edge_decl.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/vector.hpp>
-#include <carve/tag.hpp>
-
-#include <vector>
-#include <list>
-
-namespace carve {
- namespace poly {
-
-
-
- struct Object;
-
-
-
- template<unsigned ndim>
- class Edge : public tagable {
- public:
- typedef Vertex<ndim> vertex_t;
- typedef typename Vertex<ndim>::vector_t vector_t;
- typedef Object obj_t;
-
- const vertex_t *v1, *v2;
- const obj_t *owner;
-
- Edge(const vertex_t *_v1, const vertex_t *_v2, const obj_t *_owner) :
- tagable(), v1(_v1), v2(_v2), owner(_owner) {
- }
-
- ~Edge() {
- }
- };
-
-
-
- struct hash_edge_ptr {
- template<unsigned ndim>
- size_t operator()(const Edge<ndim> * const &e) const {
- return (size_t)e;
- }
- };
-
-
-
- }
-}
-
diff --git a/extern/carve/include/carve/edge_impl.hpp b/extern/carve/include/carve/edge_impl.hpp
deleted file mode 100644
index ff00615c768..00000000000
--- a/extern/carve/include/carve/edge_impl.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-namespace carve {
- namespace poly {
- }
-}
diff --git a/extern/carve/include/carve/exact.hpp b/extern/carve/include/carve/exact.hpp
deleted file mode 100644
index a74fb77d2ec..00000000000
--- a/extern/carve/include/carve/exact.hpp
+++ /dev/null
@@ -1,704 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <vector>
-#include <numeric>
-#include <algorithm>
-
-
-namespace carve {
- namespace exact {
-
- class exact_t : public std::vector<double> {
- typedef std::vector<double> super;
-
- public:
- exact_t() : super() {
- }
-
- exact_t(double v, size_t sz = 1) : super(sz, v) {
- }
-
- template<typename iter_t>
- exact_t(iter_t a, iter_t b) : super(a, b) {
- }
-
- exact_t(double a, double b) : super() {
- reserve(2);
- push_back(a);
- push_back(b);
- }
-
- exact_t(double a, double b, double c) : super() {
- reserve(3);
- push_back(a);
- push_back(b);
- push_back(c);
- }
-
- exact_t(double a, double b, double c, double d) : super() {
- reserve(4);
- push_back(a);
- push_back(b);
- push_back(c);
- push_back(d);
- }
-
- exact_t(double a, double b, double c, double d, double e) : super() {
- reserve(5);
- push_back(a);
- push_back(b);
- push_back(c);
- push_back(d);
- push_back(e);
- }
-
- exact_t(double a, double b, double c, double d, double e, double f) : super() {
- reserve(6);
- push_back(a);
- push_back(b);
- push_back(c);
- push_back(d);
- push_back(e);
- push_back(f);
- }
-
- exact_t(double a, double b, double c, double d, double e, double f, double g) : super() {
- reserve(7);
- push_back(a);
- push_back(b);
- push_back(c);
- push_back(d);
- push_back(e);
- push_back(f);
- push_back(g);
- }
-
- exact_t(double a, double b, double c, double d, double e, double f, double g, double h) : super() {
- reserve(8);
- push_back(a);
- push_back(b);
- push_back(c);
- push_back(d);
- push_back(e);
- push_back(f);
- push_back(g);
- push_back(h);
- }
-
- void compress();
-
- exact_t compressed() const {
- exact_t result(*this);
- result.compress();
- return result;
- }
-
- operator double() const {
- return std::accumulate(begin(), end(), 0.0);
- }
-
- void removeZeroes() {
- erase(std::remove(begin(), end(), 0.0), end());
- }
- };
-
- inline std::ostream &operator<<(std::ostream &out, const exact_t &p) {
- out << '{';
- out << p[0];
- for (size_t i = 1; i < p.size(); ++i) out << ';' << p[i];
- out << '}';
- return out;
- }
-
-
-
- namespace detail {
- const struct constants_t {
- double splitter; /* = 2^ceiling(p / 2) + 1. Used to split floats in half. */
- double epsilon; /* = 2^(-p). Used to estimate roundoff errors. */
- /* A set of coefficients used to calculate maximum roundoff errors. */
- double resulterrbound;
- double ccwerrboundA, ccwerrboundB, ccwerrboundC;
- double o3derrboundA, o3derrboundB, o3derrboundC;
- double iccerrboundA, iccerrboundB, iccerrboundC;
- double isperrboundA, isperrboundB, isperrboundC;
-
- constants_t() {
- double half;
- double check, lastcheck;
- int every_other;
-
- every_other = 1;
- half = 0.5;
- epsilon = 1.0;
- splitter = 1.0;
- check = 1.0;
- /* Repeatedly divide `epsilon' by two until it is too small to add to */
- /* one without causing roundoff. (Also check if the sum is equal to */
- /* the previous sum, for machines that round up instead of using exact */
- /* rounding. Not that this library will work on such machines anyway. */
- do {
- lastcheck = check;
- epsilon *= half;
- if (every_other) {
- splitter *= 2.0;
- }
- every_other = !every_other;
- check = 1.0 + epsilon;
- } while ((check != 1.0) && (check != lastcheck));
- splitter += 1.0;
-
- /* Error bounds for orientation and incircle tests. */
- resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
- ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
- ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
- ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
- o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
- o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
- o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
- iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
- iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
- iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
- isperrboundA = (16.0 + 224.0 * epsilon) * epsilon;
- isperrboundB = (5.0 + 72.0 * epsilon) * epsilon;
- isperrboundC = (71.0 + 1408.0 * epsilon) * epsilon * epsilon;
- }
- } constants;
-
- template<unsigned U, unsigned V>
- struct op {
- enum {
- Vlo = V / 2,
- Vhi = V - Vlo
- };
-
- static inline void add(const double *a, const double *b, double *r) {
- double t[U + Vlo];
- op<U, Vlo>::add(a, b, t);
- for (size_t i = 0; i < Vlo; ++i) r[i] = t[i];
- op<U, Vhi>::add(t + Vlo, b + Vlo, r + Vlo);
- }
-
- static inline void sub(const double *a, const double *b, double *r) {
- double t[U + Vlo];
- op<U, Vlo>::sub(a, b, t);
- for (size_t i = 0; i < Vlo; ++i) r[i] = t[i];
- op<U, Vhi>::sub(t + Vlo, b + Vlo, r + Vlo);
- }
- };
-
- template<unsigned U>
- struct op<U, 1> {
- enum {
- Ulo = U / 2,
- Uhi = U - Ulo
- };
- static void add(const double *a, const double *b, double *r) {
- double t[Ulo + 1];
- op<Ulo, 1>::add(a, b, t);
- for (size_t i = 0; i < Ulo; ++i) r[i] = t[i];
- op<Uhi, 1>::add(a + Ulo, t + Ulo, r + Ulo);
- }
-
- static void sub(const double *a, const double *b, double *r) {
- double t[Ulo + 1];
- op<Ulo, 1>::sub(a, b, t);
- for (size_t i = 0; i < Ulo; ++i) r[i] = t[i];
- op<Uhi, 1>::add(a + Ulo, t + Ulo, r + Ulo);
- }
- };
-
- template<>
- struct op<1, 1> {
- static void add_fast(const double *a, const double *b, double *r) {
- assert(fabs(a[0]) >= fabs(b[0]));
- volatile double sum = a[0] + b[0];
- volatile double bvirt = sum - a[0];
- r[0] = b[0] - bvirt;
- r[1] = sum;
- }
-
- static void sub_fast(const double *a, const double *b, double *r) {
- assert(fabs(a[0]) >= fabs(b[0]));
- volatile double diff = a[0] - b[0];
- volatile double bvirt = a[0] - diff;
- r[0] = bvirt - b[0];
- r[1] = diff;
- }
-
- static void add(const double *a, const double *b, double *r) {
- volatile double sum = a[0] + b[0];
- volatile double bvirt = sum - a[0];
- double avirt = sum - bvirt;
- double bround = b[0] - bvirt;
- double around = a[0] - avirt;
- r[0] = around + bround;
- r[1] = sum;
- }
-
- static void sub(const double *a, const double *b, double *r) {
- volatile double diff = a[0] - b[0];
- volatile double bvirt = a[0] - diff;
- double avirt = diff + bvirt;
- double bround = bvirt - b[0];
- double around = a[0] - avirt;
- r[0] = around + bround;
- r[1] = diff;
- }
- };
-
-
- template<unsigned U, unsigned V>
- static exact_t add(const double *a, const double *b) {
- exact_t result;
- result.resize(U + V);
- op<U,V>::add(a, b, &result[0]);
- return result;
- }
-
-
- template<unsigned U, unsigned V>
- static exact_t sub(const double *a, const double *b) {
- exact_t result;
- result.resize(U + V);
- op<U,V>::sub(a, b, &result[0]);
- return result;
- }
-
-
- template<unsigned U, unsigned V>
- static exact_t add(const exact_t &a, const exact_t &b) {
- assert(a.size() == U);
- assert(b.size() == V);
- exact_t result;
- result.resize(U + V);
- std::fill(result.begin(), result.end(), std::numeric_limits<double>::quiet_NaN());
- op<U,V>::add(&a[0], &b[0], &result[0]);
- return result;
- }
-
-
- template<unsigned U, unsigned V>
- static exact_t add(const exact_t &a, const double *b) {
- assert(a.size() == U);
- exact_t result;
- result.resize(U + V);
- std::fill(result.begin(), result.end(), std::numeric_limits<double>::quiet_NaN());
- op<U,V>::add(&a[0], b, &result[0]);
- return result;
- }
-
-
- template<unsigned U, unsigned V>
- static exact_t sub(const exact_t &a, const exact_t &b) {
- assert(a.size() == U);
- assert(b.size() == V);
- exact_t result;
- result.resize(U + V);
- std::fill(result.begin(), result.end(), std::numeric_limits<double>::quiet_NaN());
- op<U,V>::sub(&a[0], &b[0], &result[0]);
- return result;
- }
-
-
- template<unsigned U, unsigned V>
- static exact_t sub(const exact_t &a, const double *b) {
- assert(a.size() == U);
- exact_t result;
- result.resize(U + V);
- std::fill(result.begin(), result.end(), std::numeric_limits<double>::quiet_NaN());
- op<U,V>::sub(&a[0], &b[0], &result[0]);
- return result;
- }
-
-
- static inline void split(const double a, double *r) {
- volatile double c = constants.splitter * a;
- volatile double abig = c - a;
- r[1] = c - abig;
- r[0] = a - r[1];
- }
-
- static inline void prod_1_1(const double *a, const double *b, double *r) {
- r[1] = a[0] * b[0];
- double a_sp[2]; split(a[0], a_sp);
- double b_sp[2]; split(b[0], b_sp);
- double err1 = r[1] - a_sp[1] * b_sp[1];
- double err2 = err1 - a_sp[0] * b_sp[1];
- double err3 = err2 - a_sp[1] * b_sp[0];
- r[0] = a_sp[0] * b_sp[0] - err3;
- }
-
- static inline void prod_1_1s(const double *a, const double *b, const double *b_sp, double *r) {
- r[1] = a[0] * b[0];
- double a_sp[2]; split(a[0], a_sp);
- double err1 = r[1] - a_sp[1] * b_sp[1];
- double err2 = err1 - a_sp[0] * b_sp[1];
- double err3 = err2 - a_sp[1] * b_sp[0];
- r[0] = a_sp[0] * b_sp[0] - err3;
- }
-
- static inline void prod_1s_1s(const double *a, const double *a_sp, const double *b, const double *b_sp, double *r) {
- r[1] = a[0] * b[0];
- double err1 = r[1] - a_sp[1] * b_sp[1];
- double err2 = err1 - a_sp[0] * b_sp[1];
- double err3 = err2 - a_sp[1] * b_sp[0];
- r[0] = a_sp[0] * b_sp[0] - err3;
- }
-
- static inline void prod_2_1(const double *a, const double *b, double *r) {
- double b_sp[2]; split(b[0], b_sp);
- double t1[2]; prod_1_1s(a+0, b, b_sp, t1);
- r[0] = t1[0];
- double t2[2]; prod_1_1s(a+1, b, b_sp, t2);
- double t3[2]; op<1,1>::add(t1+1, t2, t3);
- r[1] = t3[0];
- double t4[2]; op<1,1>::add_fast(t2+1, t3+1, r + 2);
- }
-
- static inline void prod_1_2(const double *a, const double *b, double *r) {
- prod_2_1(b, a, r);
- }
-
- static inline void prod_4_1(const double *a, const double *b, double *r) {
- double b_sp[2]; split(b[0], b_sp);
- double t1[2]; prod_1_1s(a+0, b, b_sp, t1);
- r[0] = t1[0];
- double t2[2]; prod_1_1s(a+1, b, b_sp, t2);
- double t3[2]; op<1,1>::add(t1+1, t2, t3);
- r[1] = t3[0];
- double t4[2]; op<1,1>::add_fast(t2+1, t3+1, t4);
- r[2] = t4[0];
- double t5[2]; prod_1_1s(a+2, b, b_sp, t5);
- double t6[2]; op<1,1>::add(t4+1, t5, t6);
- r[3] = t6[0];
- double t7[2]; op<1,1>::add_fast(t5+1, t6+1, t7);
- r[4] = t7[0];
- double t8[2]; prod_1_1s(a+3, b, b_sp, t8);
- double t9[2]; op<1,1>::add(t7+1, t8, t9);
- r[5] = t9[0];
- op<1,1>::add_fast(t8+1, t9+1, r + 6);
- }
-
- static inline void prod_1_4(const double *a, const double *b, double *r) {
- prod_4_1(b, a, r);
- }
-
- static inline void prod_2_2(const double *a, const double *b, double *r) {
- double a1_sp[2]; split(a[1], a1_sp);
- double a0_sp[2]; split(a[0], a0_sp);
- double b1_sp[2]; split(b[1], b1_sp);
- double b0_sp[2]; split(b[0], b0_sp);
-
- double t1[2]; prod_1s_1s(a+0, a0_sp, b+0, b0_sp, t1);
- r[0] = t1[0];
- double t2[2]; prod_1s_1s(a+1, a1_sp, b+0, b0_sp, t2);
-
- double t3[2]; op<1,1>::add(t1+1, t2, t3);
- double t4[2]; op<1,1>::add_fast(t2+1, t3+1, t4);
-
- double t5[2]; prod_1s_1s(a+0, a0_sp, b+1, b1_sp, t5);
-
- double t6[2]; op<1,1>::add(t3, t5, t6);
- r[1] = t6[0];
- double t7[2]; op<1,1>::add(t4, t6+1, t7);
- double t8[2]; op<1,1>::add(t4+1, t7+1, t8);
-
- double t9[2]; prod_1s_1s(a+1, a1_sp, b+1, b1_sp, t9);
-
- double t10[2]; op<1,1>::add(t5+1, t9, t10);
- double t11[2]; op<1,1>::add(t7, t10, t11);
- r[2] = t11[0];
- double t12[2]; op<1,1>::add(t8, t11+1, t12);
- double t13[2]; op<1,1>::add(t8+1, t12+1, t13);
- double t14[2]; op<1,1>::add(t9+1, t10+1, t14);
- double t15[2]; op<1,1>::add(t12, t14, t15);
- r[3] = t15[0];
- double t16[2]; op<1,1>::add(t13, t15+1, t16);
- double t17[2]; op<1,1>::add(t13+1, t16+1, t17);
- double t18[2]; op<1,1>::add(t16, t14+1, t18);
- r[4] = t18[0];
- double t19[2]; op<1,1>::add(t17, t18+1, t19);
- r[5] = t19[0];
- double t20[2]; op<1,1>::add(t17+1, t19+1, t20);
- r[6] = t20[0];
- r[7] = t20[1];
- }
-
-
-
- static inline void square(const double a, double *r) {
- r[1] = a * a;
- double a_sp[2]; split(a, a_sp);
- double err1 = r[1] - (a_sp[1] * a_sp[1]);
- double err3 = err1 - ((a_sp[1] + a_sp[1]) * a_sp[0]);
- r[0] = a_sp[0] * a_sp[0] - err3;
- }
-
- static inline void square_2(const double *a, double *r) {
- double t1[2]; square(a[0], t1);
- r[0] = t1[0];
- double t2 = a[0] + a[0];
- double t3[2]; prod_1_1(a+1, &t2, t3);
- double t4[3]; op<2,1>::add(t3, t1 + 1, t4);
- r[1] = t4[0];
- double t5[2]; square(a[1], t5);
- double t6[4]; op<2,2>::add(t5, t4 + 1, r + 2);
- }
- }
-
-
-
- void exact_t::compress() {
- double sum[2];
-
- int j = size() - 1;
- double Q = (*this)[j];
- for (int i = (int)size()-2; i >= 0; --i) {
- detail::op<1,1>::add_fast(&Q, &(*this)[i], sum);
- if (sum[0] != 0) {
- (*this)[j--] = sum[1];
- Q = sum[0];
- } else {
- Q = sum[1];
- }
- }
- int j2 = 0;
- for (int i = j + 1; i < (int)size(); ++i) {
- detail::op<1,1>::add_fast(&(*this)[i], &Q, sum);
- if (sum[0] != 0) {
- (*this)[j2++] = sum[0];
- }
- Q = sum[1];
- }
- (*this)[j2++] = Q;
-
- erase(begin() + j2, end());
- }
-
- template<typename iter_t>
- void negate(iter_t begin, iter_t end) {
- while (begin != end) { *begin = -*begin; ++begin; }
- }
-
- void negate(exact_t &e) {
- negate(&e[0], &e[e.size()]);
- }
-
- template<typename iter_t>
- void scale_zeroelim(iter_t ebegin,
- iter_t eend,
- double b,
- exact_t &h) {
- double Q;
-
- h.clear();
- double b_sp[2]; detail::split(b, b_sp);
-
- double prod[2], sum[2];
-
- detail::prod_1_1s((double *)ebegin++, &b, b_sp, prod);
- Q = prod[1];
- if (prod[0] != 0.0) {
- h.push_back(prod[0]);
- }
- while (ebegin != eend) {
- double enow = *ebegin++;
- detail::prod_1_1s(&enow, &b, b_sp, prod);
- detail::op<1,1>::add(&Q, prod, sum);
- if (sum[0] != 0) {
- h.push_back(sum[0]);
- }
- detail::op<1,1>::add_fast(prod+1, sum+1, sum);
- Q = sum[1];
- if (sum[0] != 0) {
- h.push_back(sum[0]);
- }
- }
- if ((Q != 0.0) || (h.size() == 0)) {
- h.push_back(Q);
- }
- }
-
- void scale_zeroelim(const exact_t &e,
- double b,
- exact_t &h) {
- scale_zeroelim(&e[0], &e[e.size()], b, h);
- }
-
- template<typename iter_t>
- void sum_zeroelim(iter_t ebegin,
- iter_t eend,
- iter_t fbegin,
- iter_t fend,
- exact_t &h) {
- double Q;
- double enow, fnow;
-
- double sum[2];
-
- enow = *ebegin;
- fnow = *fbegin;
-
- h.clear();
-
- if ((fnow > enow) == (fnow > -enow)) {
- Q = enow;
- enow = *++ebegin;
- } else {
- Q = fnow;
- fnow = *++fbegin;
- }
-
- if (ebegin != eend && fbegin != fend) {
- if ((fnow > enow) == (fnow > -enow)) {
- detail::op<1,1>::add_fast(&enow, &Q, sum);
- enow = *++ebegin;
- } else {
- detail::op<1,1>::add_fast(&fnow, &Q, sum);
- fnow = *++fbegin;
- }
- Q = sum[1];
- if (sum[0] != 0.0) {
- h.push_back(sum[0]);
- }
- while (ebegin != eend && fbegin != fend) {
- if ((fnow > enow) == (fnow > -enow)) {
- detail::op<1,1>::add(&Q, &enow, sum);
- enow = *++ebegin;
- } else {
- detail::op<1,1>::add(&Q, &fnow, sum);
- fnow = *++fbegin;
- }
- Q = sum[1];
- if (sum[0] != 0.0) {
- h.push_back(sum[0]);
- }
- }
- }
-
- while (ebegin != eend) {
- detail::op<1,1>::add(&Q, &enow, sum);
- enow = *++ebegin;
- Q = sum[1];
- if (sum[0] != 0.0) {
- h.push_back(sum[0]);
- }
- }
- while (fbegin != fend) {
- detail::op<1,1>::add(&Q, &fnow, sum);
- fnow = *++fbegin;
- Q = sum[1];
- if (sum[0] != 0.0) {
- h.push_back(sum[0]);
- }
- }
-
- if (Q != 0.0 || !h.size()) {
- h.push_back(Q);
- }
- }
-
- void sum_zeroelim(const exact_t &e,
- const exact_t &f,
- exact_t &h) {
- sum_zeroelim(&e[0], &e[e.size()], &f[0], &f[f.size()], h);
- }
-
- void sum_zeroelim(const double *ebegin,
- const double *eend,
- const exact_t &f,
- exact_t &h) {
- sum_zeroelim(ebegin, eend, &f[0], &f[f.size()], h);
- }
-
- void sum_zeroelim(const exact_t &e,
- const double *fbegin,
- const double *fend,
- exact_t &h) {
- sum_zeroelim(&e[0], &e[e.size()], fbegin, fend, h);
- }
-
-
- exact_t operator+(const exact_t &a, const exact_t &b) {
- exact_t r;
- sum_zeroelim(a, b, r);
- return r;
- }
-
-
-
- void diffprod(const double a, const double b, const double c, const double d, double *r) {
- // return ab - cd;
- double ab[2], cd[2];
- detail::prod_1_1(&a, &b, ab);
- detail::prod_1_1(&c, &d, cd);
- detail::op<2,2>::sub(ab, cd, r);
- }
-
- double orient3dexact(const double *pa,
- const double *pb,
- const double *pc,
- const double *pd) {
- using namespace detail;
-
- double ab[4]; diffprod(pa[0], pb[1], pb[0], pa[1], ab);
- double bc[4]; diffprod(pb[0], pc[1], pc[0], pb[1], bc);
- double cd[4]; diffprod(pc[0], pd[1], pd[0], pc[1], cd);
- double da[4]; diffprod(pd[0], pa[1], pa[0], pd[1], da);
- double ac[4]; diffprod(pa[0], pc[1], pc[0], pa[1], ac);
- double bd[4]; diffprod(pb[0], pd[1], pd[0], pb[1], bd);
-
- exact_t temp;
- exact_t cda, dab, abc, bcd;
- exact_t adet, bdet, cdet, ddet, abdet, cddet, det;
-
- sum_zeroelim(cd, cd + 4, da, da + 4, temp);
- sum_zeroelim(temp, ac, ac + 4, cda);
-
- sum_zeroelim(da, da + 4, ab, ab + 4, temp);
- sum_zeroelim(temp, bd, bd + 4, dab);
-
- negate(bd, bd + 4);
- negate(ac, bd + 4);
-
- sum_zeroelim(ab, ab + 4, bc, bc + 4, temp);
- sum_zeroelim(temp, ac, ac + 4, abc);
-
- sum_zeroelim(bc, bc + 4, cd, cd + 4, temp);
- sum_zeroelim(temp, bd, bd + 4, bcd);
-
- scale_zeroelim(bcd, +pa[2], adet);
- scale_zeroelim(cda, -pb[2], bdet);
- scale_zeroelim(dab, +pc[2], cdet);
- scale_zeroelim(abc, -pd[2], ddet);
-
- sum_zeroelim(adet, bdet, abdet);
- sum_zeroelim(cdet, ddet, cddet);
-
- sum_zeroelim(abdet, cddet, det);
-
- return det[det.size() - 1];
- }
-
- }
-}
diff --git a/extern/carve/include/carve/face_decl.hpp b/extern/carve/include/carve/face_decl.hpp
deleted file mode 100644
index f37464be914..00000000000
--- a/extern/carve/include/carve/face_decl.hpp
+++ /dev/null
@@ -1,208 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/geom2d.hpp>
-#include <carve/vector.hpp>
-#include <carve/matrix.hpp>
-#include <carve/geom3d.hpp>
-#include <carve/aabb.hpp>
-#include <carve/tag.hpp>
-
-#include <vector>
-#include <list>
-#include <map>
-
-namespace carve {
- namespace poly {
-
-
-
- struct Object;
-
- template<unsigned ndim>
- class Edge;
-
-
-
- template<unsigned ndim>
- struct p2_adapt_project {
- typedef carve::geom2d::P2 (*proj_t)(const carve::geom::vector<ndim> &);
- proj_t proj;
- p2_adapt_project(proj_t _proj) : proj(_proj) { }
- carve::geom2d::P2 operator()(const carve::geom::vector<ndim> &v) const { return proj(v); }
- carve::geom2d::P2 operator()(const carve::geom::vector<ndim> *v) const { return proj(*v); }
- carve::geom2d::P2 operator()(const Vertex<ndim> &v) const { return proj(v.v); }
- carve::geom2d::P2 operator()(const Vertex<ndim> *v) const { return proj(v->v); }
- };
-
-
- template<unsigned ndim>
- class Face : public tagable {
- public:
- typedef Vertex<ndim> vertex_t;
- typedef typename Vertex<ndim>::vector_t vector_t;
- typedef Edge<ndim> edge_t;
- typedef Object obj_t;
- typedef carve::geom::aabb<ndim> aabb_t;
- typedef carve::geom::plane<ndim> plane_t;
-
- typedef carve::geom2d::P2 (*project_t)(const vector_t &);
- typedef vector_t (*unproject_t)(const carve::geom2d::P2 &, const plane_t &);
-
- protected:
- std::vector<const vertex_t *> vertices; // pointer into polyhedron.vertices
- std::vector<const edge_t *> edges; // pointer into polyhedron.edges
-
- project_t getProjector(bool positive_facing, int axis);
- unproject_t getUnprojector(bool positive_facing, int axis);
-
- public:
- typedef typename std::vector<const vertex_t *>::iterator vertex_iter_t;
- typedef typename std::vector<const vertex_t *>::const_iterator const_vertex_iter_t;
-
- typedef typename std::vector<const edge_t *>::iterator edge_iter_t;
- typedef typename std::vector<const edge_t *>::const_iterator const_edge_iter_t;
-
- obj_t *owner;
-
- aabb_t aabb;
- plane_t plane_eqn;
- int manifold_id;
- int group_id;
-
- project_t project;
- unproject_t unproject;
-
- Face(const std::vector<const vertex_t *> &_vertices, bool delay_recalc = false);
- Face(const vertex_t *v1, const vertex_t *v2, const vertex_t *v3, bool delay_recalc = false);
- Face(const vertex_t *v1, const vertex_t *v2, const vertex_t *v3, const vertex_t *v4, bool delay_recalc = false);
-
- template <typename iter_t>
- Face(const Face *base, iter_t vbegin, iter_t vend, bool flipped) {
- init(base, vbegin, vend, flipped);
- }
-
- Face(const Face *base, const std::vector<const vertex_t *> &_vertices, bool flipped) {
- init(base, _vertices, flipped);
- }
-
- Face() {}
- ~Face() {}
-
- bool recalc();
-
- template<typename iter_t>
- Face *init(const Face *base, iter_t vbegin, iter_t vend, bool flipped);
- Face *init(const Face *base, const std::vector<const vertex_t *> &_vertices, bool flipped);
-
- template<typename iter_t>
- Face *create(iter_t vbegin, iter_t vend, bool flipped) const;
- Face *create(const std::vector<const vertex_t *> &_vertices, bool flipped) const;
-
- Face *clone(bool flipped = false) const;
- void invert();
-
- void getVertexLoop(std::vector<const vertex_t *> &loop) const;
-
- const vertex_t *&vertex(size_t idx);
- const vertex_t *vertex(size_t idx) const;
- size_t nVertices() const;
-
- vertex_iter_t vbegin() { return vertices.begin(); }
- vertex_iter_t vend() { return vertices.end(); }
- const_vertex_iter_t vbegin() const { return vertices.begin(); }
- const_vertex_iter_t vend() const { return vertices.end(); }
-
- std::vector<carve::geom::vector<2> > projectedVertices() const;
-
- const edge_t *&edge(size_t idx);
- const edge_t *edge(size_t idx) const;
- size_t nEdges() const;
-
- edge_iter_t ebegin() { return edges.begin(); }
- edge_iter_t eend() { return edges.end(); }
- const_edge_iter_t ebegin() const { return edges.begin(); }
- const_edge_iter_t eend() const { return edges.end(); }
-
- bool containsPoint(const vector_t &p) const;
- bool containsPointInProjection(const vector_t &p) const;
- bool simpleLineSegmentIntersection(const carve::geom::linesegment<ndim> &line,
- vector_t &intersection) const;
- IntersectionClass lineSegmentIntersection(const carve::geom::linesegment<ndim> &line,
- vector_t &intersection) const;
- vector_t centroid() const;
-
- p2_adapt_project<ndim> projector() const {
- return p2_adapt_project<ndim>(project);
- }
-
- void swap(Face<ndim> &other);
- };
-
-
-
- struct hash_face_ptr {
- template<unsigned ndim>
- size_t operator()(const Face<ndim> * const &f) const {
- return (size_t)f;
- }
- };
-
-
-
- namespace face {
-
-
-
- template<unsigned ndim>
- static inline carve::geom2d::P2 project(const Face<ndim> *f, const typename Face<ndim>::vector_t &v) {
- return f->project(v);
- }
-
-
-
- template<unsigned ndim>
- static inline carve::geom2d::P2 project(const Face<ndim> &f, const typename Face<ndim>::vector_t &v) {
- return f.project(v);
- }
-
-
-
- template<unsigned ndim>
- static inline typename Face<ndim>::vector_t unproject(const Face<ndim> *f, const carve::geom2d::P2 &p) {
- return f->unproject(p, f->plane_eqn);
- }
-
-
-
- template<unsigned ndim>
- static inline typename Face<ndim>::vector_t unproject(const Face<ndim> &f, const carve::geom2d::P2 &p) {
- return f.unproject(p, f.plane_eqn);
- }
-
-
-
- }
-
-
-
- }
-}
diff --git a/extern/carve/include/carve/face_impl.hpp b/extern/carve/include/carve/face_impl.hpp
deleted file mode 100644
index d4fe70ffdd8..00000000000
--- a/extern/carve/include/carve/face_impl.hpp
+++ /dev/null
@@ -1,142 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-namespace std {
- template<unsigned ndim>
- inline void swap(carve::poly::Face<ndim> &a, carve::poly::Face<ndim> &b) {
- a.swap(b);
- }
-}
-
-namespace carve {
- namespace poly {
- template<unsigned ndim>
- void Face<ndim>::swap(Face<ndim> &other) {
- std::swap(vertices, other.vertices);
- std::swap(edges, other.edges);
- std::swap(owner, other.owner);
- std::swap(aabb, other.aabb);
- std::swap(plane_eqn, other.plane_eqn);
- std::swap(manifold_id, other.manifold_id);
- std::swap(group_id, other.group_id);
- std::swap(project, other.project);
- std::swap(unproject, other.unproject);
- }
-
- template<unsigned ndim>
- template<typename iter_t>
- Face<ndim> *Face<ndim>::init(const Face<ndim> *base, iter_t vbegin, iter_t vend, bool flipped) {
- CARVE_ASSERT(vbegin < vend);
-
- vertices.reserve((size_t)std::distance(vbegin, vend));
-
- if (flipped) {
- std::reverse_copy(vbegin, vend, std::back_inserter(vertices));
- plane_eqn = -base->plane_eqn;
- } else {
- std::copy(vbegin, vend, std::back_inserter(vertices));
- plane_eqn = base->plane_eqn;
- }
-
- edges.clear();
- edges.resize(nVertices(), NULL);
-
- aabb.fit(vertices.begin(), vertices.end(), vec_adapt_vertex_ptr());
- untag();
-
- int da = carve::geom::largestAxis(plane_eqn.N);
-
- project = getProjector(plane_eqn.N.v[da] > 0, da);
- unproject = getUnprojector(plane_eqn.N.v[da] > 0, da);
-
- return this;
- }
-
- template<unsigned ndim>
- template<typename iter_t>
- Face<ndim> *Face<ndim>::create(iter_t vbegin, iter_t vend, bool flipped) const {
- return (new Face)->init(this, vbegin, vend, flipped);
- }
-
- template<unsigned ndim>
- Face<ndim> *Face<ndim>::create(const std::vector<const vertex_t *> &_vertices, bool flipped) const {
- return (new Face)->init(this, _vertices.begin(), _vertices.end(), flipped);
- }
-
- template<unsigned ndim>
- Face<ndim> *Face<ndim>::clone(bool flipped) const {
- return (new Face)->init(this, vertices, flipped);
- }
-
- template<unsigned ndim>
- void Face<ndim>::getVertexLoop(std::vector<const vertex_t *> &loop) const {
- loop.resize(nVertices(), NULL);
- std::copy(vbegin(), vend(), loop.begin());
- }
-
- template<unsigned ndim>
- const typename Face<ndim>::edge_t *&Face<ndim>::edge(size_t idx) {
- return edges[idx];
- }
-
- template<unsigned ndim>
- const typename Face<ndim>::edge_t *Face<ndim>::edge(size_t idx) const {
- return edges[idx];
- }
-
- template<unsigned ndim>
- size_t Face<ndim>::nEdges() const {
- return edges.size();
- }
-
- template<unsigned ndim>
- const typename Face<ndim>::vertex_t *&Face<ndim>::vertex(size_t idx) {
- return vertices[idx];
- }
-
- template<unsigned ndim>
- const typename Face<ndim>::vertex_t *Face<ndim>::vertex(size_t idx) const {
- return vertices[idx];
- }
-
- template<unsigned ndim>
- size_t Face<ndim>::nVertices() const {
- return vertices.size();
- }
-
- template<unsigned ndim>
- typename Face<ndim>::vector_t Face<ndim>::centroid() const {
- vector_t c;
- carve::geom::centroid(vertices.begin(), vertices.end(), vec_adapt_vertex_ptr(), c);
- return c;
- }
-
- template<unsigned ndim>
- std::vector<carve::geom::vector<2> > Face<ndim>::projectedVertices() const {
- p2_adapt_project<ndim> proj = projector();
- std::vector<carve::geom::vector<2> > result;
- result.reserve(nVertices());
- for (size_t i = 0; i < nVertices(); ++i) {
- result.push_back(proj(vertex(i)->v));
- }
- return result;
- }
-
- }
-}
diff --git a/extern/carve/include/carve/faceloop.hpp b/extern/carve/include/carve/faceloop.hpp
deleted file mode 100644
index d9bf234af66..00000000000
--- a/extern/carve/include/carve/faceloop.hpp
+++ /dev/null
@@ -1,103 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-#include <carve/classification.hpp>
-#include <carve/collection_types.hpp>
-
-namespace carve {
- namespace csg {
-
- struct FaceLoopGroup;
-
- struct FaceLoop {
- FaceLoop *next, *prev;
- const carve::mesh::MeshSet<3>::face_t *orig_face;
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> vertices;
- FaceLoopGroup *group;
-
- FaceLoop(const carve::mesh::MeshSet<3>::face_t *f, const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &v) : next(NULL), prev(NULL), orig_face(f), vertices(v), group(NULL) {}
- };
-
-
- struct FaceLoopList {
- FaceLoop *head, *tail;
- unsigned count;
-
- FaceLoopList() : head(NULL), tail(NULL), count(0) { }
-
- void append(FaceLoop *f) {
- f->prev = tail;
- f->next = NULL;
- if (tail) tail->next = f;
- tail = f;
- if (!head) head = f;
- count++;
- }
-
- void prepend(FaceLoop *f) {
- f->next = head;
- f->prev = NULL;
- if (head) head->prev = f;
- head = f;
- if (!tail) tail = f;
- count++;
- }
-
- unsigned size() const {
- return count;
- }
-
- FaceLoop *remove(FaceLoop *f) {
- FaceLoop *r = f->next;
- if (f->prev) { f->prev->next = f->next; } else { head = f->next; }
- if (f->next) { f->next->prev = f->prev; } else { tail = f->prev; }
- f->next = f->prev = NULL;
- count--;
- return r;
- }
-
- ~FaceLoopList() {
- FaceLoop *a = head, *b;
- while (a) {
- b = a;
- a = a->next;
- delete b;
- }
- }
- };
-
- struct FaceLoopGroup {
- const carve::mesh::MeshSet<3> *src;
- FaceLoopList face_loops;
- V2Set perimeter;
- std::list<ClassificationInfo> classification;
-
- FaceLoopGroup(const carve::mesh::MeshSet<3> *_src) : src(_src) {
- }
-
- FaceClass classificationAgainst(const carve::mesh::MeshSet<3>::mesh_t *mesh) const;
- };
-
-
-
- typedef std::list<FaceLoopGroup> FLGroupList;
-
- }
-}
diff --git a/extern/carve/include/carve/geom.hpp b/extern/carve/include/carve/geom.hpp
deleted file mode 100644
index 9fd624a44f7..00000000000
--- a/extern/carve/include/carve/geom.hpp
+++ /dev/null
@@ -1,367 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <vector>
-
-namespace carve {
- namespace geom {
-
- template<unsigned ndim> struct aabb;
-
- // ========================================================================
- struct _uninitialized { };
-
- template<unsigned ndim>
- struct base {
- double v[ndim];
- };
-
- template<> struct base<2> {union { double v[2]; struct { double x, y; }; }; };
- template<> struct base<3> {union { double v[3]; struct { double x, y, z; }; }; };
- template<> struct base<4> {union { double v[4]; struct { double x, y, z, w; }; }; };
-
- template<unsigned ndim>
- struct vector : public base<ndim> {
- enum { __ndim = ndim };
-
- static vector ZERO();
- double length2() const;
- double length() const;
- vector<ndim> &normalize();
- vector<ndim> normalized() const;
- bool exactlyZero() const;
- bool isZero(double epsilon = EPSILON) const;
- void setZero();
- void fill(double val);
- vector<ndim> &scaleBy(double d);
- vector<ndim> &invscaleBy(double d);
- vector<ndim> scaled(double d) const;
- vector<ndim> invscaled(double d) const;
- vector<ndim> &negate();
- vector<ndim> negated() const;
- double &operator[](unsigned i);
- const double &operator[](unsigned i) const;
- template<typename assign_t>
- vector<ndim> &operator=(const assign_t &t);
- std::string asStr() const;
-
- aabb<ndim> getAABB() const;
-
- vector() { setZero(); }
- vector(noinit_t) { }
- };
-
- template<unsigned ndim>
- vector<ndim> vector<ndim>::ZERO() { vector<ndim> r; r.setZero(); return r; }
-
- static inline vector<2> VECTOR(double x, double y) { vector<2> r; r.x = x; r.y = y; return r; }
- static inline vector<3> VECTOR(double x, double y, double z) { vector<3> r; r.x = x; r.y = y; r.z = z; return r; }
- static inline vector<4> VECTOR(double x, double y, double z, double w) { vector<4> r; r.x = x; r.y = y; r.z = z; r.w = w; return r; }
-
- template<unsigned ndim> vector<ndim> operator+(const vector<ndim> &a, const vector<ndim> &b);
- template<unsigned ndim> vector<ndim> operator+(const vector<ndim> &a, double b);
- template<unsigned ndim, typename val_t> vector<ndim> operator+(const vector<ndim> &a, const val_t &b);
- template<unsigned ndim, typename val_t> vector<ndim> operator+(const val_t &a, const vector<ndim> &b);
-
- template<unsigned ndim> vector<ndim> &operator+=(vector<ndim> &a, const vector<ndim> &b);
- template<unsigned ndim> vector<ndim> &operator+=(vector<ndim> &a, double b);
- template<unsigned ndim, typename val_t> vector<ndim> &operator+=(vector<ndim> &a, const val_t &b);
-
- template<unsigned ndim> vector<ndim> operator-(const vector<ndim> &a);
-
- template<unsigned ndim> vector<ndim> operator-(const vector<ndim> &a, const vector<ndim> &b);
- template<unsigned ndim> vector<ndim> operator-(const vector<ndim> &a, double b);
- template<unsigned ndim, typename val_t> vector<ndim> operator-(const vector<ndim> &a, const val_t &b);
- template<unsigned ndim, typename val_t> vector<ndim> operator-(const val_t &a, const vector<ndim> &b);
-
- template<unsigned ndim> vector<ndim> &operator-=(vector<ndim> &a, const vector<ndim> &b);
- template<unsigned ndim> vector<ndim> &operator-=(vector<ndim> &a, double b);
- template<unsigned ndim, typename val_t> vector<ndim> &operator-=(vector<ndim> &a, const val_t &b);
-
- template<unsigned ndim> vector<ndim> operator*(const vector<ndim> &a, double s);
- template<unsigned ndim> vector<ndim> operator*(double s, const vector<ndim> &a);
- template<unsigned ndim> vector<ndim> &operator*=(vector<ndim> &a, double s);
-
- template<unsigned ndim> vector<ndim> operator/(const vector<ndim> &a, double s);
- template<unsigned ndim> vector<ndim> &operator/=(vector<ndim> &a, double s);
-
- template<unsigned ndim> bool operator==(const vector<ndim> &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator!=(const vector<ndim> &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator<(const vector<ndim> &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator<=(const vector<ndim> &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator>(const vector<ndim> &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator>=(const vector<ndim> &a, const vector<ndim> &b);
-
- template<unsigned ndim> vector<ndim> abs(const vector<ndim> &a);
-
- template<unsigned ndim> double distance2(const vector<ndim> &a, const vector<ndim> &b);
-
- template<unsigned ndim> double distance(const vector<ndim> &a, const vector<ndim> &b);
-
- template<unsigned ndim> bool equal(const vector<ndim> &a, const vector<ndim> &b);
-
- template<unsigned ndim> int smallestAxis(const vector<ndim> &a);
-
- template<unsigned ndim> int largestAxis(const vector<ndim> &a);
-
- template<unsigned ndim> vector<2> select(const vector<ndim> &a, int a1, int a2);
-
- template<unsigned ndim> vector<3> select(const vector<ndim> &a, int a1, int a2, int a3);
-
- template<unsigned ndim, typename assign_t, typename oper_t>
- vector<ndim> &assign_op(vector<ndim> &a, const assign_t &t, oper_t op);
-
- template<unsigned ndim, typename assign1_t, typename assign2_t, typename oper_t>
- vector<ndim> &assign_op(vector<ndim> &a, const assign1_t &t1, const assign2_t &t2, oper_t op);
-
- template<unsigned ndim, typename iter_t>
- void bounds(iter_t begin, iter_t end, vector<ndim> &min, vector<ndim> &max);
-
- template<unsigned ndim, typename iter_t, typename adapt_t>
- void bounds(iter_t begin, iter_t end, adapt_t adapt, vector<ndim> &min, vector<ndim> &max);
-
- template<unsigned ndim, typename iter_t>
- void centroid(iter_t begin, iter_t end, vector<ndim> &c);
-
- template<unsigned ndim, typename iter_t, typename adapt_t>
- void centroid(iter_t begin, iter_t end, adapt_t adapt, vector<ndim> &c);
-
- template<unsigned ndim, typename val_t> double dot(const vector<ndim> &a, const val_t &b);
-
- static inline vector<3> cross(const vector<3> &a, const vector<3> &b);
-
- static inline double cross(const vector<2> &a, const vector<2> &b);
-
- static inline double dotcross(const vector<3> &a, const vector<3> &b, const vector<3> &c);
-
-
-
- // ========================================================================
- struct axis_pos {
- int axis;
- double pos;
-
- axis_pos(int _axis, double _pos) : axis(_axis), pos(_pos) { }
- };
-
- template<unsigned ndim>
- double distance(const axis_pos &a, const vector<ndim> &b);
-
- template<unsigned ndim>
- double distance2(const axis_pos &a, const vector<ndim> &b);
-
- template<unsigned ndim> bool operator<(const axis_pos &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator<(const vector<ndim> &a, const axis_pos &b);
-
- template<unsigned ndim> bool operator<=(const axis_pos &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator<=(const vector<ndim> &a, const axis_pos &b);
-
- template<unsigned ndim> bool operator>(const axis_pos &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator>(const vector<ndim> &a, const axis_pos &b);
-
- template<unsigned ndim> bool operator>=(const axis_pos &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator>=(const vector<ndim> &a, const axis_pos &b);
-
- template<unsigned ndim> bool operator==(const axis_pos &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator==(const vector<ndim> &a, const axis_pos &b);
-
- template<unsigned ndim> bool operator!=(const axis_pos &a, const vector<ndim> &b);
- template<unsigned ndim> bool operator!=(const vector<ndim> &a, const axis_pos &b);
-
-
-
- // ========================================================================
- template<unsigned ndim>
- struct ray {
- typedef vector<ndim> vector_t;
-
- vector_t D, v;
-
- bool OK() const;
-
- ray() { }
- ray(vector_t _D, vector_t _v) : D(_D), v(_v) { }
- };
-
- template<unsigned ndim>
- ray<ndim> rayThrough(const vector<ndim> &a, const vector<ndim> &b);
-
- static inline double distance2(const ray<3> &r, const vector<3> &v);
-
- static inline double distance(const ray<3> &r, const vector<3> &v);
-
- static inline double distance2(const ray<2> &r, const vector<2> &v);
-
- static inline double distance(const ray<2> &r, const vector<2> &v);
-
-
-
- // ========================================================================
- template<unsigned ndim>
- struct linesegment {
- typedef vector<ndim> vector_t;
-
- vector_t v1;
- vector_t v2;
- vector_t midpoint;
- vector_t half_length;
-
- void update();
- bool OK() const;
- void flip();
-
- aabb<ndim> getAABB() const;
-
- linesegment(const vector_t &_v1, const vector_t &_v2);
- };
-
- template<unsigned ndim>
- double distance2(const linesegment<ndim> &l, const vector<ndim> &v);
-
- template<unsigned ndim>
- double distance(const linesegment<ndim> &l, const vector<ndim> &v);
-
-
-
- // ========================================================================
- template<unsigned ndim>
- struct plane {
- typedef vector<ndim> vector_t;
-
- vector_t N;
- double d;
-
- void negate();
-
- plane();
- plane(const vector_t &_N, vector_t _p);
- plane(const vector_t &_N, double _d);
- };
-
- template<unsigned ndim>
- inline plane<ndim> operator-(const plane<ndim> &p);
-
- template<unsigned ndim, typename val_t>
- double distance(const plane<ndim> &plane, const val_t &point);
-
- template<unsigned ndim, typename val_t>
- double distance2(const plane<ndim> &plane, const val_t &point);
-
- template<unsigned ndim>
- static inline vector<ndim> closestPoint(const plane<ndim> &p, const vector<ndim> &v);
-
-
-
- // ========================================================================
- template<unsigned ndim>
- struct sphere {
- typedef vector<ndim> vector_t;
-
- vector_t C;
- double r;
-
- aabb<ndim> getAABB() const;
-
- sphere();
- sphere(const vector_t &_C, double _r);
- };
-
- template<unsigned ndim, typename val_t>
- double distance(const sphere<ndim> &sphere, const val_t &point);
-
- template<unsigned ndim, typename val_t>
- double distance2(const sphere<ndim> &sphere, const val_t &point);
-
- template<unsigned ndim>
- static inline vector<ndim> closestPoint(const sphere<ndim> &sphere, const vector<ndim> &point);
-
-
- // ========================================================================
- template<unsigned ndim>
- struct tri {
- typedef vector<ndim> vector_t;
-
- vector_t v[3];
-
- aabb<ndim> getAABB() const;
-
- tri() { }
- tri(vector_t _v[3]);
- tri(const vector_t &a, const vector_t &b, const vector_t &c);
-
- vector_t normal() const {
- return cross(v[1] - v[0], v[2] - v[1]).normalized();
- }
- };
-
-
-
- template<unsigned ndim> std::ostream &operator<<(std::ostream &o, const vector<ndim> &v);
- template<unsigned ndim> std::ostream &operator<<(std::ostream &o, const carve::geom::plane<ndim> &p);
- template<unsigned ndim> std::ostream &operator<<(std::ostream &o, const carve::geom::sphere<ndim> &sphere);
- template<unsigned ndim> std::ostream &operator<<(std::ostream &o, const carve::geom::tri<ndim> &tri);
-
-
-
- template<unsigned ndim> vector<ndim> closestPoint(const tri<ndim> &tri, const vector<ndim> &pt);
- template<unsigned ndim> double distance(const tri<ndim> &tri, const vector<ndim> &pt);
- template<unsigned ndim> double distance2(const tri<ndim> &tri, const vector<ndim> &pt);
-
-
-
- // ========================================================================
- struct distance_functor {
- template<typename obj1_t, typename obj2_t>
- double operator()(const obj1_t &o1, const obj2_t &o2) {
- return distance(o1, o2);
- }
- };
-
-
-
- // ========================================================================
- template<int base, int power> struct __pow__ { enum { val = __pow__<base, (power >> 1)>::val * __pow__<base, power - (power >> 1)>::val }; };
- template<int base> struct __pow__<base, 1> { enum { val = base }; };
- template<int base> struct __pow__<base, 0> { enum { val = 1 }; };
-
- template<unsigned base, unsigned ndigits>
- struct quantize {
- typedef __pow__<base, ndigits> fac;
-
- double operator()(double in) {
- return round(in * fac::val) / fac::val;
- }
-
- template<unsigned ndim>
- vector<ndim> operator()(const vector<ndim> &in) {
- vector<ndim> r(NOINIT);
- assign_op(r, in, *this);
- return r;
- }
- };
-
-
-
- }
-}
-
-
-#include <carve/geom_impl.hpp>
diff --git a/extern/carve/include/carve/geom2d.hpp b/extern/carve/include/carve/geom2d.hpp
deleted file mode 100644
index eee257e2bcf..00000000000
--- a/extern/carve/include/carve/geom2d.hpp
+++ /dev/null
@@ -1,403 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/math.hpp>
-#include <carve/math_constants.hpp>
-
-#include <carve/geom.hpp>
-
-#include <vector>
-#include <algorithm>
-
-#include <math.h>
-
-#if defined(CARVE_DEBUG)
-# include <iostream>
-#endif
-
-#if defined CARVE_USE_EXACT_PREDICATES
-# include <carve/shewchuk_predicates.hpp>
-#endif
-
-namespace carve {
- namespace geom2d {
-
- typedef carve::geom::vector<2> P2;
- typedef carve::geom::ray<2> Ray2;
- typedef carve::geom::linesegment<2> LineSegment2;
-
-
-
- struct p2_adapt_ident {
- P2 &operator()(P2 &p) const { return p; }
- const P2 &operator()(const P2 &p) const { return p; }
- };
-
-
-
- typedef std::vector<P2> P2Vector;
-
- /**
- * \brief Return the orientation of c with respect to the ray defined by a->b.
- *
- * (Can be implemented exactly)
- *
- * @param[in] a
- * @param[in] b
- * @param[in] c
- *
- * @return positive, if c to the left of a->b.
- * zero, if c is colinear with a->b.
- * negative, if c to the right of a->b.
- */
-#if defined CARVE_USE_EXACT_PREDICATES
- inline double orient2d(const P2 &a, const P2 &b, const P2 &c) {
- return shewchuk::orient2d(a.v, b.v, c.v);
- }
-#else
- inline double orient2d(const P2 &a, const P2 &b, const P2 &c) {
- double acx = a.x - c.x;
- double bcx = b.x - c.x;
- double acy = a.y - c.y;
- double bcy = b.y - c.y;
- return acx * bcy - acy * bcx;
- }
-#endif
-
- /**
- * \brief Determine whether p is internal to the anticlockwise
- * angle abc, where b is the apex of the angle.
- *
- * @param[in] a
- * @param[in] b
- * @param[in] c
- * @param[in] p
- *
- * @return true, if p is contained in the anticlockwise angle from
- * b->a to b->c. Reflex angles contain p if p lies
- * on b->a or on b->c. Acute angles do not contain p
- * if p lies on b->a or on b->c. This is so that
- * internalToAngle(a,b,c,p) = !internalToAngle(c,b,a,p)
- */
- inline bool internalToAngle(const P2 &a,
- const P2 &b,
- const P2 &c,
- const P2 &p) {
- bool reflex = (a < c) ? orient2d(b, a, c) <= 0.0 : orient2d(b, c, a) > 0.0;
- double d1 = orient2d(b, a, p);
- double d2 = orient2d(b, c, p);
- if (reflex) {
- return d1 >= 0.0 || d2 <= 0.0;
- } else {
- return d1 > 0.0 && d2 < 0.0;
- }
- }
-
- /**
- * \brief Determine whether p is internal to the anticlockwise
- * angle ac, with apex at (0,0).
- *
- * @param[in] a
- * @param[in] c
- * @param[in] p
- *
- * @return true, if p is contained in a0c.
- */
- inline bool internalToAngle(const P2 &a,
- const P2 &c,
- const P2 &p) {
- return internalToAngle(a, P2::ZERO(), c, p);
- }
-
- template<typename P2vec>
- bool isAnticlockwise(const P2vec &tri) {
- return orient2d(tri[0], tri[1], tri[2]) > 0.0;
- }
-
- template<typename P2vec>
- bool pointIntersectsTriangle(const P2 &p, const P2vec &tri) {
- int orient = isAnticlockwise(tri) ? +1 : -1;
- if (orient2d(tri[0], tri[1], p) * orient < 0) return false;
- if (orient2d(tri[1], tri[2], p) * orient < 0) return false;
- if (orient2d(tri[2], tri[0], p) * orient < 0) return false;
- return true;
- }
-
- template<typename P2vec>
- bool lineIntersectsTriangle(const P2 &p1, const P2 &p2, const P2vec &tri) {
- double s[3];
- // does tri lie on one side or the other of p1-p2?
- s[0] = orient2d(p1, p2, tri[0]);
- s[1] = orient2d(p1, p2, tri[1]);
- s[2] = orient2d(p1, p2, tri[2]);
- if (*std::max_element(s, s+3) < 0) return false;
- if (*std::min_element(s, s+3) > 0) return false;
-
- // does line lie entirely to the right of a triangle edge?
- int orient = isAnticlockwise(tri) ? +1 : -1;
- if (orient2d(tri[0], tri[1], p1) * orient < 0 && orient2d(tri[0], tri[1], p2) * orient < 0) return false;
- if (orient2d(tri[1], tri[2], p1) * orient < 0 && orient2d(tri[1], tri[2], p2) * orient < 0) return false;
- if (orient2d(tri[2], tri[0], p1) * orient < 0 && orient2d(tri[2], tri[0], p2) * orient < 0) return false;
- return true;
- }
-
- template<typename P2vec>
- int triangleLineOrientation(const P2 &p1, const P2 &p2, const P2vec &tri) {
- double lo, hi, tmp;
- lo = hi = orient2d(p1, p2, tri[0]);
- tmp = orient2d(p1, p2, tri[1]); lo = std::min(lo, tmp); hi = std::max(hi, tmp);
- tmp = orient2d(p1, p2, tri[2]); lo = std::min(lo, tmp); hi = std::max(hi, tmp);
- if (hi < 0.0) return -1;
- if (lo > 0.0) return +1;
- return 0;
- }
-
- template<typename P2vec>
- bool triangleIntersectsTriangle(const P2vec &tri_b, const P2vec &tri_a) {
- int orient_a = isAnticlockwise(tri_a) ? +1 : -1;
- if (triangleLineOrientation(tri_a[0], tri_a[1], tri_b) * orient_a < 0) return false;
- if (triangleLineOrientation(tri_a[1], tri_a[2], tri_b) * orient_a < 0) return false;
- if (triangleLineOrientation(tri_a[2], tri_a[0], tri_b) * orient_a < 0) return false;
-
- int orient_b = isAnticlockwise(tri_b) ? +1 : -1;
- if (triangleLineOrientation(tri_b[0], tri_b[1], tri_a) * orient_b < 0) return false;
- if (triangleLineOrientation(tri_b[1], tri_b[2], tri_a) * orient_b < 0) return false;
- if (triangleLineOrientation(tri_b[2], tri_b[0], tri_a) * orient_b < 0) return false;
-
- return true;
- }
-
-
-
- static inline double atan2(const P2 &p) {
- return ::atan2(p.y, p.x);
- }
-
-
-
- struct LineIntersectionInfo {
- LineIntersectionClass iclass;
- P2 ipoint;
- int p1, p2;
-
- LineIntersectionInfo(LineIntersectionClass _iclass,
- P2 _ipoint = P2::ZERO(),
- int _p1 = -1,
- int _p2 = -1) :
- iclass(_iclass), ipoint(_ipoint), p1(_p1), p2(_p2) {
- }
- };
-
- struct PolyInclusionInfo {
- PointClass iclass;
- int iobjnum;
-
- PolyInclusionInfo(PointClass _iclass,
- int _iobjnum = -1) :
- iclass(_iclass), iobjnum(_iobjnum) {
- }
- };
-
- struct PolyIntersectionInfo {
- IntersectionClass iclass;
- P2 ipoint;
- size_t iobjnum;
-
- PolyIntersectionInfo(IntersectionClass _iclass,
- const P2 &_ipoint,
- size_t _iobjnum) :
- iclass(_iclass), ipoint(_ipoint), iobjnum(_iobjnum) {
- }
- };
-
- bool lineSegmentIntersection_simple(const P2 &l1v1, const P2 &l1v2,
- const P2 &l2v1, const P2 &l2v2);
- bool lineSegmentIntersection_simple(const LineSegment2 &l1,
- const LineSegment2 &l2);
-
- LineIntersectionInfo lineSegmentIntersection(const P2 &l1v1, const P2 &l1v2,
- const P2 &l2v1, const P2 &l2v2);
- LineIntersectionInfo lineSegmentIntersection(const LineSegment2 &l1,
- const LineSegment2 &l2);
-
- int lineSegmentPolyIntersections(const std::vector<P2> &points,
- LineSegment2 line,
- std::vector<PolyInclusionInfo> &out);
-
- int sortedLineSegmentPolyIntersections(const std::vector<P2> &points,
- LineSegment2 line,
- std::vector<PolyInclusionInfo> &out);
-
-
-
- static inline bool quadIsConvex(const P2 &a, const P2 &b, const P2 &c, const P2 &d) {
- double s_1, s_2;
-
- s_1 = carve::geom2d::orient2d(a, c, b);
- s_2 = carve::geom2d::orient2d(a, c, d);
- if ((s_1 < 0.0 && s_2 < 0.0) || (s_1 > 0.0 && s_2 > 0.0)) return false;
-
- s_1 = carve::geom2d::orient2d(b, d, a);
- s_2 = carve::geom2d::orient2d(b, d, c);
- if ((s_1 < 0.0 && s_2 < 0.0) || (s_1 > 0.0 && s_2 > 0.0)) return false;
-
- return true;
- }
-
- template<typename T, typename adapt_t>
- inline bool quadIsConvex(const T &a, const T &b, const T &c, const T &d, adapt_t adapt) {
- return quadIsConvex(adapt(a), adapt(b), adapt(c), adapt(d));
- }
-
-
-
- double signedArea(const std::vector<P2> &points);
-
- static inline double signedArea(const P2 &a, const P2 &b, const P2 &c) {
- return ((b.y + a.y) * (b.x - a.x) + (c.y + b.y) * (c.x - b.x) + (a.y + c.y) * (a.x - c.x)) / 2.0;
- }
-
- template<typename T, typename adapt_t>
- double signedArea(const std::vector<T> &points, adapt_t adapt) {
- P2Vector::size_type l = points.size();
- double A = 0.0;
-
- for (P2Vector::size_type i = 0; i < l - 1; i++) {
- A += (adapt(points[i + 1]).y + adapt(points[i]).y) * (adapt(points[i + 1]).x - adapt(points[i]).x);
- }
- A += (adapt(points[0]).y + adapt(points[l - 1]).y) * (adapt(points[0]).x - adapt(points[l - 1]).x);
-
- return A / 2.0;
- }
-
-
-
- template<typename iter_t, typename adapt_t>
- double signedArea(iter_t begin, iter_t end, adapt_t adapt) {
- double A = 0.0;
- P2 p, n;
-
- if (begin == end) return 0.0;
-
- p = adapt(*begin);
- for (iter_t c = begin; ++c != end; ) {
- P2 n = adapt(*c);
- A += (n.y + p.y) * (n.x - p.x);
- p = n;
- }
- n = adapt(*begin);
- A += (n.y + p.y) * (n.x - p.x);
-
- return A / 2.0;
- }
-
-
-
- bool pointInPolySimple(const std::vector<P2> &points, const P2 &p);
-
- template<typename T, typename adapt_t>
- bool pointInPolySimple(const std::vector<T> &points, adapt_t adapt, const P2 &p) {
- CARVE_ASSERT(points.size() > 0);
- P2Vector::size_type l = points.size();
- double s = 0.0;
- double rp, r0, d;
-
- rp = r0 = atan2(adapt(points[0]) - p);
-
- for (P2Vector::size_type i = 1; i < l; i++) {
- double r = atan2(adapt(points[i]) - p);
- d = r - rp;
- if (d > M_PI) d -= M_TWOPI;
- if (d < -M_PI) d += M_TWOPI;
- s = s + d;
- rp = r;
- }
-
- d = r0 - rp;
- if (d > M_PI) d -= M_TWOPI;
- if (d < -M_PI) d += M_TWOPI;
- s = s + d;
-
- return !carve::math::ZERO(s);
- }
-
-
-
- PolyInclusionInfo pointInPoly(const std::vector<P2> &points, const P2 &p);
-
- template<typename T, typename adapt_t>
- PolyInclusionInfo pointInPoly(const std::vector<T> &points, adapt_t adapt, const P2 &p) {
- P2Vector::size_type l = points.size();
- for (unsigned i = 0; i < l; i++) {
- if (equal(adapt(points[i]), p)) return PolyInclusionInfo(POINT_VERTEX, (int)i);
- }
-
- for (unsigned i = 0; i < l; i++) {
- unsigned j = (i + 1) % l;
-
- if (std::min(adapt(points[i]).x, adapt(points[j]).x) - EPSILON < p.x &&
- std::max(adapt(points[i]).x, adapt(points[j]).x) + EPSILON > p.x &&
- std::min(adapt(points[i]).y, adapt(points[j]).y) - EPSILON < p.y &&
- std::max(adapt(points[i]).y, adapt(points[j]).y) + EPSILON > p.y &&
- distance2(carve::geom::rayThrough(adapt(points[i]), adapt(points[j])), p) < EPSILON2) {
- return PolyInclusionInfo(POINT_EDGE, (int)i);
- }
- }
-
- if (pointInPolySimple(points, adapt, p)) {
- return PolyInclusionInfo(POINT_IN);
- }
-
- return PolyInclusionInfo(POINT_OUT);
- }
-
-
-
- bool pickContainedPoint(const std::vector<P2> &poly, P2 &result);
-
- template<typename T, typename adapt_t>
- bool pickContainedPoint(const std::vector<T> &poly, adapt_t adapt, P2 &result) {
-#if defined(CARVE_DEBUG)
- std::cerr << "pickContainedPoint ";
- for (unsigned i = 0; i < poly.size(); ++i) std::cerr << " " << adapt(poly[i]);
- std::cerr << std::endl;
-#endif
-
- const size_t S = poly.size();
- P2 a, b, c;
- for (unsigned i = 0; i < S; ++i) {
- a = adapt(poly[i]);
- b = adapt(poly[(i + 1) % S]);
- c = adapt(poly[(i + 2) % S]);
-
- if (cross(a - b, c - b) < 0) {
- P2 p = (a + b + c) / 3;
- if (pointInPolySimple(poly, adapt, p)) {
- result = p;
- return true;
- }
- }
- }
- return false;
- }
-
- }
-}
diff --git a/extern/carve/include/carve/geom3d.hpp b/extern/carve/include/carve/geom3d.hpp
deleted file mode 100644
index 6c945cc58cf..00000000000
--- a/extern/carve/include/carve/geom3d.hpp
+++ /dev/null
@@ -1,324 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-#include <carve/geom.hpp>
-
-#include <math.h>
-#include <carve/math_constants.hpp>
-
-#include <vector>
-#include <list>
-#include <map>
-
-#if defined(CARVE_DEBUG)
-# include <iostream>
-#endif
-
-#if defined CARVE_USE_EXACT_PREDICATES
-# include <carve/shewchuk_predicates.hpp>
-#endif
-
-namespace carve {
- namespace geom3d {
-
- typedef carve::geom::plane<3> Plane;
- typedef carve::geom::ray<3> Ray;
- typedef carve::geom::linesegment<3> LineSegment;
- typedef carve::geom::vector<3> Vector;
-
- template<typename iter_t, typename adapt_t>
- bool fitPlane(iter_t begin, iter_t end, adapt_t adapt, Plane &plane) {
- std::vector<Vector> p;
- for (; begin != end; ++begin) {
- p.push_back(adapt(*begin));
- }
-
- if (p.size() < 3) {
- return false;
- }
-
- Vector C;
- carve::geom::centroid(p.begin(), p.end(), C);
-
- Vector n;
-
- if (p.size() == 3) {
- n = cross(p[1] - p[0], p[2] - p[0]);
- } else {
- const size_t N = p.size();
-
- n = cross(p[N-1] - C, p[0] - C);
- if (n < Vector::ZERO()) n.negate();
- for (size_t i = 1; i < p.size(); ++i) {
- Vector v = cross(p[i] - C, p[i-1] - C);
- if (v < Vector::ZERO()) v.negate();
- n += v;
- }
- }
-
- double l = n.length();
-
- if (l == 0.0) {
- n.x = 1.0;
- n.y = 0.0;
- n.z = 0.0;
- } else {
- n.normalize();
- }
-
- plane.N = n;
- plane.d = -dot(n, C);
-
-#if defined(CARVE_DEBUG)
- if (p.size() > 3) {
- std::cerr << "N-gon with " << p.size() << " vertices: fitted distance:";
- for (size_t i = 0; i < p.size(); ++i) {
- std::cerr << " {" << p[i] << "} " << distance(plane, p[i]);
- }
- std::cerr << std::endl;
- }
-#endif
-
- return true;
- }
-
- bool planeIntersection(const Plane &a, const Plane &b, Ray &r);
-
- IntersectionClass rayPlaneIntersection(const Plane &p,
- const Vector &v1,
- const Vector &v2,
- Vector &v,
- double &t);
-
- IntersectionClass lineSegmentPlaneIntersection(const Plane &p,
- const LineSegment &line,
- Vector &v);
-
- RayIntersectionClass rayRayIntersection(const Ray &r1,
- const Ray &r2,
- Vector &v1,
- Vector &v2,
- double &mu1,
- double &mu2);
-
-
-
- // test whether point d is above, below or on the plane formed by the triangle a,b,c.
- // return: +ve = d is below a,b,c
- // -ve = d is above a,b,c
- // 0 = d is on a,b,c
-#if defined CARVE_USE_EXACT_PREDICATES
- inline double orient3d(const Vector &a,
- const Vector &b,
- const Vector &c,
- const Vector &d) {
- return shewchuk::orient3d(a.v, b.v, c.v, d.v);
- }
-#else
- inline double orient3d(const Vector &a,
- const Vector &b,
- const Vector &c,
- const Vector &d) {
- return dotcross((a - d), (b - d), (c - d));
- }
-#endif
-
- // Volume of a tetrahedron described by 4 points. Will be
- // positive if the anticlockwise normal of a,b,c is oriented out
- // of the tetrahedron.
- //
- // see: http://mathworld.wolfram.com/Tetrahedron.html
- inline double tetrahedronVolume(const Vector &a,
- const Vector &b,
- const Vector &c,
- const Vector &d) {
- return dotcross((a - d), (b - d), (c - d)) / 6.0;
- }
-
- /**
- * \brief Determine whether p is internal to the wedge defined by
- * the area between the planes defined by a,b,c and a,b,d
- * angle abc, where ab is the apex of the angle.
- *
- * @param[in] a
- * @param[in] b
- * @param[in] c
- * @param[in] d
- * @param[in] p
- *
- * @return true, if p is contained in the wedge defined by the
- * area between the planes defined by a,b,c and
- * a,b,d. If the wedge is reflex, p is considered to
- * be contained if it lies on either plane. Acute
- * wdges do not contain p if p lies on either
- * plane. This is so that internalToWedge(a,b,c,d,p) =
- * !internalToWedge(a,b,d,c,p)
- */
- inline bool internalToWedge(const Vector &a,
- const Vector &b,
- const Vector &c,
- const Vector &d,
- const Vector &p) {
- bool reflex = (c < d) ?
- orient3d(a, b, c, d) >= 0.0 :
- orient3d(a, b, d, c) < 0.0;
-
- double d1 = orient3d(a, b, c, p);
- double d2 = orient3d(a, b, d, p);
-
- if (reflex) {
- // above a,b,c or below a,b,d (or coplanar with either)
- return d1 <= 0.0 || d2 >= 0.0;
- } else {
- // above a,b,c and below a,b,d
- return d1 < 0.0 && d2 > 0.0;
- }
- }
-
- /**
- * \brief Determine the ordering relationship of a and b, when
- * rotating around direction, starting from base.
- *
- * @param[in] adirection
- * @param[in] base
- * @param[in] a
- * @param[in] b
- *
- * @return
- * * -1, if a is ordered before b around, rotating about direction.
- * * 0, if a and b are equal in angle.
- * * +1, if a is ordered after b around, rotating about direction.
- */
- inline int compareAngles(const Vector &direction, const Vector &base, const Vector &a, const Vector &b) {
- // double d1 = carve::geom3d::orient3d(carve::geom::VECTOR(0,0,0), direction, a, b);
- // double d2 = carve::geom3d::orient3d(carve::geom::VECTOR(0,0,0), direction, base, a);
- // double d3 = carve::geom3d::orient3d(carve::geom::VECTOR(0,0,0), direction, base, b);
-
-#if defined(CARVE_USE_EXACT_PREDICATES)
- // which is equivalent to the following (which eliminates a
- // vector subtraction):
- double d1 = carve::geom3d::orient3d(direction, b, a, carve::geom::VECTOR(0,0,0));
- double d2 = carve::geom3d::orient3d(direction, a, base, carve::geom::VECTOR(0,0,0));
- double d3 = carve::geom3d::orient3d(direction, b, base, carve::geom::VECTOR(0,0,0));
-#else
- // dotcross = a . (b x c)
- double d1 = carve::geom::dotcross(direction, b, a );
- double d2 = carve::geom::dotcross(direction, a, base);
- double d3 = carve::geom::dotcross(direction, b, base);
-#endif
-
- // CASE: a and b are coplanar wrt. direction.
- if (d1 == 0.0) {
- // a and b point in the same direction.
- if (dot(a, b) > 0.0) {
- // Neither is less than the other.
- return 0;
- }
-
- // a and b point in opposite directions.
- // * if d2 < 0.0, a is above plane(direction, base) and is less
- // than b.
- // * if d2 == 0.0 a is coplanar with plane(direction, base) and is
- // less than b if it points in the same direction as base.
- // * if d2 > 0.0, a is below plane(direction, base) and is greater
- // than b.
-
- if (d2 == 0.0) { return dot(a, base) > 0.0 ? -1 : +1; }
- if (d3 == 0.0) { return dot(b, base) > 0.0 ? +1 : -1; }
- if (d2 < 0.0 && d3 > 0.0) return -1;
- if (d2 > 0.0 && d3 < 0.0) return +1;
-
- // both a and b are to one side of plane(direction, base) -
- // rounding error (if a and b are truly coplanar with
- // direction, one should be above, and one should be below any
- // other plane that is not itself coplanar with
- // plane(direction, a|b) - which would imply d2 and d3 == 0.0).
-
- // If both are below plane(direction, base) then the one that
- // points in the same direction as base is greater.
- // If both are above plane(direction, base) then the one that
- // points in the same direction as base is lesser.
- if (d2 > 0.0) { return dot(a, base) > 0.0 ? +1 : -1; }
- else { return dot(a, base) > 0.0 ? -1 : +1; }
- }
-
- // CASE: a and b are not coplanar wrt. direction
-
- if (d2 < 0.0) {
- // if a is above plane(direction,base), then a is less than b if
- // b is below plane(direction,base) or b is above plane(direction,a)
- return (d3 > 0.0 || d1 < 0.0) ? -1 : +1;
- } else if (d2 == 0.0) {
- // if a is on plane(direction,base) then a is less than b if a
- // points in the same direction as base, or b is below
- // plane(direction,base)
- return (dot(a, base) > 0.0 || d3 > 0.0) ? -1 : +1;
- } else {
- // if a is below plane(direction,base), then a is less than b if b
- // is below plane(direction,base) and b is above plane(direction,a)
- return (d3 > 0.0 && d1 < 0.0) ? -1 : +1;
- }
- }
-
- // The anticlockwise angle from vector "from" to vector "to", oriented around the vector "orient".
- static inline double antiClockwiseAngle(const Vector &from, const Vector &to, const Vector &orient) {
- double dp = dot(from, to);
- Vector cp = cross(from, to);
- if (cp.isZero()) {
- if (dp < 0) {
- return M_PI;
- } else {
- return 0.0;
- }
- } else {
- if (dot(cp, orient) > 0.0) {
- return acos(dp);
- } else {
- return M_TWOPI - acos(dp);
- }
- }
- }
-
-
-
- static inline double antiClockwiseOrdering(const Vector &from, const Vector &to, const Vector &orient) {
- double dp = dot(from, to);
- Vector cp = cross(from, to);
- if (cp.isZero()) {
- if (dp < 0) {
- return 2.0;
- } else {
- return 0.0;
- }
- } else {
- if (dot(cp, orient) > 0.0) {
- // 1..-1 -> 0..2
- return 1.0 - dp;
- } else {
- // -1..1 -> 2..4
- return dp + 1.0;
- }
- }
- }
-
-
-
- }
-}
diff --git a/extern/carve/include/carve/geom_impl.hpp b/extern/carve/include/carve/geom_impl.hpp
deleted file mode 100644
index cd1d5f8bac6..00000000000
--- a/extern/carve/include/carve/geom_impl.hpp
+++ /dev/null
@@ -1,672 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/math.hpp>
-
-namespace carve {
- namespace geom {
-
-
-
- template<unsigned ndim>
- double vector<ndim>::length2() const { return dot(*this, *this); }
-
- template<unsigned ndim>
- double vector<ndim>::length() const { return sqrt(dot(*this, *this)); }
-
- template<unsigned ndim>
- vector<ndim> &vector<ndim>::normalize() {
-#if defined(CARVE_DEBUG)
- CARVE_ASSERT(length() > 0.0);
-#endif
- *this /= length();
- return *this;
- }
-
- template<unsigned ndim>
- vector<ndim> vector<ndim>::normalized() const {
-#if defined(CARVE_DEBUG)
- CARVE_ASSERT(length() > 0.0);
-#endif
- return *this / length();
- }
-
- template<unsigned ndim>
- bool vector<ndim>::exactlyZero() const {
- for (unsigned i = 0; i < ndim; ++i) if (this->v[i]) return false;
- return true;
- }
- template<unsigned ndim>
- bool vector<ndim>::isZero(double epsilon) const {
- return length2() < epsilon * epsilon;
- }
-
- template<unsigned ndim>
- void vector<ndim>::setZero() { for (size_t i = 0; i < ndim; ++i) this->v[i] = 0.0; }
-
- template<unsigned ndim>
- void vector<ndim>::fill(double val) { for (size_t i = 0; i < ndim; ++i) this->v[i] = val; }
-
- template<unsigned ndim>
- vector<ndim> &vector<ndim>::scaleBy(double d) { for (unsigned i = 0; i < ndim; ++i) this->v[i] *= d; return *this; }
- template<unsigned ndim>
- vector<ndim> &vector<ndim>::invscaleBy(double d) { for (unsigned i = 0; i < ndim; ++i) this->v[i] /= d; return *this; }
-
- template<unsigned ndim>
- vector<ndim> vector<ndim>::scaled(double d) const { return *this * d; }
- template<unsigned ndim>
- vector<ndim> vector<ndim>::invscaled(double d) const { return *this / d; }
-
- template<unsigned ndim>
- vector<ndim> &vector<ndim>::negate() { for (unsigned i = 0; i < ndim; ++i) this->v[i] = -this->v[i]; return *this; }
- template<unsigned ndim>
- vector<ndim> vector<ndim>::negated() const { return -*this; }
-
- template<unsigned ndim>
- double &vector<ndim>::operator[](unsigned i) { return this->v[i]; }
- template<unsigned ndim>
- const double &vector<ndim>::operator[](unsigned i) const { return this->v[i]; }
-
- template<unsigned ndim>
- template<typename assign_t>
- vector<ndim> &vector<ndim>::operator=(const assign_t &t) {
- for (unsigned i = 0; i < ndim; ++i) this->v[i] = t[i];
- return *this;
- }
-
- template<unsigned ndim>
- std::string vector<ndim>::asStr() const {
- std::ostringstream out;
- out << '<';
- out << std::setprecision(24);
- for (unsigned i = 0; i < ndim; ++i) { if (i) out << ','; out << this->v[i]; }
- out << '>';
- return out.str();
- }
-
-
-
- template<unsigned ndim>
- vector<ndim> operator+(const vector<ndim> &a, const vector<ndim> &b) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] + b[i];
- return c;
- }
-
- template<unsigned ndim>
- vector<ndim> operator+(const vector<ndim> &a, double b) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] + b;
- return c;
- }
-
- template<unsigned ndim, typename val_t>
- vector<ndim> operator+(const vector<ndim> &a, const val_t &b) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] + b[i];
- return c;
- }
-
- template<unsigned ndim, typename val_t>
- vector<ndim> operator+(const val_t &a, const vector<ndim> &b) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] + b[i];
- return c;
- }
-
- template<unsigned ndim>
- vector<ndim> &operator+=(vector<ndim> &a, const vector<ndim> &b) {
- for (unsigned i = 0; i < ndim; ++i) a[i] += b[i];
- return a;
- }
-
- template<unsigned ndim>
- vector<ndim> &operator+=(vector<ndim> &a, double b) {
- for (unsigned i = 0; i < ndim; ++i) a[i] += b;
- return a;
- }
-
- template<unsigned ndim, typename val_t>
- vector<ndim> &operator+=(vector<ndim> &a, const val_t &b) {
- for (unsigned i = 0; i < ndim; ++i) a[i] += b[i];
- return a;
- }
-
-
-
- template<unsigned ndim>
- vector<ndim> operator-(const vector<ndim> &a) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = -a[i];
- return c;
- }
-
-
-
- template<unsigned ndim>
- vector<ndim> operator-(const vector<ndim> &a, double b) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] - b;
- return c;
- }
-
- template<unsigned ndim>
- vector<ndim> operator-(const vector<ndim> &a, const vector<ndim> &b) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] - b[i];
- return c;
- }
-
- template<unsigned ndim, typename val_t>
- vector<ndim> operator-(const vector<ndim> &a, const val_t &b) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] - b[i];
- return c;
- }
-
- template<unsigned ndim, typename val_t>
- vector<ndim> operator-(const val_t &a, const vector<ndim> &b) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] - b[i];
- return c;
- }
-
- template<unsigned ndim>
- vector<ndim> &operator-=(vector<ndim> &a, const vector<ndim> &b) {
- for (unsigned i = 0; i < ndim; ++i) a[i] -= b[i];
- return a;
- }
-
- template<unsigned ndim>
- vector<ndim> &operator-=(vector<ndim> &a, double b) {
- for (unsigned i = 0; i < ndim; ++i) a[i] -= b;
- return a;
- }
-
- template<unsigned ndim, typename val_t>
- vector<ndim> &operator-=(vector<ndim> &a, const val_t &b) {
- for (unsigned i = 0; i < ndim; ++i) a[i] -= b[i];
- return a;
- }
-
-
-
- template<unsigned ndim>
- vector<ndim> operator*(const vector<ndim> &a, double s) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] * s;
- return c;
- }
-
- template<unsigned ndim>
- vector<ndim> operator*(double s, const vector<ndim> &a) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] * s;
- return c;
- }
-
- template<unsigned ndim>
- vector<ndim> &operator*=(vector<ndim> &a, double s) {
- for (unsigned i = 0; i < ndim; ++i) a[i] *= s;
- return a;
- }
-
-
-
- template<unsigned ndim>
- vector<ndim> operator/(const vector<ndim> &a, double s) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = a[i] / s;
- return c;
- }
-
- template<unsigned ndim>
- vector<ndim> &operator/=(vector<ndim> &a, double s) {
- for (unsigned i = 0; i < ndim; ++i) a[i] /= s;
- return a;
- }
-
-
-
- template<unsigned ndim>
- bool operator==(const vector<ndim> &a, const vector<ndim> &b) {
- for (unsigned i = 0; i < ndim; ++i) { if (a[i] != b[i]) return false; }
- return true;
- }
-
- template<unsigned ndim>
- bool operator!=(const vector<ndim> &a, const vector<ndim> &b) {
- return !(a == b);
- }
-
- template<unsigned ndim>
- bool operator<(const vector<ndim> &a, const vector<ndim> &b) {
- for (unsigned i = 0; i < ndim; ++i) { if (a[i] < b[i]) return true; if (a[i] > b[i]) return false; }
- return false;
- }
-
- template<unsigned ndim>
- bool operator<=(const vector<ndim> &a, const vector<ndim> &b) {
- return !(b < a);
- }
-
- template<unsigned ndim>
- bool operator>(const vector<ndim> &a, const vector<ndim> &b) {
- return b < a;
- }
-
- template<unsigned ndim>
- bool operator>=(const vector<ndim> &a, const vector<ndim> &b) {
- return !(a < b);
- }
-
-
-
- template<unsigned ndim>
- vector<ndim> abs(const vector<ndim> &a) {
- vector<ndim> c(NOINIT);
- for (unsigned i = 0; i < ndim; ++i) c[i] = fabs(a[i]);
- return c;
- }
-
- template<unsigned ndim>
- double distance2(const vector<ndim> &a, const vector<ndim> &b) {
- return (b - a).length2();
- }
-
- template<unsigned ndim>
- double distance(const vector<ndim> &a, const vector<ndim> &b) {
- return (b - a).length();
- }
-
- template<unsigned ndim>
- bool equal(const vector<ndim> &a, const vector<ndim> &b) {
- return (b - a).isZero();
- }
-
- template<unsigned ndim>
- int smallestAxis(const vector<ndim> &a) {
- int idx = 0;
- double lo = fabs(a[0]);
- for (unsigned i = 1; i < ndim; ++i) {
- double val = fabs(a[i]);
- if (val <= lo) { lo = val; idx = (int)i; }
- }
- return idx;
- }
-
- template<unsigned ndim>
- int largestAxis(const vector<ndim> &a) {
- int idx = 0;
- double hi = fabs(a[0]);
- for (unsigned i = 1; i < ndim; ++i) {
- double val = fabs(a[i]);
- if (val > hi) { hi = val; idx = (int)i; }
- }
- return idx;
- }
-
- template<unsigned ndim>
- vector<2> select(const vector<ndim> &a, int a1, int a2) {
- vector<2> r(NOINIT);
- r.v[0] = a.v[a1]; r.v[1] = a.v[a2];
- return r;
- }
-
- template<unsigned ndim>
- vector<3> select(const vector<ndim> &a, int a1, int a2, int a3) {
- vector<3> r(NOINIT);
- r.v[0] = a.v[a1]; r.v[1] = a.v[a2]; r.v[2] = a.v[a3];
- return r;
- }
-
- template<unsigned ndim, typename assign_t, typename oper_t>
- vector<ndim> &assign_op(vector<ndim> &a, const assign_t &t, oper_t op) {
- for (unsigned i = 0; i < ndim; ++i) a[i] = op(t[i]);
- return a;
- }
-
- template<unsigned ndim, typename assign1_t, typename assign2_t, typename oper_t>
- vector<ndim> &assign_op(vector<ndim> &a, const assign1_t &t1, const assign2_t &t2, oper_t op) {
- for (unsigned i = 0; i < ndim; ++i) a[i] = op(t1[i], t2[i]);
- return a;
- }
-
- template<unsigned ndim, typename iter_t>
- void bounds(iter_t begin, iter_t end, vector<ndim> &min, vector<ndim> &max) {
- if (begin == end) {
- min.setZero();
- max.setZero();
- } else {
- min = max = *begin;
- while (++begin != end) {
- vector<ndim> v = *begin;
- assign_op(min, min, v, carve::util::min_functor());
- assign_op(max, max, v, carve::util::max_functor());
- }
- }
- }
-
- template<unsigned ndim, typename iter_t, typename adapt_t>
- void bounds(iter_t begin, iter_t end, adapt_t adapt, vector<ndim> &min, vector<ndim> &max) {
- if (begin == end) {
- min.setZero();
- max.setZero();
- } else {
- min = max = adapt(*begin);
- while (++begin != end) {
- vector<ndim> v = adapt(*begin);
- assign_op(min, min, v, carve::util::min_functor());
- assign_op(max, max, v, carve::util::max_functor());
- }
- }
- }
-
- template<unsigned ndim, typename iter_t>
- void centroid(iter_t begin, iter_t end, vector<ndim> &c) {
- c.setZero();
- int n = 0;
- for (; begin != end; ++begin, ++n) { c += *begin; }
- c /= double(n);
- }
-
- template<unsigned ndim, typename iter_t, typename adapt_t>
- void centroid(iter_t begin, iter_t end, adapt_t adapt, vector<ndim> &c) {
- c.setZero();
- int n = 0;
- for (; begin != end; ++begin, ++n) { c += adapt(*begin); }
- c /= double(n);
- }
-
- template<unsigned ndim, typename val_t>
- double dot(const vector<ndim> &a, const val_t &b) {
- double r = 0.0;
- for (unsigned i = 0; i < ndim; ++i) r += a[i] * b[i];
- return r;
- }
-
- static inline vector<3> cross(const vector<3> &a, const vector<3> &b) {
- // Compute a x b
- return VECTOR(+(a.y * b.z - a.z * b.y),
- -(a.x * b.z - a.z * b.x),
- +(a.x * b.y - a.y * b.x));
- }
-
- static inline double cross(const vector<2> &a, const vector<2> &b) {
- // Compute a x b
- return a.x * b.y - b.x * a.y;
- }
-
- static inline double dotcross(const vector<3> &a, const vector<3> &b, const vector<3> &c) {
- // Compute a . (b x c)
- return
- (a.x * b.y * c.z + a.y * b.z * c.x + a.z * b.x * c.y) -
- (a.x * c.y * b.z + a.y * c.z * b.x + a.z * c.x * b.y);
- }
-
-
-
- template<unsigned ndim>
- double distance(const axis_pos &a, const vector<ndim> &b) {
- return fabs(b[a.axis] - a.pos);
- }
-
- template<unsigned ndim>
- double distance2(const axis_pos &a, const vector<ndim> &b) {
- double r = fabs(b[a.axis] - a.pos);
- return r * r;
- }
-
- template<unsigned ndim> bool operator<(const axis_pos &a, const vector<ndim> &b) { return a.pos < b[a.axis]; }
- template<unsigned ndim> bool operator<(const vector<ndim> &a, const axis_pos &b) { return a[b.axis] < b.pos; }
-
- template<unsigned ndim> bool operator<=(const axis_pos &a, const vector<ndim> &b) { return a.pos <= b[a.axis]; }
- template<unsigned ndim> bool operator<=(const vector<ndim> &a, const axis_pos &b) { return a[b.axis] <= b.pos; }
-
- template<unsigned ndim> bool operator>(const axis_pos &a, const vector<ndim> &b) { return a.pos > b[a.axis]; }
- template<unsigned ndim> bool operator>(const vector<ndim> &a, const axis_pos &b) { return a[b.axis] > b.pos; }
-
- template<unsigned ndim> bool operator>=(const axis_pos &a, const vector<ndim> &b) { return a.pos >= b[a.axis]; }
- template<unsigned ndim> bool operator>=(const vector<ndim> &a, const axis_pos &b) { return a[b.axis] >= b.pos; }
-
- template<unsigned ndim> bool operator==(const axis_pos &a, const vector<ndim> &b) { return a.pos == b[a.axis]; }
- template<unsigned ndim> bool operator==(const vector<ndim> &a, const axis_pos &b) { return a[b.axis] == b.pos; }
-
- template<unsigned ndim> bool operator!=(const axis_pos &a, const vector<ndim> &b) { return a.pos != b[a.axis]; }
- template<unsigned ndim> bool operator!=(const vector<ndim> &a, const axis_pos &b) { return a[b.axis] != b.pos; }
-
-
-
- template<unsigned ndim>
- bool ray<ndim>::OK() const {
- return !D.isZero();
- }
-
- template<unsigned ndim>
- ray<ndim> rayThrough(const vector<ndim> &a, const vector<ndim> &b) {
- return ray<ndim>(b - a, a);
- }
-
- static inline double distance2(const ray<3> &r, const vector<3> &v) {
- return cross(r.D, v - r.v).length2() / r.D.length2();
- }
-
- static inline double distance(const ray<3> &r, const vector<3> &v) {
- return sqrt(distance2(r, v));
- }
-
- static inline double distance2(const ray<2> &r, const vector<2> &v) {
- double t = cross(r.D, v - r.v);
- return (t * t) / r.D.length2();
- }
-
- static inline double distance(const ray<2> &r, const vector<2> &v) {
- return sqrt(distance2(r, v));
- }
-
-
-
- template<unsigned ndim>
- void linesegment<ndim>::update() {
- midpoint = (v2 + v1) / 2.0;
- half_length = (v2 - v1) / 2.0;
- }
-
- template<unsigned ndim>
- bool linesegment<ndim>::OK() const {
- return !half_length.isZero();
- }
-
- template<unsigned ndim>
- void linesegment<ndim>::flip() {
- std::swap(v1, v2);
- half_length = (v2 - v1) / 2.0;
- }
-
- template<unsigned ndim>
- aabb<ndim> linesegment<ndim>::getAABB() const {
- aabb<ndim> r;
- r.fit(v1, v2);
- return r;
- }
-
- template<unsigned ndim>
- linesegment<ndim>::linesegment(const vector_t &_v1, const vector_t &_v2) : v1(_v1), v2(_v2) {
- update();
- }
-
-
-
- template<unsigned ndim>
- double distance2(const linesegment<ndim> &l, const vector<ndim> &v) {
- vector<ndim> D = l.v2 - l.v1;
- double t = dot(v - l.v1, D) / dot(D, D);
- if (t <= 0.0) return (v - l.v1).length2();
- if (t >= 1.0) return (v - l.v2).length2();
- vector<ndim> vc = D * t + l.v1;
- return (v - vc).length2();
- }
-
- template<unsigned ndim>
- double distance(const linesegment<ndim> &l, const vector<ndim> &v) {
- return sqrt(distance2(l, v));
- }
-
-
- template<unsigned ndim>
- void plane<ndim>::negate() {
- N.negate();
- d = -d;
- }
-
- template<unsigned ndim>
- plane<ndim>::plane() {
- N.setZero();
- N[0] = 1.0;
- d= 0.0;
- }
-
- template<unsigned ndim>
- plane<ndim>::plane(const vector_t &_N, vector_t _p) : N(_N), d(-dot(_p, _N)) {
- }
-
- template<unsigned ndim>
- plane<ndim>::plane(const vector_t &_N, double _d) : N(_N), d(_d) {
- }
-
-
-
- template<unsigned ndim>
- plane<ndim> operator-(const plane<ndim> &p) {
- return plane<ndim>(-p.N, -p.d);
- }
-
- template<unsigned ndim, typename val_t>
- double distance(const plane<ndim> &plane, const val_t &point) {
- return dot(plane.N, point) + plane.d;
- }
-
- template<unsigned ndim, typename val_t>
- double distance2(const plane<ndim> &plane, const val_t &point) {
- double d = distance(plane, point);
- return d * d;
- }
-
- template<unsigned ndim>
- vector<ndim> closestPoint(const plane<ndim> &p, const vector<ndim> &v) {
- return v - p.N * (p.d + dot(p.N, v)) / dot(p.N, p.N);
- }
-
-
-
- template<unsigned ndim>
- aabb<ndim> sphere<ndim>::getAABB() const {
- aabb<ndim> r;
- r.fit(C - r, C + r);
- }
-
- template<unsigned ndim>
- sphere<ndim>::sphere() {
- C.setZero();
- r = 1.0;
- }
-
- template<unsigned ndim>
- sphere<ndim>::sphere(const vector_t &_C, double _r) : C(_C), r(_r) {
- }
-
-
-
- template<unsigned ndim, typename val_t>
- double distance(const sphere<ndim> &sphere, const val_t &point) {
- return std::max(0.0, distance(sphere.C, point) - sphere.r);
- }
-
- template<unsigned ndim, typename val_t>
- double distance2(const sphere<ndim> &sphere, const val_t &point) {
- return std::max(0.0, distance2(sphere.C, point) - sphere.r * sphere.r);
- }
-
- template<unsigned ndim>
- vector<ndim> closestPoint(const sphere<ndim> &sphere, const vector<ndim> &point) {
- return (point - sphere.C).normalized() * sphere.r;
- }
-
-
-
- template<unsigned ndim>
- aabb<ndim> tri<ndim>::getAABB() const {
- aabb<ndim> aabb;
- aabb.fit(v[0], v[1], v[2]);
- return aabb;
- }
-
- template<unsigned ndim>
- tri<ndim>::tri(vector_t _v[3]) {
- std::copy(v, v+3, _v);
- }
-
- template<unsigned ndim>
- tri<ndim>::tri(const vector_t &a, const vector_t &b, const vector_t &c) {
- v[0] = a;
- v[1] = b;
- v[2] = c;
- }
-
-
-
- template<unsigned ndim>
- std::ostream &operator<<(std::ostream &o, const vector<ndim> &v) {
- o << v.asStr();
- return o;
- }
-
- template<unsigned ndim>
- std::ostream &operator<<(std::ostream &o, const carve::geom::plane<ndim> &p) {
- o << p.N << ";" << p.d;
- return o;
- }
-
- template<unsigned ndim>
- std::ostream &operator<<(std::ostream &o, const carve::geom::sphere<ndim> &sphere) {
- o << "{sphere " << sphere.C << ";" << sphere.r << "}";
- return o;
- }
-
- template<unsigned ndim>
- std::ostream &operator<<(std::ostream &o, const carve::geom::tri<ndim> &tri) {
- o << "{tri " << tri.v[0] << ";" << tri.v[1] << ";" << tri.v[2] << "}";
- return o;
- }
-
-
-
- template<unsigned ndim>
- double distance(const tri<ndim> &tri, const vector<ndim> &pt) {
- return distance(closestPoint(tri, pt), pt);
- }
-
-
-
- template<unsigned ndim>
- double distance2(const tri<ndim> &tri, const vector<ndim> &pt) {
- return distance2(closestPoint(tri, pt), pt);
- }
- }
-}
diff --git a/extern/carve/include/carve/gnu_cxx.h b/extern/carve/include/carve/gnu_cxx.h
deleted file mode 100644
index 280fa360478..00000000000
--- a/extern/carve/include/carve/gnu_cxx.h
+++ /dev/null
@@ -1,4 +0,0 @@
-// Copyright 2006 Tobias Sargeant (toby@permuted.net)
-// All rights reserved.
-
-#pragma once
diff --git a/extern/carve/include/carve/heap.hpp b/extern/carve/include/carve/heap.hpp
deleted file mode 100644
index b6ec6b29528..00000000000
--- a/extern/carve/include/carve/heap.hpp
+++ /dev/null
@@ -1,425 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-namespace carve {
- namespace heap {
- namespace detail {
-
-
-
- struct ignore_position_t {
- template<typename value_t>
- void operator()(value_t &val, size_t idx) const {}
- };
-
-
-
- template<typename random_access_iter_t,
- typename distance_t,
- typename value_t,
- typename pred_t,
- typename pos_notifier_t>
- void _adjust_heap(random_access_iter_t begin,
- distance_t pos,
- distance_t len,
- value_t val,
- pred_t pred,
- pos_notifier_t notify) {
- const distance_t top = pos;
-
- distance_t child = pos * 2 + 2;
- while (child < len) {
- if (pred(begin[child], begin[child - 1])) child--;
-
- begin[pos] = begin[child];
- notify(begin[pos], pos);
- pos = child;
- child = pos * 2 + 2;
- }
-
- if (child == len) {
- child--;
- begin[pos] = begin[child];
- notify(begin[pos], pos);
- pos = child;
- }
-
- distance_t parent = (pos - 1) / 2;
- while (pos > top && pred(begin[parent], val)) {
- begin[pos] = begin[parent];
- notify(begin[pos], pos);
- pos = parent;
- parent = (pos - 1) / 2;
- }
-
- begin[pos] = val;
- notify(begin[pos], pos);
- }
-
-
-
- template<typename random_access_iter_t,
- typename distance_t,
- typename value_t,
- typename pred_t,
- typename pos_notifier_t>
- void _push_heap(random_access_iter_t begin,
- distance_t pos,
- value_t val,
- pred_t pred,
- pos_notifier_t notify) {
- distance_t parent = (pos - 1) / 2;
- while (pos > 0 && pred(begin[parent], val)) {
- begin[pos] = begin[parent];
- notify(begin[pos], pos);
- pos = parent;
- parent = (pos - 1) / 2;
- }
- begin[pos] = val;
- notify(begin[pos], pos);
- }
-
-
-
- template<typename random_access_iter_t,
- typename distance_t,
- typename pred_t,
- typename pos_notifier_t>
- void _remove_heap(random_access_iter_t begin,
- distance_t pos,
- distance_t len,
- pred_t pred,
- pos_notifier_t notify) {
- --len;
- if (pos != len) {
- typedef typename std::iterator_traits<random_access_iter_t>::value_type value_t;
- value_t removed = begin[pos];
- _adjust_heap(begin, pos, len, begin[len], pred, notify);
- begin[len] = removed;
- notify(begin[len], len);
- }
- }
-
-
-
- template<typename random_access_iter_t,
- typename distance_t,
- typename pred_t,
- typename pos_notifier_t>
- void _make_heap(random_access_iter_t begin,
- distance_t len,
- pred_t pred,
- pos_notifier_t notify) {
- for (distance_t pos = len / 2; pos > 0; ) {
- --pos;
- _adjust_heap(begin, pos, len, begin[pos], pred, ignore_position_t());
- }
- for (distance_t pos = 0; pos < len; ++pos) {
- notify(begin[pos], pos);
- }
- }
-
-
-
- template<typename random_access_iter_t,
- typename distance_t,
- typename pred_t>
- void _make_heap(random_access_iter_t begin,
- distance_t len,
- pred_t pred,
- ignore_position_t) {
- for (distance_t pos = len / 2; pos > 0; ) {
- --pos;
- _adjust_heap(begin, pos, len, begin[pos], pred, ignore_position_t());
- }
- }
-
-
-
- template<typename random_access_iter_t,
- typename distance_t,
- typename pred_t>
- bool _is_heap(random_access_iter_t begin,
- distance_t len,
- pred_t pred) {
- distance_t parent = 0;
-
- for (distance_t child = 1; child < len; ++child) {
- if (pred(begin[parent], begin[child])) {
- return false;
- }
- if (++child == len) break;
- if (pred(begin[parent], begin[child])) {
- return false;
- }
- ++parent;
- }
-
- return true;
- }
-
-
-
- }
-
-
-
- template<typename random_access_iter_t>
- void adjust_heap(random_access_iter_t begin,
- random_access_iter_t end,
- random_access_iter_t pos) {
- typedef typename std::iterator_traits<random_access_iter_t>::value_type value_t;
-
- detail::_adjust_heap(begin, pos - begin, end - begin, *pos, std::less<value_t>());
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t>
- void adjust_heap(random_access_iter_t begin,
- random_access_iter_t end,
- random_access_iter_t pos,
- pred_t pred) {
- detail::_adjust_heap(begin, pos - begin, end - begin, *pos, pred);
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t,
- typename pos_notifier_t>
- void adjust_heap(random_access_iter_t begin,
- random_access_iter_t end,
- random_access_iter_t pos,
- pred_t pred,
- pos_notifier_t notify) {
- detail::_adjust_heap(begin, pos - begin, end - begin, *pos, pred, notify);
- }
-
-
-
- template<typename random_access_iter_t>
- void remove_heap(random_access_iter_t begin,
- random_access_iter_t end,
- random_access_iter_t pos) {
- typedef typename std::iterator_traits<random_access_iter_t>::value_type value_t;
-
- detail::_remove_heap(begin, pos - begin, end - begin, std::less<value_t>(), detail::ignore_position_t());
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t>
- void remove_heap(random_access_iter_t begin,
- random_access_iter_t end,
- random_access_iter_t pos,
- pred_t pred) {
- detail::_remove_heap(begin, pos - begin, end - begin, pred, detail::ignore_position_t());
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t,
- typename pos_notifier_t>
- void remove_heap(random_access_iter_t begin,
- random_access_iter_t end,
- random_access_iter_t pos,
- pred_t pred,
- pos_notifier_t notify) {
- detail::_remove_heap(begin, pos - begin, end - begin, pred, notify);
- }
-
-
-
- template<typename random_access_iter_t>
- void pop_heap(random_access_iter_t begin,
- random_access_iter_t end) {
- typedef typename std::iterator_traits<random_access_iter_t>::value_type value_t;
- typedef typename std::iterator_traits<random_access_iter_t>::difference_type distance_t;
-
- detail::_remove_heap(begin, distance_t(0), end - begin, std::less<value_t>(), detail::ignore_position_t());
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t>
- void pop_heap(random_access_iter_t begin,
- random_access_iter_t end,
- pred_t pred) {
- typedef typename std::iterator_traits<random_access_iter_t>::difference_type distance_t;
-
- detail::_remove_heap(begin, distance_t(0), end - begin, pred, detail::ignore_position_t());
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t,
- typename pos_notifier_t>
- void pop_heap(random_access_iter_t begin,
- random_access_iter_t end,
- pred_t pred,
- pos_notifier_t notify) {
- typedef typename std::iterator_traits<random_access_iter_t>::difference_type distance_t;
-
- detail::_remove_heap(begin, distance_t(0), end - begin, pred, notify);
- }
-
-
-
- template<typename random_access_iter_t>
- void push_heap(random_access_iter_t begin,
- random_access_iter_t end) {
- typedef typename std::iterator_traits<random_access_iter_t>::value_type value_t;
- typedef typename std::iterator_traits<random_access_iter_t>::difference_type distance_t;
-
- distance_t pos = end - begin - 1;
- detail::_push_heap(begin, pos, begin[pos], std::less<value_t>(), detail::ignore_position_t());
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t>
- void push_heap(random_access_iter_t begin,
- random_access_iter_t end,
- pred_t pred) {
- typedef typename std::iterator_traits<random_access_iter_t>::difference_type distance_t;
-
- distance_t pos = end - begin - 1;
- detail::_push_heap(begin, pos, begin[pos], pred, detail::ignore_position_t());
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t,
- typename pos_notifier_t>
- void push_heap(random_access_iter_t begin,
- random_access_iter_t end,
- pred_t pred,
- pos_notifier_t notify) {
- typedef typename std::iterator_traits<random_access_iter_t>::difference_type distance_t;
-
- distance_t pos = end - begin - 1;
- detail::_push_heap(begin, pos, begin[pos], pred, notify);
- }
-
-
-
- template<typename random_access_iter_t>
- void make_heap(random_access_iter_t begin,
- random_access_iter_t end) {
- typedef typename std::iterator_traits<random_access_iter_t>::value_type value_t;
-
- detail::_make_heap(begin, end - begin, std::less<value_t>(), detail::ignore_position_t());
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t>
- void make_heap(random_access_iter_t begin,
- random_access_iter_t end,
- pred_t pred) {
- detail::_make_heap(begin, end - begin, pred, detail::ignore_position_t());
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t,
- typename pos_notifier_t>
- void make_heap(random_access_iter_t begin,
- random_access_iter_t end,
- pred_t pred,
- pos_notifier_t notify) {
- detail::_make_heap(begin, end - begin, pred, notify);
- }
-
-
-
- template<typename random_access_iter_t>
- bool is_heap(random_access_iter_t begin,
- random_access_iter_t end) {
- typedef typename std::iterator_traits<random_access_iter_t>::value_type value_t;
-
- return detail::_is_heap(begin, end - begin, std::less<value_t>());
- }
-
-
-
- template<typename random_access_iter_t, typename pred_t>
- bool is_heap(random_access_iter_t begin,
- random_access_iter_t end,
- pred_t pred) {
- return detail::_is_heap(begin, end - begin, pred);
- }
-
-
-
- template<typename random_access_iter_t>
- void sort_heap(random_access_iter_t begin,
- random_access_iter_t end) {
- typedef typename std::iterator_traits<random_access_iter_t>::difference_type distance_t;
- typedef typename std::iterator_traits<random_access_iter_t>::value_type value_t;
-
- for (distance_t len = end - begin; len > 1; --len) {
- detail::_remove_heap(begin, distance_t(0), len, std::less<value_t>(), detail::ignore_position_t());
- }
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t>
- void sort_heap(random_access_iter_t begin,
- random_access_iter_t end,
- pred_t pred) {
- typedef typename std::iterator_traits<random_access_iter_t>::difference_type distance_t;
-
- for (distance_t len = end - begin; len > 1; --len) {
- detail::_remove_heap(begin, distance_t(0), len, pred, detail::ignore_position_t());
- }
- }
-
-
-
- template<typename random_access_iter_t,
- typename pred_t,
- typename pos_notifier_t>
- void sort_heap(random_access_iter_t begin,
- random_access_iter_t end,
- pred_t pred,
- pos_notifier_t notify) {
- typedef typename std::iterator_traits<random_access_iter_t>::difference_type distance_t;
-
- for (distance_t len = end - begin; len > 1; --len) {
- detail::_remove_heap(begin, distance_t(0), len, pred, detail::ignore_position_t());
- notify(begin[len], len);
- }
- notify(begin[0], 0);
- }
-
-
-
- }
-}
diff --git a/extern/carve/include/carve/input.hpp b/extern/carve/include/carve/input.hpp
deleted file mode 100644
index cddf6456c05..00000000000
--- a/extern/carve/include/carve/input.hpp
+++ /dev/null
@@ -1,304 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <map>
-#include <string>
-
-#include <carve/carve.hpp>
-#include <carve/poly.hpp>
-#include <carve/mesh.hpp>
-#include <carve/polyline.hpp>
-#include <carve/pointset.hpp>
-
-
-
-namespace carve {
- namespace input {
-
- typedef std::map<std::string, std::string> Options;
-
- static inline Options opts() {
- return Options();
- }
-
- static inline Options opts(const char **kv) {
- Options r;
- for (size_t i = 0; kv[i] != NULL; i += 2) {
- r[kv[i]] = kv[i+1];
- }
- return r;
- }
-
- static inline Options opts(const std::string &k1, const std::string &v1) {
- Options r;
- r[k1] = v1;
- return r;
- }
-
- static inline Options opts(const std::string &k1, const std::string &v1,
- const std::string &k2, const std::string &v2) {
- Options r;
- r[k1] = v1;
- r[k2] = v2;
- return r;
- }
-
- static inline Options opts(const std::string &k1, const std::string &v1,
- const std::string &k2, const std::string &v2,
- const std::string &k3, const std::string &v3) {
- Options r;
- r[k1] = v1;
- r[k2] = v2;
- r[k3] = v3;
- return r;
- }
-
- static inline bool _bool(const std::string &str, bool _default = false) {
- if (str == "true") return true;
- if (str == "false") return false;
- return _default;
- }
-
- struct Data {
- Data() {
- }
-
- virtual ~Data() {
- }
-
- virtual void transform(const carve::math::Matrix & /* transform */) {
- }
- };
-
-
-
- struct VertexData : public Data {
- std::vector<carve::geom3d::Vector> points;
-
- VertexData() : Data() {
- }
-
- virtual ~VertexData() {
- }
-
- virtual void transform(const carve::math::Matrix &transform) {
- for (size_t i = 0; i < points.size(); ++i) {
- points[i] *= transform;
- }
- }
-
- size_t addVertex(carve::geom3d::Vector point) {
- size_t index = points.size();
- points.push_back(point);
- return index;
- }
-
- inline void reserveVertices(int count) {
- points.reserve(count);
- }
-
- size_t getVertexCount() const {
- return points.size();
- }
-
- const carve::geom3d::Vector &getVertex(int index) const {
- return points[index];
- }
- };
-
-
-
- struct PolyhedronData : public VertexData {
- std::vector<int> faceIndices;
- int faceCount;
-
- PolyhedronData() : VertexData(), faceIndices(), faceCount(0) {
- }
-
- virtual ~PolyhedronData() {
- }
-
- void reserveFaces(int count, int avgFaceSize) {
- faceIndices.reserve(faceIndices.size() + count * (1 + avgFaceSize));
- }
-
- int getFaceCount() const {
- return faceCount;
- }
-
- template <typename Iter>
- void addFace(Iter begin, Iter end) {
- size_t n = std::distance(begin, end);
- faceIndices.reserve(faceIndices.size() + n + 1);
- faceIndices.push_back(n);
- std::copy(begin, end, std::back_inserter(faceIndices));
- ++faceCount;
- }
-
- void addFace(int a, int b, int c) {
- faceIndices.push_back(3);
- faceIndices.push_back(a);
- faceIndices.push_back(b);
- faceIndices.push_back(c);
- ++faceCount;
- }
-
- void addFace(int a, int b, int c, int d) {
- faceIndices.push_back(4);
- faceIndices.push_back(a);
- faceIndices.push_back(b);
- faceIndices.push_back(c);
- faceIndices.push_back(d);
- ++faceCount;
- }
-
- void clearFaces() {
- faceIndices.clear();
- faceCount = 0;
- }
-
- carve::poly::Polyhedron *create(const Options &options) const {
- return new carve::poly::Polyhedron(points, faceCount, faceIndices);
- }
-
- carve::mesh::MeshSet<3> *createMesh(const Options &options) const {
- Options::const_iterator i;
- carve::mesh::MeshOptions opts;
- i = options.find("avoid_cavities");
- if (i != options.end()) {
- opts.avoid_cavities(_bool((*i).second));
- }
- return new carve::mesh::MeshSet<3>(points, faceCount, faceIndices, opts);
- }
- };
-
-
-
- struct PolylineSetData : public VertexData {
- typedef std::pair<bool, std::vector<int> > polyline_data_t;
- std::list<polyline_data_t> polylines;
-
- PolylineSetData() : VertexData(), polylines() {
- }
-
- virtual ~PolylineSetData() {
- }
-
- void beginPolyline(bool closed = false) {
- polylines.push_back(std::make_pair(closed, std::vector<int>()));
- }
-
- void reservePolyline(size_t len) {
- polylines.back().second.reserve(len);
- }
-
- void addPolylineIndex(int idx) {
- polylines.back().second.push_back(idx);
- }
-
- carve::line::PolylineSet *create(const Options &options) const {
- carve::line::PolylineSet *p = new carve::line::PolylineSet(points);
-
- for (std::list<polyline_data_t>::const_iterator i = polylines.begin();
- i != polylines.end();
- ++i) {
- p->addPolyline((*i).first, (*i).second.begin(), (*i).second.end());
- }
- return p;
- }
- };
-
-
-
- struct PointSetData : public VertexData {
-
- PointSetData() : VertexData() {
- }
-
- virtual ~PointSetData() {
- }
-
- carve::point::PointSet *create(const Options &options) const {
- carve::point::PointSet *p = new carve::point::PointSet(points);
- return p;
- }
- };
-
-
-
- class Input {
- public:
- std::list<Data *> input;
-
- Input() {
- }
-
- ~Input() {
- for (std::list<Data *>::iterator i = input.begin(); i != input.end(); ++i) {
- delete (*i);
- }
- }
-
- void addDataBlock(Data *data) {
- input.push_back(data);
- }
-
- void transform(const carve::math::Matrix &transform) {
- if (transform == carve::math::Matrix::IDENT()) return;
- for (std::list<Data *>::iterator i = input.begin(); i != input.end(); ++i) {
- (*i)->transform(transform);
- }
- }
-
- template<typename T>
- static inline T *create(Data *d, const Options &options = Options()) {
- return NULL;
- }
- };
-
- template<>
- inline carve::mesh::MeshSet<3> *Input::create(Data *d, const Options &options) {
- PolyhedronData *p = dynamic_cast<PolyhedronData *>(d);
- if (p == NULL) return NULL;
- return p->createMesh(options);
- }
-
- template<>
- inline carve::poly::Polyhedron *Input::create(Data *d, const Options &options) {
- PolyhedronData *p = dynamic_cast<PolyhedronData *>(d);
- if (p == NULL) return NULL;
- return p->create(options);
- }
-
- template<>
- inline carve::line::PolylineSet *Input::create(Data *d, const Options &options) {
- PolylineSetData *p = dynamic_cast<PolylineSetData *>(d);
- if (p == NULL) return NULL;
- return p->create(options);
- }
-
- template<>
- inline carve::point::PointSet *Input::create(Data *d, const Options &options) {
- PointSetData *p = dynamic_cast<PointSetData *>(d);
- if (p == NULL) return NULL;
- return p->create(options);
- }
-
- }
-}
diff --git a/extern/carve/include/carve/interpolator.hpp b/extern/carve/include/carve/interpolator.hpp
deleted file mode 100644
index 23335ccbf38..00000000000
--- a/extern/carve/include/carve/interpolator.hpp
+++ /dev/null
@@ -1,513 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-#include <carve/geom2d.hpp>
-#include <carve/poly.hpp>
-#include <carve/mesh.hpp>
-#include <carve/csg.hpp>
-
-namespace carve {
- namespace interpolate {
-
- static inline std::vector<double> polyInterpolate(const std::vector<carve::geom2d::P2> &s,
- const carve::geom2d::P2 &v) {
- // see hormann et al. 2006
- const size_t SZ = s.size();
- std::vector<double> r;
- std::vector<double> A;
- std::vector<double> D;
-
- std::vector<double> result;
-
- r.resize(SZ);
- A.resize(SZ);
- D.resize(SZ);
-
- result.resize(SZ, 0.0);
-
- for (size_t i = 0; i < SZ; ++i) {
- size_t i2 = (i + 1) % SZ;
- carve::geom2d::P2 si = s[i] - v;
- carve::geom2d::P2 si2 = s[i2] - v;
-
- r[i] = sqrt(dot(si, si));
- A[i] = cross(si, si2) / 2.0;
- D[i] = dot(si, si2);
- if (fabs(r[i]) < 1e-16) {
- result[i] = 1.0;
- return result;
- } else if (fabs(A[i]) < 1e-16 && D[i] < 0.0) {
- double r2 = sqrt(dot(si2, si2));
- result[i2] = r[i] / (r[i] + r2);
- result[i] = r2 / (r[i] + r2);
- return result;
- }
- }
-
- double w_sum = 0.0;
-
- for (size_t i = 0; i < SZ; ++i) {
- size_t i_m = (i + SZ - 1) % SZ;
- size_t i_p = (i + 1) % SZ;
-
- double w = 0.0;
- if (fabs(A[i_m]) > 1e-16)
- w += (r[i_m] - D[i_m] / r[i]) / A[i_m];
- if (fabs(A[i]) > 1e-16)
- w += (r[i_p] - D[i] / r[i]) / A[i];
-
- result[i] = w;
- w_sum += w;
- }
-
- for (size_t i = 0; i < SZ; ++i) {
- result[i] /= w_sum;
- }
-
-// carve::geom2d::P2 test;
-// for (size_t i = 0; i < SZ; ++i) {
-// test = test + result[i] * s[i];
-// }
-
- return result;
- }
-
-
-
- template<typename iter_t,
- typename adapt_t,
- typename val_t,
- typename mod_t>
- val_t interp(iter_t begin,
- iter_t end,
- adapt_t adapt,
- const std::vector<val_t> &vals,
- double x,
- double y,
- mod_t mod = mod_t()) {
- std::vector<carve::geom2d::P2> s;
- s.reserve(std::distance(begin, end));
- std::transform(begin, end, std::back_inserter(s), adapt);
- std::vector<double> weight = polyInterpolate(s, carve::geom::VECTOR(x, y));
-
- val_t v;
- for (size_t z = 0; z < weight.size(); z++) {
- v += weight[z] * vals[z];
- }
-
- return mod(v);
- }
-
-
-
- template<typename iter_t,
- typename adapt_t,
- typename val_t>
- val_t interp(iter_t begin,
- iter_t end,
- adapt_t adapt,
- const std::vector<val_t> &vals,
- double x,
- double y) {
- return interp(begin, end, adapt, vals, x, y, identity_t<val_t>());
- }
-
-
-
- template<typename vertex_t,
- typename adapt_t,
- typename val_t,
- typename mod_t>
- val_t interp(const std::vector<vertex_t> &poly,
- adapt_t adapt,
- const std::vector<val_t> &vals,
- double x,
- double y,
- mod_t mod = mod_t()) {
- return interp(poly.begin(), poly.end(), adapt, vals, x, y, mod);
- }
-
-
-
- template<typename vertex_t,
- typename adapt_t,
- typename val_t>
- val_t interp(const std::vector<vertex_t> &poly,
- adapt_t adapt,
- const std::vector<val_t> &vals,
- double x,
- double y) {
- return interp(poly.begin(), poly.end(), adapt, vals, x, y, identity_t<val_t>());
- }
-
-
-
- template<typename val_t,
- typename mod_t>
- val_t interp(const std::vector<carve::geom2d::P2> &poly,
- const std::vector<val_t> &vals,
- double x,
- double y,
- mod_t mod = mod_t()) {
- std::vector<double> weight = polyInterpolate(poly, carve::geom::VECTOR(x, y));
-
- val_t v;
- for (size_t z = 0; z < weight.size(); z++) {
- v += weight[z] * vals[z];
- }
-
- return mod(v);
- }
-
-
-
- template<typename val_t>
- val_t interp(const std::vector<carve::geom2d::P2> &poly,
- const std::vector<val_t> &vals,
- double x,
- double y) {
- return interp(poly, vals, x, y, identity_t<val_t>());
- }
-
-
-
- class Interpolator {
- public:
- typedef carve::mesh::MeshSet<3> meshset_t;
-
- protected:
- friend struct Hook;
-
- struct Hook : public carve::csg::CSG::Hook {
- const carve::csg::CSG &csg;
- Interpolator *interpolator;
-
- virtual unsigned hookBits() const {
- return carve::csg::CSG::Hooks::RESULT_FACE_BIT;
- }
- virtual void resultFace(const meshset_t::face_t *new_face,
- const meshset_t::face_t *orig_face,
- bool flipped) {
- interpolator->resultFace(csg, new_face, orig_face, flipped);
- }
- virtual void processOutputFace(std::vector<carve::mesh::MeshSet<3>::face_t *> &new_faces,
- const meshset_t::face_t *orig_face,
- bool flipped) {
- interpolator->processOutputFace(csg, new_faces, orig_face, flipped);
- }
- virtual void edgeDivision(const meshset_t::edge_t *orig_edge,
- size_t orig_edge_idx,
- const meshset_t::vertex_t *v1,
- const meshset_t::vertex_t *v2) {
- interpolator->edgeDivision(csg, orig_edge, orig_edge_idx, v1, v2);
- }
-
- Hook(Interpolator *_interpolator, const carve::csg::CSG &_csg) : csg(_csg), interpolator(_interpolator) {
- }
-
- virtual ~Hook() {
- }
- };
-
- virtual Hook *makeHook(carve::csg::CSG &csg) {
- return new Hook(this, csg);
- }
-
- virtual void resultFace(const carve::csg::CSG &csg,
- const meshset_t::face_t *new_face,
- const meshset_t::face_t *orig_face,
- bool flipped) {
- }
-
- virtual void processOutputFace(const carve::csg::CSG &csg,
- std::vector<carve::mesh::MeshSet<3>::face_t *> &new_faces,
- const meshset_t::face_t *orig_face,
- bool flipped) {
- }
-
- virtual void edgeDivision(const carve::csg::CSG &csg,
- const meshset_t::edge_t *orig_edge,
- size_t orig_edge_idx,
- const meshset_t::vertex_t *v1,
- const meshset_t::vertex_t *v2) {
- }
-
- public:
-
- Interpolator() {
- }
-
- virtual ~Interpolator() {
- }
-
- void installHooks(carve::csg::CSG &csg) {
- Hook *hook = makeHook(csg);
- csg.hooks.registerHook(hook, hook->hookBits());
- }
- };
-
-
-
- template<typename attr_t>
- class FaceVertexAttr : public Interpolator {
- public:
- typedef std::pair<const meshset_t::face_t *, unsigned> key_t;
-
- protected:
- struct key_hash {
- size_t operator()(const key_t &v) const {
- return size_t(v.first) ^ size_t(v.second);
- }
- };
-
- typedef std::unordered_map<const meshset_t::vertex_t *, attr_t> attrvmap_t;
- typedef std::unordered_map<key_t, attr_t, key_hash> attrmap_t;
-
- attrmap_t attrs;
-
- virtual void resultFace(const carve::csg::CSG &csg,
- const meshset_t::face_t *new_face,
- const meshset_t::face_t *orig_face,
- bool flipped) {
- std::vector<attr_t> vertex_attrs;
- attrvmap_t base_attrs;
- vertex_attrs.reserve(orig_face->nVertices());
-
- for (meshset_t::face_t::const_edge_iter_t e = orig_face->begin(); e != orig_face->end(); ++e) {
- typename attrmap_t::const_iterator a = attrs.find(key_t(orig_face, e.idx()));
- if (a == attrs.end()) return;
- vertex_attrs.push_back((*a).second);
- base_attrs[e->vert] = vertex_attrs.back();
- }
-
- for (meshset_t::face_t::const_edge_iter_t e = new_face->begin(); e != new_face->end(); ++e) {
- const meshset_t::vertex_t *vertex = e->vert;
- typename attrvmap_t::const_iterator b = base_attrs.find(vertex);
- if (b != base_attrs.end()) {
- attrs[key_t(new_face, e.idx())] = (*b).second;
- } else {
- carve::geom2d::P2 p = orig_face->project(e->vert->v);
- attr_t attr = interp(orig_face->begin(),
- orig_face->end(),
- orig_face->projector(),
- vertex_attrs,
- p.x,
- p.y);
- attrs[key_t(new_face, e.idx())] = attr;
- }
- }
- }
-
- public:
- bool hasAttribute(const meshset_t::face_t *f, unsigned v) {
- return attrs.find(key_t(f, v)) != attrs.end();
- }
-
- attr_t getAttribute(const meshset_t::face_t *f, unsigned v, const attr_t &def = attr_t()) {
- typename attrmap_t::const_iterator fv = attrs.find(key_t(f, v));
- if (fv != attrs.end()) {
- return (*fv).second;
- }
- return def;
- }
-
- void setAttribute(const meshset_t::face_t *f, unsigned v, const attr_t &attr) {
- attrs[key_t(f, v)] = attr;
- }
-
- FaceVertexAttr() : Interpolator() {
- }
-
- virtual ~FaceVertexAttr() {
- }
-
- };
-
-
-
- template<typename attr_t>
- class FaceEdgeAttr : public Interpolator {
- public:
- typedef std::pair<const meshset_t::face_t *, unsigned> key_t;
-
- protected:
- typedef std::pair<const meshset_t::vertex_t *, const meshset_t::vertex_t *> vpair_t;
-
- struct key_hash {
- size_t operator()(const key_t &v) const {
- return size_t(v.first) ^ size_t(v.second);
- }
- };
- struct vpair_hash {
- size_t operator()(const vpair_t &v) const {
- return size_t(v.first) ^ size_t(v.second);
- }
- };
-
- typedef std::unordered_map<key_t, attr_t, key_hash> attrmap_t;
- typedef std::unordered_map<vpair_t, key_t, vpair_hash> edgedivmap_t;
-
- attrmap_t attrs;
- edgedivmap_t edgediv;
-
- struct Hook : public Interpolator::Hook {
- public:
- virtual unsigned hookBits() const {
- return
- carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT |
- carve::csg::CSG::Hooks::EDGE_DIVISION_BIT;
- }
- Hook(Interpolator *_interpolator, const carve::csg::CSG &_csg) : Interpolator::Hook(_interpolator, _csg) {
- }
- virtual ~Hook() {
- }
- };
-
- virtual Interpolator::Hook *makeHook(carve::csg::CSG &csg) {
- return new Hook(this, csg);
- }
-
- virtual void edgeDivision(const carve::csg::CSG &csg,
- const meshset_t::edge_t *orig_edge,
- size_t orig_edge_idx,
- const meshset_t::vertex_t *v1,
- const meshset_t::vertex_t *v2) {
- key_t k(orig_edge->face, orig_edge_idx);
- typename attrmap_t::const_iterator attr_i = attrs.find(k);
- if (attr_i == attrs.end()) return;
- edgediv[vpair_t(v1, v2)] = k;
- }
-
- virtual void processOutputFace(const carve::csg::CSG &csg,
- std::vector<carve::mesh::MeshSet<3>::face_t *> &new_faces,
- const meshset_t::face_t *orig_face,
- bool flipped) {
- edgedivmap_t undiv;
-
- for (meshset_t::face_t::const_edge_iter_t e = orig_face->begin(); e != orig_face->end(); ++e) {
- key_t k(orig_face, e.idx());
- typename attrmap_t::const_iterator attr_i = attrs.find(k);
- if (attr_i == attrs.end()) {
- continue;
- } else {
- undiv[vpair_t(e->v1(), e->v2())] = k;
- }
- }
-
- for (size_t fnum = 0; fnum < new_faces.size(); ++fnum) {
- const carve::mesh::MeshSet<3>::face_t *new_face = new_faces[fnum];
- for (meshset_t::face_t::const_edge_iter_t e = new_face->begin(); e != new_face->end(); ++e) {
- key_t k(new_face, e.idx());
-
- vpair_t vp;
- if (!flipped) {
- vp = vpair_t(e->v1(), e->v2());
- } else {
- vp = vpair_t(e->v2(), e->v1());
- }
- typename edgedivmap_t::const_iterator vp_i;
- if ((vp_i = undiv.find(vp)) != undiv.end()) {
- attrs[k] = attrs[vp_i->second];
- } else if ((vp_i = edgediv.find(vp)) != edgediv.end()) {
- attrs[k] = attrs[vp_i->second];
- }
- }
- }
- }
-
- public:
-
- bool hasAttribute(const meshset_t::face_t *f, unsigned e) {
- return attrs.find(std::make_pair(f, e)) != attrs.end();
- }
-
- attr_t getAttribute(const meshset_t::face_t *f, unsigned e, const attr_t &def = attr_t()) {
- typename attrmap_t::const_iterator fv = attrs.find(std::make_pair(f, e));
- if (fv != attrs.end()) {
- return (*fv).second;
- }
- return def;
- }
-
- void setAttribute(const meshset_t::face_t *f, unsigned e, const attr_t &attr) {
- attrs[std::make_pair(f, e)] = attr;
- }
-
- FaceEdgeAttr() : Interpolator() {
- }
-
- virtual ~FaceEdgeAttr() {
- }
- };
-
-
-
- template<typename attr_t>
- class FaceAttr : public Interpolator {
- public:
- typedef const meshset_t::face_t *key_t;
-
- protected:
- struct key_hash {
- size_t operator()(const key_t &f) const {
- return size_t(f);
- }
- };
-
- typedef std::unordered_map<key_t, attr_t, key_hash> attrmap_t;
-
- attrmap_t attrs;
-
- virtual void resultFace(const carve::csg::CSG &csg,
- const meshset_t::face_t *new_face,
- const meshset_t::face_t *orig_face,
- bool flipped) {
- typename attrmap_t::const_iterator i = attrs.find(key_t(orig_face));
- if (i != attrs.end()) {
- attrs[key_t(new_face)] = (*i).second;
- }
- }
-
- public:
- bool hasAttribute(const meshset_t::face_t *f) {
- return attrs.find(key_t(f)) != attrs.end();
- }
-
- attr_t getAttribute(const meshset_t::face_t *f, const attr_t &def = attr_t()) {
- typename attrmap_t::const_iterator i = attrs.find(key_t(f));
- if (i != attrs.end()) {
- return (*i).second;
- }
- return def;
- }
-
- void setAttribute(const meshset_t::face_t *f, const attr_t &attr) {
- attrs[key_t(f)] = attr;
- }
-
- FaceAttr() : Interpolator() {
- }
-
- virtual ~FaceAttr() {
- }
- };
-
- }
-}
diff --git a/extern/carve/include/carve/intersection.hpp b/extern/carve/include/carve/intersection.hpp
deleted file mode 100644
index af1bc829291..00000000000
--- a/extern/carve/include/carve/intersection.hpp
+++ /dev/null
@@ -1,267 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-#include <carve/collection_types.hpp>
-#include <carve/iobj.hpp>
-
-namespace carve {
- namespace csg {
-
- /**
- * \class Intersections
- * \brief Storage for computed intersections between vertices, edges and faces.
- *
- */
- struct Intersections : public std::unordered_map<IObj, IObjVMapSmall, IObj_hash> {
- typedef carve::mesh::MeshSet<3>::vertex_t vertex_t;
- typedef carve::mesh::MeshSet<3>::edge_t edge_t;
- typedef carve::mesh::MeshSet<3>::face_t face_t;
-
- typedef std::unordered_map<IObj, IObjVMapSmall, IObj_hash> super;
-
- ~Intersections() {
- }
-
- /**
- * \brief Record the position of intersection between a pair of intersection objects.
- *
- * @param a The first intersecting object.
- * @param b The second intersecting object.
- * @param p The point of intersection.
- */
- void record(IObj a, IObj b, vertex_t *p) {
- if (a > b) std::swap(a, b);
- (*this)[a][b] = p;
- (*this)[b][a] = p;
- }
-
- /**
- * \brief Test whether vertex \a v intersects face \a f.
- *
- * @param v The vertex to test.
- * @param f The face to test.
- *
- * @return true, if \a v intersects \a f.
- */
- bool intersectsFace(vertex_t *v, face_t *f) const;
-
- /**
- * \brief Collect sets of vertices, edges and faces that intersect \a obj
- *
- * @param[in] obj The intersection object to search for intersections.
- * @param[out] collect_v A vector of vertices intersecting \a obj.
- * @param[out] collect_e A vector of edges intersecting \a obj.
- * @param[out] collect_f A vector of faces intersecting \a obj.
- */
- void collect(const IObj &obj,
- std::vector<vertex_t *> *collect_v,
- std::vector<edge_t *> *collect_e,
- std::vector<face_t *> *collect_f) const;
-
-
- /**
- * \brief Determine whether two intersection objects intersect.
- *
- * @param a The first intersection object.
- * @param b The second intersection object.
- *
- * @return true, if \a a and \a b intersect.
- */
- bool intersectsExactly(const IObj &a, const IObj &b) {
- Intersections::const_iterator i = find(a);
- if (i == end()) return false;
- return i->second.find(b) != i->second.end();
- }
-
- /**
- * \brief Determine whether an intersection object intersects a vertex.
- *
- * @param a The intersection object.
- * @param v The vertex.
- *
- * @return true, if \a a and \a v intersect.
- */
- bool intersects(const IObj &a, vertex_t *v) {
- Intersections::const_iterator i = find(a);
- if (i == end()) return false;
- if (i->second.find(v) != i->second.end()) return true;
- return false;
- }
-
- /**
- * \brief Determine whether an intersection object intersects an edge.
- *
- * @param a The intersection object.
- * @param e The edge.
- *
- * @return true, if \a a and \a e intersect (either on the edge,
- * or at either endpoint).
- */
- bool intersects(const IObj &a, edge_t *e) {
- Intersections::const_iterator i = find(a);
- if (i == end()) return false;
- for (super::data_type::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
- const IObj &obj = j->first;
- switch (obj.obtype) {
- case IObj::OBTYPE_VERTEX:
- if (obj.vertex == e->v1() || obj.vertex == e->v2()) return true;
- break;
- case IObj::OBTYPE_EDGE:
- if (obj.edge == e) return true;
- break;
- default:
- break;
- }
- }
- return false;
- }
-
- /**
- * \brief Determine whether an intersection object intersects a face.
- *
- * @param a The intersection object.
- * @param f The face.
- *
- * @return true, if \a a and \a f intersect (either on the face,
- * or at any associated edge or vertex).
- */
- bool intersects(const IObj &a, face_t *f) {
- Intersections::const_iterator i = find(a);
- if (i == end()) return false;
- if (i->second.find(f) != i->second.end()) return true;
- edge_t *e = f->edge;
- do {
- if (i->second.find(e) != i->second.end()) return true;
- if (i->second.find(e->vert) != i->second.end()) return true;
- e = e->next;
- } while (e != f->edge);
- return false;
- }
-
- /**
- * \brief Determine whether an edge intersects another edge.
- *
- * @param e The edge.
- * @param f The face.
- *
- * @return true, if \a e and \a f intersect.
- */
- bool intersects(edge_t *e1, edge_t *e2) {
- if (intersects(e1->v1(), e2) || intersects(e1->v2(), e2) || intersects(IObj(e1), e2)) return true;
- return false;
- }
-
- /**
- * \brief Determine whether an edge intersects a face.
- *
- * @param e The edge.
- * @param f The face.
- *
- * @return true, if \a e and \a f intersect.
- */
- bool intersects(edge_t *e, face_t *f) {
- if (intersects(e->v1(), f) || intersects(e->v2(), f) || intersects(IObj(e), f)) return true;
- return false;
- }
-
- /**
- * \brief Determine the faces intersected by an edge.
- *
- * @tparam face_set_t A collection type holding face_t *
- * @param[in] e The edge.
- * @param[out] f The resulting set of faces.
- */
- template<typename face_set_t>
- void intersectedFaces(edge_t *e, face_set_t &f) const {
- std::vector<face_t *> intersected_faces;
- std::vector<edge_t *> intersected_edges;
- std::vector<vertex_t *> intersected_vertices;
-
- collect(e, &intersected_vertices, &intersected_edges, &intersected_faces);
-
- for (unsigned i = 0; i < intersected_vertices.size(); ++i) {
- facesForVertex(intersected_vertices[i], f);
- }
- for (unsigned i = 0; i < intersected_edges.size(); ++i) {
- facesForEdge(intersected_edges[i], f);
- }
- f.insert(intersected_faces.begin(), intersected_faces.end());
- }
-
- /**
- * \brief Determine the faces intersected by a vertex.
- *
- * @tparam face_set_t A collection type holding face_t *
- * @param[in] v The vertex.
- * @param[out] f The resulting set of faces.
- */
- template<typename face_set_t>
- void intersectedFaces(vertex_t *v, face_set_t &f) const {
- std::vector<face_t *> intersected_faces;
- std::vector<edge_t *> intersected_edges;
- std::vector<vertex_t *> intersected_vertices;
-
- collect(v, &intersected_vertices, &intersected_edges, &intersected_faces);
-
- for (unsigned i = 0; i < intersected_vertices.size(); ++i) {
- facesForVertex(intersected_vertices[i], f);
- }
- for (unsigned i = 0; i < intersected_edges.size(); ++i) {
- facesForEdge(intersected_edges[i], f);
- }
- f.insert(intersected_faces.begin(), intersected_faces.end());
- }
-
- /**
- * \brief Collect the set of faces that contain all vertices in \a verts.
- *
- * @tparam vertex_set_t A collection type holding vertex_t *
- * @tparam face_set_t A collection type holding face_t *
- * @param[in] verts A set of vertices.
- * @param[out] result The resulting set of faces.
- */
- template<typename vertex_set_t, typename face_set_t>
- void commonFaces(const vertex_set_t &verts, face_set_t &result) {
-
- std::set<face_t *> ifaces, temp, out;
- typename vertex_set_t::const_iterator i = verts.begin();
- if (i == verts.end()) return;
- intersectedFaces((*i), ifaces);
- while (++i != verts.end()) {
- temp.clear();
- intersectedFaces((*i), temp);
-
- out.clear();
- std::set_intersection(temp.begin(), temp.end(),
- ifaces.begin(), ifaces.end(),
- set_inserter(out));
- ifaces.swap(out);
- }
- std::copy(ifaces.begin(), ifaces.end(), set_inserter(result));
- }
-
- void clear() {
- super::clear();
- }
-
- };
-
- }
-}
diff --git a/extern/carve/include/carve/iobj.hpp b/extern/carve/include/carve/iobj.hpp
deleted file mode 100644
index 8fcb1c9506a..00000000000
--- a/extern/carve/include/carve/iobj.hpp
+++ /dev/null
@@ -1,106 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-namespace carve {
- namespace csg {
- struct IObj {
- enum {
- OBTYPE_NONE = 0,
- OBTYPE_VERTEX = 1,
- OBTYPE_EDGE = 2,
- OBTYPE_FACE = 4
- } obtype;
-
- union {
- carve::mesh::MeshSet<3>::vertex_t *vertex;
- carve::mesh::MeshSet<3>::edge_t *edge;
- carve::mesh::MeshSet<3>::face_t *face;
- intptr_t val;
- };
-
- IObj() : obtype(OBTYPE_NONE), val(0) { }
- IObj(carve::mesh::MeshSet<3>::vertex_t *v) : obtype(OBTYPE_VERTEX), vertex(v) { }
- IObj(carve::mesh::MeshSet<3>::edge_t *e) : obtype(OBTYPE_EDGE), edge(e) { }
- IObj(carve::mesh::MeshSet<3>::face_t *f) : obtype(OBTYPE_FACE), face(f) { }
- char typeChar() const { return "NVExF"[obtype]; }
- };
-
-
-
- struct IObj_hash {
- inline size_t operator()(const IObj &i) const {
- return (size_t)i.val;
- }
- inline size_t operator()(const std::pair<const IObj, const IObj> &i) const {
- return (size_t)i.first.val ^ (size_t)i.second.val;
- }
- };
-
-
-
- typedef std::unordered_set<std::pair<const IObj, const IObj>, IObj_hash> IObjPairSet;
-
- typedef std::unordered_map<IObj, carve::mesh::MeshSet<3>::vertex_t *, IObj_hash> IObjVMap;
- typedef std::map<IObj, carve::mesh::MeshSet<3>::vertex_t *> IObjVMapSmall;
-
- class VertexIntersections :
- public std::unordered_map<carve::mesh::MeshSet<3>::vertex_t *, IObjPairSet> {
- };
-
-
-
- static inline bool operator==(const carve::csg::IObj &a, const carve::csg::IObj &b) {
- return a.obtype == b.obtype && a.val == b.val;
- }
-
- static inline bool operator!=(const carve::csg::IObj &a, const carve::csg::IObj &b) {
- return a.obtype != b.obtype || a.val != b.val;
- }
-
- static inline bool operator<(const carve::csg::IObj &a, const carve::csg::IObj &b) {
- return a.obtype < b.obtype || (a.obtype == b.obtype && a.val < b.val);
- }
-
- static inline bool operator<=(const carve::csg::IObj &a, const carve::csg::IObj &b) {
- return a.obtype < b.obtype || (a.obtype == b.obtype && a.val <= b.val);
- }
-
- static inline bool operator>(const carve::csg::IObj &a, const carve::csg::IObj &b) {
- return a.obtype > b.obtype || (a.obtype == b.obtype && a.val > b.val);
- }
-
- static inline bool operator>=(const carve::csg::IObj &a, const carve::csg::IObj &b) {
- return a.obtype > b.obtype || (a.obtype == b.obtype && a.val >= b.val);
- }
-
- static inline std::ostream &operator<<(std::ostream &o, const carve::csg::IObj &a) {
- switch (a.obtype) {
- case carve::csg::IObj::OBTYPE_NONE: o << "NONE{}"; break;
- case carve::csg::IObj::OBTYPE_VERTEX: o << "VERT{" << a.vertex << "}"; break;
- case carve::csg::IObj::OBTYPE_EDGE: o << "EDGE{" << a.edge << "}"; break;
- case carve::csg::IObj::OBTYPE_FACE: o << "FACE{" << a.face << "}"; break;
- }
- return o;
- }
-
- }
-}
-
diff --git a/extern/carve/include/carve/kd_node.hpp b/extern/carve/include/carve/kd_node.hpp
deleted file mode 100644
index a05a844e41f..00000000000
--- a/extern/carve/include/carve/kd_node.hpp
+++ /dev/null
@@ -1,308 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-#include <carve/geom.hpp>
-#include <carve/aabb.hpp>
-
-#include <queue>
-#include <list>
-#include <limits>
-
-namespace carve {
- namespace geom {
- template<unsigned ndim,
- typename data_t,
- typename inserter_t,
- typename aabb_calc_t>
- class kd_node {
- kd_node(const kd_node &);
- kd_node &operator=(const kd_node &);
-
- public:
- kd_node *c_neg;
- kd_node *c_pos;
- kd_node *parent;
- axis_pos splitpos;
-
- typedef vector<ndim> vector_t;
- typedef std::list<data_t> container_t;
-
- container_t data;
-
- kd_node(kd_node *_parent = NULL) : c_neg(NULL), c_pos(NULL), parent(_parent), splitpos(0, 0.0) {
- }
-
- ~kd_node() {
- if (c_neg) delete c_neg;
- if (c_pos) delete c_pos;
- }
-
- template<typename visitor_t>
- void closeNodes(const vector_t &p, double d, visitor_t &visit) const {
- if (c_neg) {
- double delta = splitpos.pos - p[splitpos.axis];
- if (delta <= d) c_neg->closeNodes(p, d, visit);
- if (delta >= -d) c_pos->closeNodes(p, d, visit);
- } else {
- visit(this);
- }
- }
-
- void removeData(const data_t &d) {
- typename container_t::iterator i = std::find(data.begin(), data.end(), d);
-
- if (i != data.end()) {
- data.erase(i);
- }
- }
-
- void addData(const data_t &d) {
- data.push_back(d);
- }
-
- void insert(const data_t &data, inserter_t &inserter) {
- inserter.insert(this, data);
- }
-
- void insert(const data_t &data) {
- inserter_t inserter;
- insert(data, inserter);
- }
-
- void remove(const data_t &data, inserter_t &inserter) {
- inserter.remove(this, data);
- }
-
- void remove(const data_t &data) {
- inserter_t inserter;
- remove(data, inserter);
- }
-
- carve::geom::aabb<ndim> nodeAABB() const {
- carve::geom::aabb<ndim> aabb;
- if (c_neg) {
- aabb = c_neg->nodeAABB();
- aabb.unionAABB(c_pos->nodeAABB());
- } else {
- if (data.size()) {
- typename container_t::const_iterator i = data.begin();
- aabb = aabb_calc_t()(*i);
- while (i != data.end()) {
- aabb.unionAABB(aabb_calc_t()(*i));
- ++i;
- }
- }
- }
- return aabb;
- }
-
- bool split(axis_pos split_at, inserter_t &inserter) {
- if (c_neg) {
- // already split
- return false;
- }
-
- c_neg = new kd_node(this);
- c_pos = new kd_node(this);
-
- // choose an axis and split point.
- splitpos = split_at;
-
- carve::geom::aabb<ndim> aabb;
-
- if (splitpos.axis < 0 ||
- splitpos.axis >= ndim ||
- splitpos.pos == std::numeric_limits<double>::max()) {
- // need an aabb
- if (data.size()) {
- typename container_t::const_iterator i = data.begin();
- aabb = aabb_calc_t()(*i);
- while (i != data.end()) {
- aabb.unionAABB(aabb_calc_t()(*i));
- ++i;
- }
- }
- }
-
- if (splitpos.axis < 0 || splitpos.axis >= ndim) {
-
- // choose an axis;
-
- // if no axis was specified, force calculation of the split position.
- splitpos.pos = std::numeric_limits<double>::max();
-
- // choose the axis of the AABB with the biggest extent.
- splitpos.axis = largestAxis(aabb.extent);
-
- if (parent && splitpos.axis == parent->splitpos.axis) {
- // but don't choose the same axis as the parent node;
- // choose the axis with the second greatest AABB extent.
- double e = -1.0;
- int a = -1;
- for (int i = 0; i < ndim; ++i) {
- if (i == splitpos.axis) continue;
- if (e < aabb.extent[i]) { a = i; e = aabb.extent[i]; }
- }
- if (a != -1) {
- splitpos.axis = a;
- }
- }
- }
-
- if (splitpos.pos == std::numeric_limits<double>::max()) {
- carve::geom::vector<ndim> min = aabb.min();
- carve::geom::vector<ndim> max = aabb.max();
- splitpos.pos = aabb.pos.v[splitpos.axis];
- }
-
- inserter.propagate(this);
-
- return true;
- }
-
- bool split(axis_pos split_at = axis_pos(-1, std::numeric_limits<double>::max())) {
- inserter_t inserter;
- return split(split_at, inserter);
- }
-
- void splitn(int num, inserter_t &inserter) {
- if (num <= 0) return;
- if (!c_neg) {
- split(inserter);
- }
- if (c_pos) c_pos->splitn(num-1, inserter);
- if (c_neg) c_neg->splitn(num-1, inserter);
- }
-
- void splitn(int num) {
- inserter_t inserter;
- splitn(num, inserter);
- }
-
- template<typename split_t>
- void splitn(int num, split_t splitter, inserter_t &inserter) {
- if (num <= 0) return;
- if (!c_neg) {
- split(inserter, splitter(this));
- }
- if (c_pos) c_pos->splitn(num-1, inserter, splitter);
- if (c_neg) c_neg->splitn(num-1, inserter, splitter);
- }
-
- template<typename split_t>
- void splitn(int num, split_t splitter) {
- inserter_t inserter;
- splitn(num, splitter, inserter);
- }
-
- template<typename pred_t>
- void splitpred(pred_t pred, inserter_t &inserter, int depth = 0) {
- if (!c_neg) {
- axis_pos splitpos(-1, std::numeric_limits<double>::max());
- if (!pred(this, depth, splitpos)) return;
- split(splitpos, inserter);
- }
- if (c_pos) c_pos->splitpred(pred, inserter, depth + 1);
- if (c_neg) c_neg->splitpred(pred, inserter, depth + 1);
- }
-
- template<typename pred_t>
- void splitpred(pred_t pred, int depth = 0) {
- inserter_t inserter;
- splitpred(pred, inserter, depth);
- }
-
- // distance_t must provide:
- // double operator()(data_t, vector<ndim>);
- // double operator()(axis_pos, vector<ndim>);
- template<typename distance_t>
- struct near_point_query {
-
- // q_t - the priority queue value type.
- // q_t.first: distance from object to query point.
- // q_t.second: pointer to object
- typedef std::pair<double, const data_t *> q_t;
-
- // the queue priority should sort from smallest distance to largest, and on equal distance, by object pointer.
- struct pcmp {
- bool operator()(const q_t &a, const q_t &b) {
- return (a.first > b.first) || ((a.first == b.first) && (a.second < b.second));
- }
- };
-
- vector<ndim> point;
- const kd_node *node;
- std::priority_queue<q_t, std::vector<q_t>, pcmp> pq;
-
- distance_t dist;
- double dist_to_parent_split;
-
- void addToPQ(kd_node *node) {
- if (node->c_neg) {
- addToPQ(node->c_neg);
- addToPQ(node->c_pos);
- } else {
- for (typename kd_node::container_t::const_iterator i = node->data.begin(); i != node->data.end(); ++i) {
- double d = dist((*i), point);
- pq.push(std::make_pair(d, &(*i)));
- }
- }
- }
-
- const data_t *next() {
- while (1) {
- if (pq.size()) {
- q_t t = pq.top();
- if (!node->parent || t.first < dist_to_parent_split) {
- pq.pop();
- return t.second;
- }
- }
-
- if (!node->parent) return NULL;
-
- if (node->parent->c_neg == node) {
- addToPQ(node->parent->c_pos);
- } else {
- addToPQ(node->parent->c_neg);
- }
-
- node = node->parent;
- dist_to_parent_split = dist(node->splitpos, point);
- }
- }
-
- near_point_query(const vector<ndim> _point, const kd_node *_node) : point(_point), node(_node), pq(), dist() {
- while (node->c_neg) {
- node = (point[node->axis] < node->pos) ? node->c_neg : node->c_pos;
- }
- if (node->parent) {
- dist_to_parent_split = dist(node->parent->splitpos, point);
- } else {
- dist_to_parent_split = HUGE_VAL;
- }
- addToPQ(node);
- }
- };
-
- };
-
- }
-}
diff --git a/extern/carve/include/carve/math.hpp b/extern/carve/include/carve/math.hpp
deleted file mode 100644
index 8b2913d8f3e..00000000000
--- a/extern/carve/include/carve/math.hpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/math_constants.hpp>
-
-#include <math.h>
-
-namespace carve {
- namespace geom {
- template<unsigned ndim> struct vector;
- }
-}
-
-namespace carve {
- namespace math {
- struct Matrix3;
- int cubic_roots(double c3, double c2, double c1, double c0, double *roots);
-
- void eigSolveSymmetric(const Matrix3 &m,
- double &l1, carve::geom::vector<3> &e1,
- double &l2, carve::geom::vector<3> &e2,
- double &l3, carve::geom::vector<3> &e3);
-
- void eigSolve(const Matrix3 &m, double &l1, double &l2, double &l3);
-
- static inline bool ZERO(double x) { return fabs(x) < carve::EPSILON; }
-
- static inline double radians(double deg) { return deg * M_PI / 180.0; }
- static inline double degrees(double rad) { return rad * 180.0 / M_PI; }
-
- static inline double ANG(double x) {
- return (x < 0) ? x + M_TWOPI : x;
- }
-
- template<typename T>
- static inline const T &clamp(const T &val, const T &min, const T &max) {
- if (val < min) return min;
- if (val > max) return max;
- return val;
- }
- }
-}
diff --git a/extern/carve/include/carve/math_constants.hpp b/extern/carve/include/carve/math_constants.hpp
deleted file mode 100644
index 427616ba051..00000000000
--- a/extern/carve/include/carve/math_constants.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <math.h>
-
-#ifndef M_SQRT_3
-#define M_SQRT_3 1.73205080756887729352
-#endif
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#ifndef M_TWOPI
-#define M_TWOPI (M_PI + M_PI)
-#endif
-
diff --git a/extern/carve/include/carve/matrix.hpp b/extern/carve/include/carve/matrix.hpp
deleted file mode 100644
index b8f4743facb..00000000000
--- a/extern/carve/include/carve/matrix.hpp
+++ /dev/null
@@ -1,262 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <cstring>
-
-#include <carve/carve.hpp>
-
-#include <carve/math.hpp>
-#include <carve/geom.hpp>
-
-namespace carve {
- namespace math {
-
- struct Quaternion {
- double x, y, z, w;
-
- Quaternion(double _x, double _y, double _z, double _w) : x(_x), y(_y), z(_z), w(_w) {
- }
-
- Quaternion(double angle, const carve::geom::vector<3> &axis) {
- double s = axis.length();
- if (!carve::math::ZERO(s)) {
- double c = 1.0 / s;
- double omega = -0.5 * angle;
- s = sin(omega);
- x = axis.x * c * s;
- y = axis.y * c * s;
- z = axis.z * c * s;
- w = cos(omega);
- normalize();
- } else {
- x = y = z = 0.0;
- w = 1.0;
- }
- }
-
- double lengthSquared() const {
- return x * x + y * y + z * z + w * w;
- }
-
- double length() const {
- return sqrt(lengthSquared());
- }
-
- Quaternion normalized() const {
- return Quaternion(*this).normalize();
- }
-
- Quaternion &normalize() {
- double l = length();
- if (l == 0.0) {
- x = 1.0; y = 0.0; z = 0.0; w = 0.0;
- } else {
- x /= l; y /= l; z /= l; w /= l;
- }
- return *this;
- }
- };
-
- struct Matrix3 {
- // access: .m[col][row], .v[col * 4 + row], ._cr
- union {
- double m[3][3];
- double v[9];
- struct {
- // transposed
- double _11, _12, _13;
- double _21, _22, _23;
- double _31, _32, _33;
- };
- };
- Matrix3(double __11, double __21, double __31,
- double __12, double __22, double __32,
- double __13, double __23, double __33) {
- // nb, args are row major, storage is column major.
- _11 = __11; _12 = __12; _13 = __13;
- _21 = __21; _22 = __22; _23 = __23;
- _31 = __31; _32 = __32; _33 = __33;
- }
- Matrix3(double _m[3][3]) {
- std::memcpy(m, _m, sizeof(m));
- }
- Matrix3(double _v[9]) {
- std::memcpy(v, _v, sizeof(v));
- }
- Matrix3() {
- _11 = 1.00; _12 = 0.00; _13 = 0.00;
- _21 = 0.00; _22 = 1.00; _23 = 0.00;
- _31 = 0.00; _32 = 0.00; _33 = 1.00;
- }
- };
-
- struct Matrix {
- // access: .m[col][row], .v[col * 4 + row], ._cr
- union {
- double m[4][4];
- double v[16];
- struct {
- // transposed
- double _11, _12, _13, _14;
- double _21, _22, _23, _24;
- double _31, _32, _33, _34;
- double _41, _42 ,_43, _44;
- };
- };
- Matrix(double __11, double __21, double __31, double __41,
- double __12, double __22, double __32, double __42,
- double __13, double __23, double __33, double __43,
- double __14, double __24, double __34, double __44) {
- // nb, args are row major, storage is column major.
- _11 = __11; _12 = __12; _13 = __13; _14 = __14;
- _21 = __21; _22 = __22; _23 = __23; _24 = __24;
- _31 = __31; _32 = __32; _33 = __33; _34 = __34;
- _41 = __41; _42 = __42; _43 = __43; _44 = __44;
- }
- Matrix(double _m[4][4]) {
- std::memcpy(m, _m, sizeof(m));
- }
- Matrix(double _v[16]) {
- std::memcpy(v, _v, sizeof(v));
- }
- Matrix() {
- _11 = 1.00; _12 = 0.00; _13 = 0.00; _14 = 0.00;
- _21 = 0.00; _22 = 1.00; _23 = 0.00; _24 = 0.00;
- _31 = 0.00; _32 = 0.00; _33 = 1.00; _34 = 0.00;
- _41 = 0.00; _42 = 0.00; _43 = 0.00; _44 = 1.00;
- }
-
- static Matrix ROT(const Quaternion &q) {
- const double w = q.w;
- const double x = q.x;
- const double y = q.y;
- const double z = q.z;
- return Matrix(1 - 2*y*y - 2*z*z, 2*x*y - 2*z*w, 2*x*z + 2*y*w, 0.0,
- 2*x*y + 2*z*w, 1 - 2*x*x - 2*z*z, 2*y*z - 2*x*w, 0.0,
- 2*x*z - 2*y*w, 2*y*z + 2*x*w, 1 - 2*x*x - 2*y*y, 0.0,
- 0.0, 0.0, 0.0, 1.0);
- }
- static Matrix ROT(double angle, const carve::geom::vector<3> &axis) {
- return ROT(Quaternion(angle, axis));
- }
- static Matrix ROT(double angle, double x, double y, double z) {
- return ROT(Quaternion(angle, carve::geom::VECTOR(x, y, z)));
- }
- static Matrix TRANS(double x, double y, double z) {
- return Matrix(1.0, 0.0, 0.0, x,
- 0.0, 1.0, 0.0, y,
- 0.0, 0.0, 1.0, z,
- 0.0, 0.0, 0.0, 1.0);
- }
- static Matrix TRANS(const carve::geom::vector<3> &v) {
- return TRANS(v.x, v.y, v.z);
- }
- static Matrix SCALE(double x, double y, double z) {
- return Matrix(x, 0.0, 0.0, 0.0,
- 0.0, y, 0.0, 0.0,
- 0.0, 0.0, z, 0.0,
- 0.0, 0.0, 0.0, 1.0);
- }
- static Matrix SCALE(const carve::geom::vector<3> &v) {
- return SCALE(v.x, v.y, v.z);
- }
- static Matrix IDENT() {
- return Matrix(1.0, 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0,
- 0.0, 0.0, 0.0, 1.0);
- }
- };
-
- static inline bool operator==(const Matrix &A, const Matrix &B) {
- for (size_t i = 0; i < 16; ++i) if (A.v[i] != B.v[i]) return false;
- return true;
- }
- static inline bool operator!=(const Matrix &A, const Matrix &B) {
- return !(A == B);
- }
- static inline carve::geom::vector<3> operator*(const Matrix &A, const carve::geom::vector<3> &b) {
- return carve::geom::VECTOR(
- A._11 * b.x + A._21 * b.y + A._31 * b.z + A._41,
- A._12 * b.x + A._22 * b.y + A._32 * b.z + A._42,
- A._13 * b.x + A._23 * b.y + A._33 * b.z + A._43
- );
- }
-
- static inline carve::geom::vector<3> &operator*=(carve::geom::vector<3> &b, const Matrix &A) {
- b = A * b;
- return b;
- }
-
- static inline carve::geom::vector<3> operator*(const Matrix3 &A, const carve::geom::vector<3> &b) {
- return carve::geom::VECTOR(
- A._11 * b.x + A._21 * b.y + A._31 * b.z,
- A._12 * b.x + A._22 * b.y + A._32 * b.z,
- A._13 * b.x + A._23 * b.y + A._33 * b.z
- );
- }
-
- static inline carve::geom::vector<3> &operator*=(carve::geom::vector<3> &b, const Matrix3 &A) {
- b = A * b;
- return b;
- }
-
- static inline Matrix operator*(const Matrix &A, const Matrix &B) {
- Matrix c;
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- c.m[i][j] = 0.0;
- for (int k = 0; k < 4; k++) {
- c.m[i][j] += A.m[k][j] * B.m[i][k];
- }
- }
- }
- return c;
- }
-
- static inline Matrix3 operator*(const Matrix3 &A, const Matrix3 &B) {
- Matrix3 c;
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- c.m[i][j] = 0.0;
- for (int k = 0; k < 3; k++) {
- c.m[i][j] += A.m[k][j] * B.m[i][k];
- }
- }
- }
- return c;
- }
-
-
-
- struct matrix_transformation {
- Matrix matrix;
-
- matrix_transformation(const Matrix &_matrix) : matrix(_matrix) {
- }
-
- carve::geom::vector<3> operator()(const carve::geom::vector<3> &vector) const {
- return matrix * vector;
- }
- };
-
-
-
- }
-}
diff --git a/extern/carve/include/carve/mesh.hpp b/extern/carve/include/carve/mesh.hpp
deleted file mode 100644
index eb9bdbd423a..00000000000
--- a/extern/carve/include/carve/mesh.hpp
+++ /dev/null
@@ -1,874 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/geom.hpp>
-#include <carve/geom3d.hpp>
-#include <carve/tag.hpp>
-#include <carve/djset.hpp>
-#include <carve/aabb.hpp>
-#include <carve/rtree.hpp>
-
-#include <iostream>
-
-namespace carve {
- namespace poly {
- class Polyhedron;
- }
-
- namespace mesh {
-
-
- template<unsigned ndim> class Edge;
- template<unsigned ndim> class Face;
- template<unsigned ndim> class Mesh;
- template<unsigned ndim> class MeshSet;
-
-
-
- // A Vertex may participate in several meshes. If the Mesh belongs
- // to a MeshSet, then the vertices come from the vertex_storage
- // member of the MeshSet. This allows one to construct one or more
- // Meshes out of sets of connected faces (possibly using vertices
- // from a variety of MeshSets, and other storage), then create a
- // MeshSet from the Mesh(es), causing the vertices to be
- // collected, cloned and repointed into the MeshSet.
-
- // Normally, in a half-edge structure, Vertex would have a member
- // pointing to an incident edge, allowing the enumeration of
- // adjacent faces and edges. Because we want to support vertex
- // sharing between Meshes and groups of Faces, this is made more
- // complex. If Vertex contained a list of incident edges, one from
- // each disjoint face set, then this could be done (with the
- // caveat that you'd need to pass in a Mesh pointer to the
- // adjacency queries). However, it seems that this would
- // unavoidably complicate the process of incorporating or removing
- // a vertex into an edge.
-
- // In most cases it is expected that a vertex will be arrived at
- // via an edge or face in the mesh (implicit or explicit) of
- // interest, so not storing this information will not hurt,
- // overly.
- template<unsigned ndim>
- class Vertex : public tagable {
- public:
- typedef carve::geom::vector<ndim> vector_t;
- typedef MeshSet<ndim> owner_t;
- typedef carve::geom::aabb<ndim> aabb_t;
-
- carve::geom::vector<ndim> v;
-
- Vertex(const vector_t &_v) : tagable(), v(_v) {
- }
-
- Vertex() : tagable(), v() {
- }
-
- aabb_t getAABB() const {
- return aabb_t(v, carve::geom::vector<ndim>::ZERO());
- }
- };
-
-
-
- struct hash_vertex_pair {
- template<unsigned ndim>
- size_t operator()(const std::pair<Vertex<ndim> *, Vertex<ndim> *> &pair) const {
- size_t r = (size_t)pair.first;
- size_t s = (size_t)pair.second;
- return r ^ ((s >> 16) | (s << 16));
- }
- template<unsigned ndim>
- size_t operator()(const std::pair<const Vertex<ndim> *, const Vertex<ndim> *> &pair) const {
- size_t r = (size_t)pair.first;
- size_t s = (size_t)pair.second;
- return r ^ ((s >> 16) | (s << 16));
- }
- };
-
-
-
- struct vertex_distance {
- template<unsigned ndim>
- double operator()(const Vertex<ndim> &a, const Vertex<ndim> &b) const {
- return carve::geom::distance(a.v, b.v);
- }
-
- template<unsigned ndim>
- double operator()(const Vertex<ndim> *a, const Vertex<ndim> *b) const {
- return carve::geom::distance(a->v, b->v);
- }
- };
-
-
-
- namespace detail {
- template<typename list_t> struct list_iter_t;
- template<typename list_t, typename mapping_t> struct mapped_list_iter_t;
- }
-
-
-
- // The half-edge structure proper (Edge) is maintained by Face
- // instances. Together with Face instances, the half-edge
- // structure defines a simple mesh (either one or two faces
- // incident on each edge).
- template<unsigned ndim>
- class Edge : public tagable {
- public:
- typedef Vertex<ndim> vertex_t;
- typedef Face<ndim> face_t;
-
- vertex_t *vert;
- face_t *face;
- Edge *prev, *next, *rev;
-
- private:
- static void _link(Edge *a, Edge *b) {
- a->next = b; b->prev = a;
- }
-
- static void _freeloop(Edge *s) {
- Edge *e = s;
- do {
- Edge *n = e->next;
- delete e;
- e = n;
- } while (e != s);
- }
-
- static void _setloopface(Edge *s, face_t *f) {
- Edge *e = s;
- do {
- e->face = f;
- e = e->next;
- } while (e != s);
- }
-
- static size_t _looplen(Edge *s) {
- Edge *e = s;
- face_t *f = s->face;
- size_t c = 0;
- do {
- ++c;
- CARVE_ASSERT(e->rev->rev == e);
- CARVE_ASSERT(e->next->prev == e);
- CARVE_ASSERT(e->face == f);
- e = e->next;
- } while (e != s);
- return c;
- }
-
- public:
- void validateLoop() {
- Edge *e = this;
- face_t *f = face;
- size_t c = 0;
- do {
- ++c;
- CARVE_ASSERT(e->rev == NULL || e->rev->rev == e);
- CARVE_ASSERT(e->next == e || e->next->vert != e->vert);
- CARVE_ASSERT(e->prev == e || e->prev->vert != e->vert);
- CARVE_ASSERT(e->next->prev == e);
- CARVE_ASSERT(e->prev->next == e);
- CARVE_ASSERT(e->face == f);
- e = e->next;
- } while (e != this);
- CARVE_ASSERT(f == NULL || c == f->n_edges);
- }
-
- size_t loopLen() {
- return _looplen(this);
- }
-
- Edge *mergeFaces();
-
- Edge *removeHalfEdge();
-
- // Remove and delete this edge.
- Edge *removeEdge();
-
- // Unlink this edge from its containing edge loop. disconnect
- // rev links. The rev links of the previous edge also change, as
- // its successor vertex changes.
- void unlink();
-
- // Insert this edge into a loop before other. If edge was
- // already in a loop, it needs to be removed first.
- void insertBefore(Edge *other);
-
- // Insert this edge into a loop after other. If edge was
- // already in a loop, it needs to be removed first.
- void insertAfter(Edge *other);
-
- size_t loopSize() const;
-
- vertex_t *v1() { return vert; }
- vertex_t *v2() { return next->vert; }
-
- const vertex_t *v1() const { return vert; }
- const vertex_t *v2() const { return next->vert; }
-
- Edge *perimNext() const;
- Edge *perimPrev() const;
-
- double length2() const {
- return (v1()->v - v2()->v).length2();
- }
-
- double length() const {
- return (v1()->v - v2()->v).length();
- }
-
- Edge(vertex_t *_vert, face_t *_face);
-
- ~Edge();
- };
-
-
-
- // A Face contains a pointer to the beginning of the half-edge
- // circular list that defines its boundary.
- template<unsigned ndim>
- class Face : public tagable {
- public:
- typedef Vertex<ndim> vertex_t;
- typedef Edge<ndim> edge_t;
- typedef Mesh<ndim> mesh_t;
-
- typedef typename Vertex<ndim>::vector_t vector_t;
- typedef carve::geom::aabb<ndim> aabb_t;
- typedef carve::geom::plane<ndim> plane_t;
- typedef carve::geom::vector<2> (*project_t)(const vector_t &);
- typedef vector_t (*unproject_t)(const carve::geom::vector<2> &, const plane_t &);
-
- struct vector_mapping {
- typedef typename vertex_t::vector_t value_type;
-
- value_type operator()(const carve::geom::vector<ndim> &v) const { return v; }
- value_type operator()(const carve::geom::vector<ndim> *v) const { return *v; }
- value_type operator()(const Edge<ndim> &e) const { return e.vert->v; }
- value_type operator()(const Edge<ndim> *e) const { return e->vert->v; }
- value_type operator()(const Vertex<ndim> &v) const { return v.v; }
- value_type operator()(const Vertex<ndim> *v) const { return v->v; }
- };
-
- struct projection_mapping {
- typedef carve::geom::vector<2> value_type;
- project_t proj;
- projection_mapping(project_t _proj) : proj(_proj) { }
- value_type operator()(const carve::geom::vector<ndim> &v) const { return proj(v); }
- value_type operator()(const carve::geom::vector<ndim> *v) const { return proj(*v); }
- value_type operator()(const Edge<ndim> &e) const { return proj(e.vert->v); }
- value_type operator()(const Edge<ndim> *e) const { return proj(e->vert->v); }
- value_type operator()(const Vertex<ndim> &v) const { return proj(v.v); }
- value_type operator()(const Vertex<ndim> *v) const { return proj(v->v); }
- };
-
- edge_t *edge;
- size_t n_edges;
- mesh_t *mesh;
- size_t id;
-
- plane_t plane;
- project_t project;
- unproject_t unproject;
-
- private:
- Face &operator=(const Face &other);
-
- protected:
- Face() : edge(NULL), n_edges(0), mesh(NULL), id(0), plane(), project(NULL), unproject(NULL) {
- }
-
- Face(const Face &other) :
- edge(NULL), n_edges(other.n_edges), mesh(NULL), id(other.id),
- plane(other.plane), project(other.project), unproject(other.unproject) {
- }
-
- project_t getProjector(bool positive_facing, int axis) const;
- unproject_t getUnprojector(bool positive_facing, int axis) const;
-
- public:
- typedef detail::list_iter_t<Edge<ndim> > edge_iter_t;
- typedef detail::list_iter_t<const Edge<ndim> > const_edge_iter_t;
-
- edge_iter_t begin() { return edge_iter_t(edge, 0); }
- edge_iter_t end() { return edge_iter_t(edge, n_edges); }
-
- const_edge_iter_t begin() const { return const_edge_iter_t(edge, 0); }
- const_edge_iter_t end() const { return const_edge_iter_t(edge, n_edges); }
-
- bool containsPoint(const vector_t &p) const;
- bool containsPointInProjection(const vector_t &p) const;
- bool simpleLineSegmentIntersection(
- const carve::geom::linesegment<ndim> &line,
- vector_t &intersection) const;
- IntersectionClass lineSegmentIntersection(
- const carve::geom::linesegment<ndim> &line,
- vector_t &intersection) const;
-
- aabb_t getAABB() const;
-
- bool recalc();
-
- void clearEdges();
-
- // build an edge loop in forward orientation from an iterator pair
- template<typename iter_t>
- void loopFwd(iter_t vbegin, iter_t vend);
-
- // build an edge loop in reverse orientation from an iterator pair
- template<typename iter_t>
- void loopRev(iter_t vbegin, iter_t vend);
-
- // initialize a face from an ordered list of vertices.
- template<typename iter_t>
- void init(iter_t begin, iter_t end);
-
- // initialization of a triangular face.
- void init(vertex_t *a, vertex_t *b, vertex_t *c);
-
- // initialization of a quad face.
- void init(vertex_t *a, vertex_t *b, vertex_t *c, vertex_t *d);
-
- void getVertices(std::vector<vertex_t *> &verts) const;
- void getProjectedVertices(std::vector<carve::geom::vector<2> > &verts) const;
-
- projection_mapping projector() const {
- return projection_mapping(project);
- }
-
- std::pair<double, double> rangeInDirection(const vector_t &v, const vector_t &b) const {
- edge_t *e = edge;
- double lo, hi;
- lo = hi = carve::geom::dot(v, e->vert->v - b);
- e = e->next;
- for (; e != edge; e = e->next) {
- double d = carve::geom::dot(v, e->vert->v - b);
- lo = std::min(lo, d);
- hi = std::max(hi, d);
- }
- return std::make_pair(lo, hi);
- }
-
- size_t nVertices() const {
- return n_edges;
- }
-
- size_t nEdges() const {
- return n_edges;
- }
-
- vector_t centroid() const;
-
- static Face *closeLoop(edge_t *open_edge);
-
- Face(edge_t *e) : edge(e), n_edges(0), mesh(NULL) {
- do {
- e->face = this;
- n_edges++;
- e = e->next;
- } while (e != edge);
- recalc();
- }
-
- Face(vertex_t *a, vertex_t *b, vertex_t *c) : edge(NULL), n_edges(0), mesh(NULL) {
- init(a, b, c);
- recalc();
- }
-
- Face(vertex_t *a, vertex_t *b, vertex_t *c, vertex_t *d) : edge(NULL), n_edges(0), mesh(NULL) {
- init(a, b, c, d);
- recalc();
- }
-
- template<typename iter_t>
- Face(iter_t begin, iter_t end) : edge(NULL), n_edges(0), mesh(NULL) {
- init(begin, end);
- recalc();
- }
-
- template<typename iter_t>
- Face *create(iter_t beg, iter_t end, bool reversed) const;
-
- Face *clone(const vertex_t *old_base, vertex_t *new_base, std::unordered_map<const edge_t *, edge_t *> &edge_map) const;
-
- void remove() {
- edge_t *e = edge;
- do {
- if (e->rev) e->rev->rev = NULL;
- e = e->next;
- } while (e != edge);
- }
-
- void invert() {
- // We invert the direction of the edges of the face in this
- // way so that the edge rev pointers (if any) are still
- // correct. It is expected that invert() will be called on
- // every other face in the mesh, too, otherwise everything
- // will get messed up.
-
- {
- // advance vertices.
- edge_t *e = edge;
- vertex_t *va = e->vert;
- do {
- e->vert = e->next->vert;
- e = e->next;
- } while (e != edge);
- edge->prev->vert = va;
- }
-
- {
- // swap prev and next pointers.
- edge_t *e = edge;
- do {
- edge_t *n = e->next;
- std::swap(e->prev, e->next);
- e = n;
- } while (e != edge);
- }
-
- plane.negate();
-
- int da = carve::geom::largestAxis(plane.N);
-
- project = getProjector(plane.N.v[da] > 0, da);
- unproject = getUnprojector(plane.N.v[da] > 0, da);
- }
-
- void canonicalize();
-
- ~Face() {
- clearEdges();
- }
- };
-
-
-
- struct MeshOptions {
- bool opt_avoid_cavities;
-
- MeshOptions() :
- opt_avoid_cavities(false) {
- }
-
- MeshOptions &avoid_cavities(bool val) {
- opt_avoid_cavities = val;
- return *this;
- }
- };
-
-
-
- namespace detail {
- class FaceStitcher {
- FaceStitcher();
- FaceStitcher(const FaceStitcher &);
- FaceStitcher &operator=(const FaceStitcher &);
-
- typedef Vertex<3> vertex_t;
- typedef Edge<3> edge_t;
- typedef Face<3> face_t;
-
- typedef std::pair<const vertex_t *, const vertex_t *> vpair_t;
- typedef std::list<edge_t *> edgelist_t;
- typedef std::unordered_map<vpair_t, edgelist_t, carve::mesh::hash_vertex_pair> edge_map_t;
- typedef std::unordered_map<const vertex_t *, std::set<const vertex_t *> > edge_graph_t;
-
- MeshOptions opts;
-
- edge_map_t edges;
- edge_map_t complex_edges;
-
- carve::djset::djset face_groups;
- std::vector<bool> is_open;
-
- edge_graph_t edge_graph;
-
- struct EdgeOrderData {
- size_t group_id;
- bool is_reversed;
- carve::geom::vector<3> face_dir;
- edge_t *edge;
-
- EdgeOrderData(edge_t *_edge, size_t _group_id, bool _is_reversed) :
- group_id(_group_id),
- is_reversed(_is_reversed) {
- if (is_reversed) {
- face_dir = -(_edge->face->plane.N);
- } else {
- face_dir = (_edge->face->plane.N);
- }
- edge = _edge;
- }
-
- struct TestGroups {
- size_t fwd, rev;
-
- TestGroups(size_t _fwd, size_t _rev) : fwd(_fwd), rev(_rev) {
- }
-
- bool operator()(const EdgeOrderData &eo) const {
- return eo.group_id == (eo.is_reversed ? rev : fwd);
- }
- };
-
- struct Cmp {
- carve::geom::vector<3> edge_dir;
- carve::geom::vector<3> base_dir;
-
- Cmp(const carve::geom::vector<3> &_edge_dir,
- const carve::geom::vector<3> &_base_dir) :
- edge_dir(_edge_dir),
- base_dir(_base_dir) {
- }
- bool operator()(const EdgeOrderData &a, const EdgeOrderData &b) const;
- };
- };
-
- void extractConnectedEdges(std::vector<const vertex_t *>::iterator begin,
- std::vector<const vertex_t *>::iterator end,
- std::vector<std::vector<Edge<3> *> > &efwd,
- std::vector<std::vector<Edge<3> *> > &erev);
-
- size_t faceGroupID(const Face<3> *face);
- size_t faceGroupID(const Edge<3> *edge);
-
- void resolveOpenEdges();
-
- void fuseEdges(std::vector<Edge<3> *> &fwd,
- std::vector<Edge<3> *> &rev);
-
- void joinGroups(std::vector<std::vector<Edge<3> *> > &efwd,
- std::vector<std::vector<Edge<3> *> > &erev,
- size_t fwd_grp,
- size_t rev_grp);
-
- void matchOrderedEdges(const std::vector<std::vector<EdgeOrderData> >::iterator begin,
- const std::vector<std::vector<EdgeOrderData> >::iterator end,
- std::vector<std::vector<Edge<3> *> > &efwd,
- std::vector<std::vector<Edge<3> *> > &erev);
-
- void reorder(std::vector<EdgeOrderData> &ordering, size_t fwd_grp);
-
- void orderForwardAndReverseEdges(std::vector<std::vector<Edge<3> *> > &efwd,
- std::vector<std::vector<Edge<3> *> > &erev,
- std::vector<std::vector<EdgeOrderData> > &result);
-
- void edgeIncidentGroups(const vpair_t &e,
- const edge_map_t &all_edges,
- std::pair<std::set<size_t>, std::set<size_t> > &groups);
-
- void buildEdgeGraph(const edge_map_t &all_edges);
- void extractPath(std::vector<const vertex_t *> &path);
- void removePath(const std::vector<const vertex_t *> &path);
- void matchSimpleEdges();
- void construct();
-
- template<typename iter_t>
- void initEdges(iter_t begin, iter_t end);
-
- template<typename iter_t>
- void build(iter_t begin, iter_t end, std::vector<Mesh<3> *> &meshes);
-
- public:
- FaceStitcher(const MeshOptions &_opts);
-
- template<typename iter_t>
- void create(iter_t begin, iter_t end, std::vector<Mesh<3> *> &meshes);
- };
- }
-
-
-
- // A Mesh is a connected set of faces. It may be open (some edges
- // have NULL rev members), or closed. On destruction, a Mesh
- // should free its Faces (which will in turn free Edges, but not
- // Vertices). A Mesh is edge-connected, which is to say that each
- // face in the mesh shares an edge with at least one other face in
- // the mesh. Touching at a vertex is not sufficient. This means
- // that the perimeter of an open mesh visits each vertex no more
- // than once.
- template<unsigned ndim>
- class Mesh {
- public:
- typedef Vertex<ndim> vertex_t;
- typedef Edge<ndim> edge_t;
- typedef Face<ndim> face_t;
- typedef carve::geom::aabb<ndim> aabb_t;
- typedef MeshSet<ndim> meshset_t;
-
- std::vector<face_t *> faces;
-
- // open_edges is a vector of all the edges in the mesh that
- // don't have a matching edge in the opposite direction.
- std::vector<edge_t *> open_edges;
-
- // closed_edges is a vector of all the edges in the mesh that
- // have a matching edge in the opposite direction, and whose
- // address is lower than their counterpart. (i.e. for each pair
- // of adjoining faces, one of the two half edges is stored in
- // closed_edges).
- std::vector<edge_t *> closed_edges;
-
- bool is_negative;
-
- meshset_t *meshset;
-
- protected:
- Mesh(std::vector<face_t *> &_faces,
- std::vector<edge_t *> &_open_edges,
- std::vector<edge_t *> &_closed_edges,
- bool _is_negative);
-
- public:
- Mesh(std::vector<face_t *> &_faces);
-
- ~Mesh();
-
- template<typename iter_t>
- static void create(iter_t begin, iter_t end, std::vector<Mesh<ndim> *> &meshes, const MeshOptions &opts);
-
- aabb_t getAABB() const {
- return aabb_t(faces.begin(), faces.end());
- }
-
- bool isClosed() const {
- return open_edges.size() == 0;
- }
-
- bool isNegative() const {
- return is_negative;
- }
-
- double volume() const {
- if (is_negative || !faces.size()) return 0.0;
-
- double vol = 0.0;
- typename vertex_t::vector_t origin = faces[0]->edge->vert->v;
-
- for (size_t f = 0; f < faces.size(); ++f) {
- face_t *face = faces[f];
- edge_t *e1 = face->edge;
- for (edge_t *e2 = e1->next ;e2->next != e1; e2 = e2->next) {
- vol += carve::geom3d::tetrahedronVolume(e1->vert->v, e2->vert->v, e2->next->vert->v, origin);
- }
- }
- return vol;
- }
-
- struct IsClosed {
- bool operator()(const Mesh &mesh) const { return mesh.isClosed(); }
- bool operator()(const Mesh *mesh) const { return mesh->isClosed(); }
- };
-
- struct IsNegative {
- bool operator()(const Mesh &mesh) const { return mesh.isNegative(); }
- bool operator()(const Mesh *mesh) const { return mesh->isNegative(); }
- };
-
- void cacheEdges();
-
- int orientationAtVertex(edge_t *);
- void calcOrientation();
-
- void recalc() {
- for (size_t i = 0; i < faces.size(); ++i) faces[i]->recalc();
- calcOrientation();
- }
-
- void invert() {
- for (size_t i = 0; i < faces.size(); ++i) {
- faces[i]->invert();
- }
- if (isClosed()) is_negative = !is_negative;
- }
-
- Mesh *clone(const vertex_t *old_base, vertex_t *new_base) const;
- };
-
- // A MeshSet manages vertex storage, and a collection of meshes.
- // It should be easy to turn a vertex pointer into its index in
- // its MeshSet vertex_storage.
- template<unsigned ndim>
- class MeshSet {
- MeshSet();
- MeshSet(const MeshSet &);
- MeshSet &operator=(const MeshSet &);
-
- template<typename iter_t>
- void _init_from_faces(iter_t begin, iter_t end, const MeshOptions &opts);
-
- public:
- typedef Vertex<ndim> vertex_t;
- typedef Edge<ndim> edge_t;
- typedef Face<ndim> face_t;
- typedef Mesh<ndim> mesh_t;
- typedef carve::geom::aabb<ndim> aabb_t;
-
- std::vector<vertex_t> vertex_storage;
- std::vector<mesh_t *> meshes;
-
- public:
- template<typename face_type>
- struct FaceIter : public std::iterator<std::random_access_iterator_tag, face_type> {
- typedef std::iterator<std::random_access_iterator_tag, face_type> super;
- typedef typename super::difference_type difference_type;
-
- const MeshSet<ndim> *obj;
- size_t mesh, face;
-
- FaceIter(const MeshSet<ndim> *_obj, size_t _mesh, size_t _face);
-
- void fwd(size_t n);
- void rev(size_t n);
- void adv(int n);
-
- FaceIter operator++(int) { FaceIter tmp = *this; tmp.fwd(1); return tmp; }
- FaceIter operator+(int v) { FaceIter tmp = *this; tmp.adv(v); return tmp; }
- FaceIter &operator++() { fwd(1); return *this; }
- FaceIter &operator+=(int v) { adv(v); return *this; }
-
- FaceIter operator--(int) { FaceIter tmp = *this; tmp.rev(1); return tmp; }
- FaceIter operator-(int v) { FaceIter tmp = *this; tmp.adv(-v); return tmp; }
- FaceIter &operator--() { rev(1); return *this; }
- FaceIter &operator-=(int v) { adv(-v); return *this; }
-
- difference_type operator-(const FaceIter &other) const;
-
- bool operator==(const FaceIter &other) const {
- return obj == other.obj && mesh == other.mesh && face == other.face;
- }
- bool operator!=(const FaceIter &other) const {
- return !(*this == other);
- }
- bool operator<(const FaceIter &other) const {
- CARVE_ASSERT(obj == other.obj);
- return mesh < other.mesh || (mesh == other.mesh && face < other.face);
- }
- bool operator>(const FaceIter &other) const {
- return other < *this;
- }
- bool operator<=(const FaceIter &other) const {
- return !(other < *this);
- }
- bool operator>=(const FaceIter &other) const {
- return !(*this < other);
- }
-
- face_type operator*() const {
- return obj->meshes[mesh]->faces[face];
- }
- };
-
- typedef FaceIter<const face_t *> const_face_iter;
- typedef FaceIter<face_t *> face_iter;
-
- face_iter faceBegin() { return face_iter(this, 0, 0); }
- face_iter faceEnd() { return face_iter(this, meshes.size(), 0); }
-
- const_face_iter faceBegin() const { return const_face_iter(this, 0, 0); }
- const_face_iter faceEnd() const { return const_face_iter(this, meshes.size(), 0); }
-
- aabb_t getAABB() const {
- return aabb_t(meshes.begin(), meshes.end());
- }
-
- template<typename func_t>
- void transform(func_t func) {
- for (size_t i = 0; i < vertex_storage.size(); ++i) {
- vertex_storage[i].v = func(vertex_storage[i].v);
- }
- for (size_t i = 0; i < meshes.size(); ++i) {
- meshes[i]->recalc();
- }
- }
-
- MeshSet(const std::vector<typename vertex_t::vector_t> &points,
- size_t n_faces,
- const std::vector<int> &face_indices,
- const MeshOptions &opts = MeshOptions());
-
- // Construct a mesh set from a set of disconnected faces. Takes
- // posession of the face pointers.
- MeshSet(std::vector<face_t *> &faces,
- const MeshOptions &opts = MeshOptions());
-
- MeshSet(std::list<face_t *> &faces,
- const MeshOptions &opts = MeshOptions());
-
- MeshSet(std::vector<vertex_t> &_vertex_storage,
- std::vector<mesh_t *> &_meshes);
-
- // This constructor consolidates and rewrites vertex pointers in
- // each mesh, repointing them to local storage.
- MeshSet(std::vector<mesh_t *> &_meshes);
-
- MeshSet *clone() const;
-
- ~MeshSet();
-
- bool isClosed() const {
- for (size_t i = 0; i < meshes.size(); ++i) {
- if (!meshes[i]->isClosed()) return false;
- }
- return true;
- }
-
-
- void invert() {
- for (size_t i = 0; i < meshes.size(); ++i) {
- meshes[i]->invert();
- }
- }
-
- void collectVertices();
-
- void canonicalize();
-
- void separateMeshes();
- };
-
-
-
- carve::PointClass classifyPoint(
- const carve::mesh::MeshSet<3> *meshset,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *face_rtree,
- const carve::geom::vector<3> &v,
- bool even_odd = false,
- const carve::mesh::Mesh<3> *mesh = NULL,
- const carve::mesh::Face<3> **hit_face = NULL);
-
-
-
- }
-
-
-
- mesh::MeshSet<3> *meshFromPolyhedron(const poly::Polyhedron *, int manifold_id);
- poly::Polyhedron *polyhedronFromMesh(const mesh::MeshSet<3> *, int manifold_id);
-
-
-
-};
-
-#include <carve/mesh_impl.hpp>
diff --git a/extern/carve/include/carve/mesh_impl.hpp b/extern/carve/include/carve/mesh_impl.hpp
deleted file mode 100644
index eecfe1fb040..00000000000
--- a/extern/carve/include/carve/mesh_impl.hpp
+++ /dev/null
@@ -1,1098 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/geom2d.hpp>
-#include <carve/geom3d.hpp>
-#include <carve/djset.hpp>
-
-#include <iostream>
-#include <deque>
-
-#include <stddef.h>
-
-namespace carve {
- namespace mesh {
-
-
-
- namespace detail {
- template<typename list_t>
- struct list_iter_t {
- typedef std::bidirectional_iterator_tag iterator_category;
- typedef list_t value_type;
- typedef ptrdiff_t difference_type;
- typedef value_type & reference;
- typedef value_type * pointer;
-
- list_t *curr;
- int pos;
-
- list_iter_t() { }
- list_iter_t(list_t *_curr, int _pos) : curr(_curr), pos(_pos) { }
-
- list_iter_t operator++(int) { list_iter_t result(*this); ++pos; curr = curr->next; return result; }
- list_iter_t operator--(int) { list_iter_t result(*this); --pos; curr = curr->prev; return result; }
-
- list_iter_t operator++() { ++pos; curr = curr->next; return *this; }
- list_iter_t operator--() { --pos; curr = curr->prev; return *this; }
-
- bool operator==(const list_iter_t &other) const { return curr == other.curr && pos == other.pos; }
- bool operator!=(const list_iter_t &other) const { return curr != other.curr || pos != other.pos; }
-
- reference operator*() { return *curr; }
- pointer operator->() { return curr; }
-
- int idx() const { return pos; }
- };
- }
-
-
-
- template<unsigned ndim>
- Edge<ndim> *Edge<ndim>::mergeFaces() {
- if (rev == NULL) return NULL;
-
- face_t *fwdface = face;
- face_t *revface = rev->face;
-
- size_t n_removed = 0;
-
- Edge *splice_beg = this;
- do {
- splice_beg = splice_beg->prev;
- ++n_removed;
- } while (splice_beg != this &&
- splice_beg->rev &&
- splice_beg->next->rev->prev == splice_beg->rev);
-
- if (splice_beg == this) {
- // edge loops are completely matched.
- return NULL;
- }
-
- Edge *splice_end = this;
- do {
- splice_end = splice_end->next;
- ++n_removed;
- } while (splice_end->rev &&
- splice_end->prev->rev->next == splice_end->rev);
-
- --n_removed;
-
- Edge *link1_p = splice_beg;
- Edge *link1_n = splice_beg->next->rev->next;
-
- Edge *link2_p = splice_end->prev->rev->prev;
- Edge *link2_n = splice_end;
-
- CARVE_ASSERT(link1_p->face == fwdface);
- CARVE_ASSERT(link1_n->face == revface);
-
- CARVE_ASSERT(link2_p->face == revface);
- CARVE_ASSERT(link2_n->face == fwdface);
-
- Edge *left_loop = link1_p->next;
-
- CARVE_ASSERT(left_loop->rev == link1_n->prev);
-
- _link(link2_n->prev, link1_p->next);
- _link(link1_n->prev, link2_p->next);
-
- _link(link1_p, link1_n);
- _link(link2_p, link2_n);
-
- fwdface->edge = link1_p;
-
- for (Edge *e = link1_n; e != link2_n; e = e->next) {
- CARVE_ASSERT(e->face == revface);
- e->face = fwdface;
- fwdface->n_edges++;
- }
- for (Edge *e = link2_n; e != link1_n; e = e->next) {
- CARVE_ASSERT(e->face == fwdface);
- }
-
- fwdface->n_edges -= n_removed;
-
- revface->n_edges = 0;
- revface->edge = NULL;
-
- _setloopface(left_loop, NULL);
- _setloopface(left_loop->rev, NULL);
-
- return left_loop;
- }
-
-
-
- template<unsigned ndim>
- Edge<ndim> *Edge<ndim>::removeHalfEdge() {
- Edge *n = NULL;
- if (face) {
- face->n_edges--;
- }
-
- if (next == this) {
- if (face) face->edge = NULL;
- } else {
- if (face && face->edge == this) face->edge = next;
- next->prev = prev;
- prev->next = next;
- n = next;
- }
- delete this;
- return n;
- }
-
-
-
- template<unsigned ndim>
- Edge<ndim> *Edge<ndim>::removeEdge() {
- if (rev) {
- rev->removeHalfEdge();
- }
- return removeHalfEdge();
- }
-
-
-
- template<unsigned ndim>
- void Edge<ndim>::unlink() {
- if (rev) { rev->rev = NULL; rev = NULL; }
- if (prev->rev) { prev->rev->rev = NULL; prev->rev = NULL; }
-
- if (face) {
- face->n_edges--;
- if (face->edge == this) face->edge = next;
- face = NULL;
- }
-
- next->prev = prev;
- prev->next = next;
-
- prev = next = this;
- }
-
-
-
- template<unsigned ndim>
- void Edge<ndim>::insertBefore(Edge<ndim> *other) {
- if (prev != this) unlink();
- prev = other->prev;
- next = other;
- next->prev = this;
- prev->next = this;
-
- if (prev->rev) { prev->rev->rev = NULL; prev->rev = NULL; }
- }
-
-
-
- template<unsigned ndim>
- void Edge<ndim>::insertAfter(Edge<ndim> *other) {
- if (prev != this) unlink();
- next = other->next;
- prev = other;
- next->prev = this;
- prev->next = this;
-
- if (prev->rev) { prev->rev->rev = NULL; prev->rev = NULL; }
- }
-
-
-
- template<unsigned ndim>
- size_t Edge<ndim>::loopSize() const {
- const Edge *e = this;
- size_t n = 0;
- do { e = e->next; ++n; } while (e != this);
- return n;
- }
-
-
-
- template<unsigned ndim>
- Edge<ndim> *Edge<ndim>::perimNext() const {
- if (rev) return NULL;
- Edge *e = next;
- while(e->rev) {
- e = e->rev->next;
- }
- return e;
- }
-
-
-
- template<unsigned ndim>
- Edge<ndim> *Edge<ndim>::perimPrev() const {
- if (rev) return NULL;
- Edge *e = prev;
- while(e->rev) {
- e = e->rev->prev;
- }
- return e;
- }
-
-
-
- template<unsigned ndim>
- Edge<ndim>::Edge(vertex_t *_vert, face_t *_face) :
- vert(_vert), face(_face), prev(NULL), next(NULL), rev(NULL) {
- prev = next = this;
- }
-
-
-
- template<unsigned ndim>
- Edge<ndim>::~Edge() {
- }
-
-
-
- template<unsigned ndim>
- typename Face<ndim>::aabb_t Face<ndim>::getAABB() const {
- aabb_t aabb;
- aabb.fit(begin(), end(), vector_mapping());
- return aabb;
- }
-
-
-
- template<unsigned ndim>
- bool Face<ndim>::recalc() {
- if (!carve::geom3d::fitPlane(begin(), end(), vector_mapping(), plane)) {
- return false;
- }
-
- int da = carve::geom::largestAxis(plane.N);
- double A = carve::geom2d::signedArea(begin(), end(), projection_mapping(getProjector(false, da)));
-
- if ((A < 0.0) ^ (plane.N.v[da] < 0.0)) {
- plane.negate();
- }
-
- project = getProjector(plane.N.v[da] > 0, da);
- unproject = getUnprojector(plane.N.v[da] > 0, da);
-
- return true;
- }
-
-
-
- template<unsigned ndim>
- void Face<ndim>::clearEdges() {
- if (!edge) return;
-
- edge_t *curr = edge;
- do {
- edge_t *next = curr->next;
- delete curr;
- curr = next;
- } while (curr != edge);
-
- edge = NULL;
-
- n_edges = 0;
- }
-
-
-
- template<unsigned ndim>
- template<typename iter_t>
- void Face<ndim>::loopFwd(iter_t begin, iter_t end) {
- clearEdges();
- if (begin == end) return;
- edge = new edge_t(*begin, this); ++n_edges; ++begin;
- while (begin != end) {
- edge_t *e = new edge_t(*begin, this);
- e->insertAfter(edge->prev);
- ++n_edges;
- ++begin;
- }
- }
-
-
-
- template<unsigned ndim>
- template<typename iter_t>
- void Face<ndim>::loopRev(iter_t begin, iter_t end) {
- clearEdges();
- if (begin == end) return;
- edge = new edge_t(*begin, this); ++n_edges; ++begin;
- while (begin != end) {
- edge_t *e = new edge_t(*begin, this);
- e->insertBefore(edge->next);
- ++n_edges;
- ++begin;
- }
- }
-
-
-
- template<unsigned ndim>
- template<typename iter_t>
- void Face<ndim>::init(iter_t begin, iter_t end) {
- loopFwd(begin, end);
- }
-
-
-
- template<unsigned ndim>
- void Face<ndim>::init(vertex_t *a, vertex_t *b, vertex_t *c) {
- clearEdges();
- edge_t *ea = new edge_t(a, this);
- edge_t *eb = new edge_t(b, this);
- edge_t *ec = new edge_t(c, this);
- eb->insertAfter(ea);
- ec->insertAfter(eb);
- edge = ea;
- n_edges = 3;
- }
-
-
-
- template<unsigned ndim>
- void Face<ndim>::init(vertex_t *a, vertex_t *b, vertex_t *c, vertex_t *d) {
- clearEdges();
- edge_t *ea = new edge_t(a, this);
- edge_t *eb = new edge_t(b, this);
- edge_t *ec = new edge_t(c, this);
- edge_t *ed = new edge_t(d, this);
- eb->insertAfter(ea);
- ec->insertAfter(eb);
- ed->insertAfter(ec);
- edge = ea;
- n_edges = 4;
- }
-
-
-
- template<unsigned ndim>
- void Face<ndim>::getVertices(std::vector<vertex_t *> &verts) const {
- verts.clear();
- verts.reserve(n_edges);
- const edge_t *e = edge;
- do { verts.push_back(e->vert); e = e->next; } while (e != edge);
- }
-
-
-
- template<unsigned ndim>
- void Face<ndim>::getProjectedVertices(std::vector<carve::geom::vector<2> > &verts) const {
- verts.clear();
- verts.reserve(n_edges);
- const edge_t *e = edge;
- do { verts.push_back(project(e->vert->v)); e = e->next; } while (e != edge);
- }
-
-
-
- template<unsigned ndim>
- typename Face<ndim>::vector_t Face<ndim>::centroid() const {
- vector_t v;
- edge_t *e = edge;
- do {
- v += e->vert->v;
- e = e->next;
- } while(e != edge);
- v /= n_edges;
- return v;
- }
-
-
-
- template<unsigned ndim>
- void Face<ndim>::canonicalize() {
- edge_t *min = edge;
- edge_t *e = edge;
-
- do {
- if (e->vert < min->vert) min = e;
- e = e->next;
- } while (e != edge);
-
- edge = min;
- }
-
-
-
- template<unsigned ndim>
- template<typename iter_t>
- Face<ndim> *Face<ndim>::create(iter_t beg, iter_t end, bool reversed) const {
- Face *r = new Face();
-
- if (reversed) {
- r->loopRev(beg, end);
- r->plane = -plane;
- } else {
- r->loopFwd(beg, end);
- r->plane = plane;
- }
-
- int da = carve::geom::largestAxis(r->plane.N);
-
- r->project = r->getProjector(r->plane.N.v[da] > 0, da);
- r->unproject = r->getUnprojector(r->plane.N.v[da] > 0, da);
-
- return r;
- }
-
-
-
- template<unsigned ndim>
- Face<ndim> *Face<ndim>::clone(const vertex_t *old_base,
- vertex_t *new_base,
- std::unordered_map<const edge_t *, edge_t *> &edge_map) const {
- Face *r = new Face(*this);
-
- edge_t *e = edge;
- edge_t *r_p = NULL;
- edge_t *r_e;
- do {
- r_e = new edge_t(e->vert - old_base + new_base, r);
- edge_map[e] = r_e;
- if (r_p) {
- r_p->next = r_e;
- r_e->prev = r_p;
- } else {
- r->edge = r_e;
- }
- r_p = r_e;
-
- if (e->rev) {
- typename std::unordered_map<const edge_t *, edge_t *>::iterator rev_i = edge_map.find(e->rev);
- if (rev_i != edge_map.end()) {
- r_e->rev = (*rev_i).second;
- (*rev_i).second->rev = r_e;
- }
- }
-
- e = e->next;
- } while (e != edge);
- r_e->next = r->edge;
- r->edge->prev = r_e;
- return r;
- }
-
-
-
- template<unsigned ndim>
- Mesh<ndim>::Mesh(std::vector<face_t *> &_faces,
- std::vector<edge_t *> &_open_edges,
- std::vector<edge_t *> &_closed_edges,
- bool _is_negative) {
- std::swap(faces, _faces);
- std::swap(open_edges, _open_edges);
- std::swap(closed_edges, _closed_edges);
- is_negative = _is_negative;
- meshset = NULL;
-
- for (size_t i = 0; i < faces.size(); ++i) {
- faces[i]->mesh = this;
- }
- }
-
-
-
- namespace detail {
- template<typename iter_t>
- void FaceStitcher::initEdges(iter_t begin,
- iter_t end) {
- size_t c = 0;
- for (iter_t i = begin; i != end; ++i) {
- face_t *face = *i;
- CARVE_ASSERT(face->mesh == NULL); // for the moment, can only insert a face into a mesh once.
-
- face->id = c++;
- edge_t *e = face->edge;
- do {
- edges[vpair_t(e->v1(), e->v2())].push_back(e);
- e = e->next;
- if (e->rev) { e->rev->rev = NULL; e->rev = NULL; }
- } while (e != face->edge);
- }
- face_groups.init(c);
- is_open.clear();
- is_open.resize(c, false);
- }
-
- template<typename iter_t>
- void FaceStitcher::build(iter_t begin,
- iter_t end,
- std::vector<Mesh<3> *> &meshes) {
- // work out what set each face belongs to, and then construct
- // mesh instances for each set of faces.
- std::vector<size_t> index_set;
- std::vector<size_t> set_size;
- face_groups.get_index_to_set(index_set, set_size);
-
- std::vector<std::vector<face_t *> > mesh_faces;
- mesh_faces.resize(set_size.size());
- for (size_t i = 0; i < set_size.size(); ++i) {
- mesh_faces[i].reserve(set_size[i]);
- }
-
- for (iter_t i = begin; i != end; ++i) {
- face_t *face = *i;
- mesh_faces[index_set[face->id]].push_back(face);
- }
-
- meshes.clear();
- meshes.reserve(mesh_faces.size());
- for (size_t i = 0; i < mesh_faces.size(); ++i) {
- meshes.push_back(new Mesh<3>(mesh_faces[i]));
- }
- }
-
- template<typename iter_t>
- void FaceStitcher::create(iter_t begin,
- iter_t end,
- std::vector<Mesh<3> *> &meshes) {
- initEdges(begin, end);
- construct();
- build(begin, end, meshes);
- }
- }
-
-
-
- template<unsigned ndim>
- void Mesh<ndim>::cacheEdges() {
- closed_edges.clear();
- open_edges.clear();
-
- for (size_t i = 0; i < faces.size(); ++i) {
- face_t *face = faces[i];
- edge_t *e = face->edge;
- do {
- if (e->rev == NULL) {
- open_edges.push_back(e);
- } else if (e < e->rev) {
- closed_edges.push_back(e);
- }
- e = e->next;
- } while (e != face->edge);
- }
- }
-
-
-
- template<unsigned ndim>
- Mesh<ndim>::Mesh(std::vector<face_t *> &_faces) : faces(), open_edges(), closed_edges(), meshset(NULL) {
- faces.swap(_faces);
- for (size_t i = 0; i < faces.size(); ++i) {
- faces[i]->mesh = this;
- }
- cacheEdges();
- calcOrientation();
- }
-
-
-
- template<unsigned ndim>
- int Mesh<ndim>::orientationAtVertex(edge_t *e_base) {
-#if defined(CARVE_DEBUG)
- std::cerr << "warning: vertex orientation not defined for ndim=" << ndim << std::endl;
-#endif
- return 0;
- }
-
-
-
- template<>
- inline int Mesh<3>::orientationAtVertex(edge_t *e_base) {
- edge_t *e = e_base;
- vertex_t::vector_t v_base = e->v1()->v;
- std::vector<vertex_t::vector_t> v_edge;
-
- if (v_edge.size() < 3) {
- return 0;
- }
-
- do {
- v_edge.push_back(e->v2()->v);
- e = e->rev->next;
- } while (e != e_base);
-
- const size_t N = v_edge.size();
-
- for (size_t i = 0; i < N; ++i) {
- size_t j = (i + 1) % N;
-
- double o_hi = 0.0;
- double o_lo = 0.0;
-
- for (size_t k = (j + 1) % N; k != i; k = (k + 1) % N) {
- double o = carve::geom3d::orient3d(v_edge[i], v_base, v_edge[j], v_edge[k]);
- o_hi = std::max(o_hi, o);
- o_lo = std::max(o_lo, o);
- }
-
- if (o_lo >= 0.0) return +1;
- if (o_hi <= 0.0) return -1;
- }
-
- return 0;
- }
-
-
-
- template<unsigned ndim>
- void Mesh<ndim>::calcOrientation() {
- if (open_edges.size() || !closed_edges.size()) {
- is_negative = false;
- return;
- }
-
- edge_t *emin = closed_edges[0];
-
- if (emin->rev->v1()->v < emin->v1()->v) emin = emin->rev;
-
- for (size_t i = 1; i < closed_edges.size(); ++i) {
- if (closed_edges[i]->v1()->v < emin->v1()->v) emin = closed_edges[i];
- if (closed_edges[i]->rev->v1()->v < emin->v1()->v) emin = closed_edges[i]->rev;
- }
-
- int orientation = orientationAtVertex(emin);
-
-#if defined(CARVE_DEBUG)
- if (orientation == 0) {
- std::cerr << "warning: could not determine orientation for mesh " << this << std::endl;
- }
-#endif
-
- is_negative = orientation == -1;
- }
-
-
-
- template<unsigned ndim>
- Mesh<ndim> *Mesh<ndim>::clone(const vertex_t *old_base,
- vertex_t *new_base) const {
- std::vector<face_t *> r_faces;
- std::vector<edge_t *> r_open_edges;
- std::vector<edge_t *> r_closed_edges;
- std::unordered_map<const edge_t *, edge_t *> edge_map;
-
- r_faces.reserve(faces.size());
- r_open_edges.reserve(r_open_edges.size());
- r_closed_edges.reserve(r_closed_edges.size());
-
- for (size_t i = 0; i < faces.size(); ++i) {
- r_faces.push_back(faces[i]->clone(old_base, new_base, edge_map));
- }
- for (size_t i = 0; i < closed_edges.size(); ++i) {
- r_closed_edges.push_back(edge_map[closed_edges[i]]);
- r_closed_edges.back()->rev = edge_map[closed_edges[i]->rev];
- }
- for (size_t i = 0; i < open_edges.size(); ++i) {
- r_open_edges.push_back(edge_map[open_edges[i]]);
- }
-
- return new Mesh(r_faces, r_open_edges, r_closed_edges, is_negative);
- }
-
-
-
- template<unsigned ndim>
- Mesh<ndim>::~Mesh() {
- for (size_t i = 0; i < faces.size(); ++i) {
- delete faces[i];
- }
- }
-
-
-
- template<unsigned ndim>
- template<typename iter_t>
- void Mesh<ndim>::create(iter_t begin, iter_t end, std::vector<Mesh<ndim> *> &meshes, const MeshOptions &opts) {
- meshes.clear();
- }
-
-
-
- template<>
- template<typename iter_t>
- void Mesh<3>::create(iter_t begin, iter_t end, std::vector<Mesh<3> *> &meshes, const MeshOptions &opts) {
- detail::FaceStitcher(opts).create(begin, end, meshes);
- }
-
-
-
- template<unsigned ndim>
- template<typename iter_t>
- void MeshSet<ndim>::_init_from_faces(iter_t begin, iter_t end, const MeshOptions &opts) {
- typedef std::unordered_map<const vertex_t *, size_t> map_t;
- map_t vmap;
-
- for (iter_t i = begin; i != end; ++i) {
- face_t *f = *i;
- edge_t *e = f->edge;
- do {
- typename map_t::const_iterator j = vmap.find(e->vert);
- if (j == vmap.end()) {
- size_t idx = vmap.size();
- vmap[e->vert] = idx;
- }
- e = e->next;
- } while (e != f->edge);
- }
-
- vertex_storage.resize(vmap.size());
- for (typename map_t::const_iterator i = vmap.begin(); i != vmap.end(); ++i) {
- vertex_storage[(*i).second].v = (*i).first->v;
- }
-
- for (iter_t i = begin; i != end; ++i) {
- face_t *f = *i;
- edge_t *e = f->edge;
- do {
- e->vert = &vertex_storage[vmap[e->vert]];
- e = e->next;
- } while (e != f->edge);
- }
-
- mesh_t::create(begin, end, meshes, opts);
-
- for (size_t i = 0; i < meshes.size(); ++i) {
- meshes[i]->meshset = this;
- }
- }
-
-
-
- template<unsigned ndim>
- MeshSet<ndim>::MeshSet(const std::vector<typename MeshSet<ndim>::vertex_t::vector_t> &points,
- size_t n_faces,
- const std::vector<int> &face_indices,
- const MeshOptions &opts) {
- vertex_storage.reserve(points.size());
- std::vector<face_t *> faces;
- faces.reserve(n_faces);
- for (size_t i = 0; i < points.size(); ++i) {
- vertex_storage.push_back(vertex_t(points[i]));
- }
-
- std::vector<vertex_t *> v;
- size_t p = 0;
- for (size_t i = 0; i < n_faces; ++i) {
- CARVE_ASSERT(face_indices[p] > 1);
-
- const size_t N = (size_t)face_indices[p++];
- v.clear();
- v.reserve(N);
- for (size_t j = 0; j < N; ++j) {
- v.push_back(&vertex_storage[face_indices[p++]]);
- }
- faces.push_back(new face_t(v.begin(), v.end()));
- }
- CARVE_ASSERT(p == face_indices.size());
- mesh_t::create(faces.begin(), faces.end(), meshes, opts);
-
- for (size_t i = 0; i < meshes.size(); ++i) {
- meshes[i]->meshset = this;
- }
- }
-
-
-
- template<unsigned ndim>
- MeshSet<ndim>::MeshSet(std::vector<face_t *> &faces, const MeshOptions &opts) {
- _init_from_faces(faces.begin(), faces.end(), opts);
- }
-
-
-
- template<unsigned ndim>
- MeshSet<ndim>::MeshSet(std::list<face_t *> &faces, const MeshOptions &opts) {
- _init_from_faces(faces.begin(), faces.end(), opts);
- }
-
-
-
- template<unsigned ndim>
- MeshSet<ndim>::MeshSet(std::vector<vertex_t> &_vertex_storage,
- std::vector<mesh_t *> &_meshes) {
- vertex_storage.swap(_vertex_storage);
- meshes.swap(_meshes);
-
- for (size_t i = 0; i < meshes.size(); ++i) {
- meshes[i]->meshset = this;
- }
- }
-
-
-
- template<unsigned ndim>
- MeshSet<ndim>::MeshSet(std::vector<typename MeshSet<ndim>::mesh_t *> &_meshes) {
- meshes.swap(_meshes);
- std::unordered_map<vertex_t *, size_t> vert_idx;
-
- for (size_t m = 0; m < meshes.size(); ++m) {
- mesh_t *mesh = meshes[m];
- CARVE_ASSERT(mesh->meshset == NULL);
- mesh->meshset = this;
- for (size_t f = 0; f < mesh->faces.size(); ++f) {
- face_t *face = mesh->faces[f];
- edge_t *edge = face->edge;
- do {
- vert_idx[edge->vert] = 0;
- edge = edge->next;
- } while (edge != face->edge);
- }
- }
-
- vertex_storage.reserve(vert_idx.size());
- for (typename std::unordered_map<vertex_t *, size_t>::iterator i = vert_idx.begin(); i != vert_idx.end(); ++i) {
- (*i).second = vertex_storage.size();
- vertex_storage.push_back(*(*i).first);
- }
-
- for (size_t m = 0; m < meshes.size(); ++m) {
- mesh_t *mesh = meshes[m];
- for (size_t f = 0; f < mesh->faces.size(); ++f) {
- face_t *face = mesh->faces[f];
- edge_t *edge = face->edge;
- do {
- size_t i = vert_idx[edge->vert];
- edge->vert = &vertex_storage[i];
- edge = edge->next;
- } while (edge != face->edge);
- }
- }
- }
-
-
-
- template<unsigned ndim>
- MeshSet<ndim> *MeshSet<ndim>::clone() const {
- std::vector<vertex_t> r_vertex_storage = vertex_storage;
- std::vector<mesh_t *> r_meshes;
- for (size_t i = 0; i < meshes.size(); ++i) {
- r_meshes.push_back(meshes[i]->clone(&vertex_storage[0], &r_vertex_storage[0]));
- }
-
- return new MeshSet(r_vertex_storage, r_meshes);
- }
-
-
-
- template<unsigned ndim>
- MeshSet<ndim>::~MeshSet() {
- for (size_t i = 0; i < meshes.size(); ++i) {
- delete meshes[i];
- }
- }
-
-
-
- template<unsigned ndim>
- template<typename face_type>
- MeshSet<ndim>::FaceIter<face_type>::FaceIter(const MeshSet<ndim> *_obj, size_t _mesh, size_t _face) : obj(_obj), mesh(_mesh), face(_face) {
- }
-
-
-
- template<unsigned ndim>
- template<typename face_type>
- void MeshSet<ndim>::FaceIter<face_type>::fwd(size_t n) {
- if (mesh < obj->meshes.size()) {
- face += n;
- while (face >= obj->meshes[mesh]->faces.size()) {
- face -= obj->meshes[mesh++]->faces.size();
- if (mesh == obj->meshes.size()) { face = 0; break; }
- }
- }
- }
-
-
-
- template<unsigned ndim>
- template<typename face_type>
- void MeshSet<ndim>::FaceIter<face_type>::rev(size_t n) {
- while (n > face) {
- n -= face;
- if (mesh == 0) { face = 0; return; }
- face = obj->meshes[--mesh]->faces.size() - 1;
- }
- face -= n;
- }
-
-
-
- template<unsigned ndim>
- template<typename face_type>
- void MeshSet<ndim>::FaceIter<face_type>::adv(int n) {
- if (n > 0) {
- fwd((size_t)n);
- } else if (n < 0) {
- rev((size_t)-n);
- }
- }
-
-
-
- template<unsigned ndim>
- template<typename face_type>
- typename MeshSet<ndim>::template FaceIter<face_type>::difference_type
- MeshSet<ndim>::FaceIter<face_type>::operator-(const FaceIter &other) const {
- CARVE_ASSERT(obj == other.obj);
- if (mesh == other.mesh) return face - other.face;
-
- size_t m = 0;
- for (size_t i = std::min(mesh, other.mesh) + 1; i < std::max(mesh, other.mesh); ++i) {
- m += obj->meshes[i]->faces.size();
- }
-
- if (mesh < other.mesh) {
- return -(difference_type)((obj->meshes[mesh]->faces.size() - face) + m + other.face);
- } else {
- return +(difference_type)((obj->meshes[other.mesh]->faces.size() - other.face) + m + face);
- }
- }
-
-
-
- template<typename order_t>
- struct VPtrSort {
- order_t order;
-
- VPtrSort(const order_t &_order = order_t()) : order(_order) {}
-
- template<unsigned ndim>
- bool operator()(carve::mesh::Vertex<ndim> *a,
- carve::mesh::Vertex<ndim> *b) const {
- return order(a->v, b->v);
- }
- };
-
-
-
- template<unsigned ndim>
- void MeshSet<ndim>::collectVertices() {
- std::unordered_map<vertex_t *, size_t> vert_idx;
-
- for (size_t m = 0; m < meshes.size(); ++m) {
- mesh_t *mesh = meshes[m];
-
- for (size_t f = 0; f < mesh->faces.size(); ++f) {
- face_t *face = mesh->faces[f];
- edge_t *edge = face->edge;
- do {
- vert_idx[edge->vert] = 0;
- edge = edge->next;
- } while (edge != face->edge);
- }
- }
-
- std::vector<vertex_t> new_vertex_storage;
- new_vertex_storage.reserve(vert_idx.size());
- for (typename std::unordered_map<vertex_t *, size_t>::iterator
- i = vert_idx.begin(); i != vert_idx.end(); ++i) {
- (*i).second = new_vertex_storage.size();
- new_vertex_storage.push_back(*(*i).first);
- }
-
- for (size_t m = 0; m < meshes.size(); ++m) {
- mesh_t *mesh = meshes[m];
- for (size_t f = 0; f < mesh->faces.size(); ++f) {
- face_t *face = mesh->faces[f];
- edge_t *edge = face->edge;
- do {
- size_t i = vert_idx[edge->vert];
- edge->vert = &new_vertex_storage[i];
- edge = edge->next;
- } while (edge != face->edge);
- }
- }
-
- std::swap(vertex_storage, new_vertex_storage);
- }
-
-
-
- template<unsigned ndim>
- void MeshSet<ndim>::canonicalize() {
- std::vector<vertex_t *> vptr;
- std::vector<vertex_t *> vmap;
- std::vector<vertex_t> vout;
- const size_t N = vertex_storage.size();
-
- vptr.reserve(N);
- vout.reserve(N);
- vmap.resize(N);
-
- for (size_t i = 0; i != N; ++i) {
- vptr.push_back(&vertex_storage[i]);
- }
- std::sort(vptr.begin(), vptr.end(), VPtrSort<std::less<typename vertex_t::vector_t> >());
-
- for (size_t i = 0; i != N; ++i) {
- vout.push_back(*vptr[i]);
- vmap[(size_t)(vptr[i] - &vertex_storage[0])] = &vout[i];
- }
-
- for (face_iter i = faceBegin(); i != faceEnd(); ++i) {
- for (typename face_t::edge_iter_t j = (*i)->begin(); j != (*i)->end(); ++j) {
- (*j).vert = vmap[(size_t)((*j).vert - &vertex_storage[0])];
- }
- (*i)->canonicalize();
- }
-
- vertex_storage.swap(vout);
- }
-
-
-
- template<unsigned ndim>
- void MeshSet<ndim>::separateMeshes() {
- size_t n;
- typedef std::unordered_map<std::pair<mesh_t *, vertex_t *>, vertex_t *> vmap_t;
- vmap_t vmap;
- typename vmap_t::iterator vmap_iter;
-
- for (face_iter i = faceBegin(); i != faceEnd(); ++i) {
- face_t *f = *i;
- for (typename face_t::edge_iter_t j = f->begin(); j != f->end(); ++j) {
- edge_t &e = *j;
- vmap[std::make_pair(f->mesh, e.vert)] = e.vert;
- }
- }
-
- std::vector<vertex_t> vout;
- vout.reserve(vmap.size());
-
- for (n = 0, vmap_iter = vmap.begin(); vmap_iter != vmap.end(); ++vmap_iter, ++n) {
- vout.push_back(*(*vmap_iter).second);
- (*vmap_iter).second = & vout.back();
- }
-
- for (face_iter i = faceBegin(); i != faceEnd(); ++i) {
- face_t *f = *i;
- for (typename face_t::edge_iter_t j = f->begin(); j != f->end(); ++j) {
- edge_t &e = *j;
- e.vert = vmap[std::make_pair(f->mesh, e.vert)];
- }
- }
-
- vertex_storage.swap(vout);
- }
-
- }
-}
diff --git a/extern/carve/include/carve/mesh_ops.hpp b/extern/carve/include/carve/mesh_ops.hpp
deleted file mode 100644
index cb79682a1f7..00000000000
--- a/extern/carve/include/carve/mesh_ops.hpp
+++ /dev/null
@@ -1,975 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/mesh.hpp>
-
-#include <iostream>
-#include <fstream>
-
-namespace carve {
- namespace mesh {
- namespace detail {
- // make a triangle out of three edges.
- template<unsigned ndim>
- void link(Edge<ndim> *e1, Edge<ndim> *e2, Edge<ndim> *e3, Face<ndim> *f = NULL) {
- e1->next = e2; e2->next = e3; e3->next = e1;
- e3->prev = e2; e2->prev = e1; e1->prev = e3;
- e1->face = e2->face = e3->face = f;
- if (f) {
- f->edge = e1;
- f->recalc();
- }
- }
-
-
-
- template<unsigned ndim, typename proj_t>
- double loopArea(carve::mesh::Edge<ndim> *edge, proj_t proj) {
- double A = 0.0;
- carve::mesh::Edge<3> *e = edge;
- do {
- carve::geom2d::P2 p1 = proj(e->vert->v);
- carve::geom2d::P2 p2 = proj(e->next->vert->v);
- A += (p2.y + p1.y) * (p2.x - p1.x);
- e = e->next;
- } while (e != edge);
- return A / 2.0;
- }
-
-
-
- template<unsigned ndim, typename proj_t>
- struct TriangulationData {
- typedef Edge<ndim> edge_t;
-
- struct VertexInfo {
- double score;
- carve::geom2d::P2 p;
- bool convex;
- bool failed;
- VertexInfo *next, *prev;
- edge_t *edge;
-
- VertexInfo(edge_t *_edge,
- const carve::geom2d::P2 &_p) :
- score(0.0), p(_p), convex(false), failed(false), next(NULL), prev(NULL), edge(_edge) {
- }
-
- bool isCandidate() const {
- return convex && !failed;
- }
-
- void fail() {
- failed = true;
- }
-
- static bool isLeft(const VertexInfo *a, const VertexInfo *b, const geom2d::P2 &p) {
- if (a < b) {
- return carve::geom2d::orient2d(a->p, b->p, p) > 0.0;
- } else {
- return carve::geom2d::orient2d(b->p, a->p, p) < 0.0;
- }
- }
-
- // is the ear prev->edge->next convex?
- bool testForConvexVertex() const {
- return isLeft(next, prev, p);
- }
-
- static double triScore(const geom2d::P2 &a, const geom2d::P2 &b, const geom2d::P2 &c) {
- // score is in the range: [0, 1]
- // equilateral triangles score 1
- // sliver triangles score 0
- double dab = (a - b).length();
- double dbc = (b - c).length();
- double dca = (c - a).length();
-
- if (dab < 1e-10 || dbc < 1e-10 || dca < 1e-10) return 0.0;
-
- return std::max(std::min((dab + dbc) / dca, std::min((dab + dca) / dbc, (dbc + dca) / dab)) - 1.0, 0.0);
- }
-
- // calculate a score for the ear edge.
- double calcScore() const {
- double this_tri = triScore(prev->p, p, next->p);
- double next_tri = triScore(prev->p, next->p, next->next->p);
- double prev_tri = triScore(prev->prev->p, prev->p, next->p);
-
- return this_tri + std::max(next_tri, prev_tri) * .2;
- }
-
- void recompute() {
- convex = testForConvexVertex();
- failed = false;
- if (convex) {
- score = calcScore();
- } else {
- score = -1e-5;
- }
- }
-
- static bool inTriangle(const VertexInfo *a,
- const VertexInfo *b,
- const VertexInfo *c,
- const geom2d::P2 &e) {
- return !isLeft(b, a, e) && !isLeft(c, b, e) && !isLeft(a, c, e);
- }
-
-
- bool isClipable() const {
- for (const VertexInfo *v_test = next->next; v_test != prev; v_test = v_test->next) {
- if (v_test->convex) {
- continue;
- }
-
- if (v_test->p == prev->p || v_test->p == next->p) {
- continue;
- }
-
- if (v_test->p == p) {
- if (v_test->next->p == prev->p && v_test->prev->p == next->p) {
- return false;
- }
-
- if (v_test->next->p == prev->p || v_test->prev->p == next->p) {
- continue;
- }
- }
-
- if (inTriangle(prev, this, next, v_test->p)) {
- return false;
- }
- }
- return true;
- }
- };
-
- struct order_by_score {
- bool operator()(const VertexInfo *a, const VertexInfo *b) const {
- return a->score < b->score;
- }
- };
-
- typedef std::pair<VertexInfo *, VertexInfo *> diag_t;
-
- proj_t proj;
-
- geom2d::P2 P(const VertexInfo *vi) const {
- return vi->p;
- }
-
- geom2d::P2 P(const edge_t *edge) const {
- return proj(edge->vert->v);
- }
-
- bool isLeft(const edge_t *a, const edge_t *b, const geom2d::P2 &p) const {
- if (a < b) {
- return carve::geom2d::orient2d(P(a), P(b), p) > 0.0;
- } else {
- return carve::geom2d::orient2d(P(b), P(a), p) < 0.0;
- }
- }
-
- bool testForConvexVertex(const edge_t *vert) const {
- return isLeft(vert->next, vert->prev, P(vert));
- }
-
- bool inCone(const VertexInfo *vert, const geom2d::P2 &p) const {
- return geom2d::internalToAngle(P(vert->next), P(vert), P(vert->prev), p);
- }
-
- int windingNumber(VertexInfo *vert, const carve::geom2d::P2 &point) const {
- int wn = 0;
-
- VertexInfo *v = vert;
- geom2d::P2 v_p = P(vert);
- do {
- geom2d::P2 n_p = P(v->next);
-
- if (v_p.y <= point.y) {
- if (n_p.y > point.y && carve::geom2d::orient2d(v_p, n_p, point) > 0.0) {
- ++wn;
- }
- } else {
- if (n_p.y <= point.y && carve::geom2d::orient2d(v_p, n_p, point) < 0.0) {
- --wn;
- }
- }
- v = v->next;
- v_p = n_p;
- } while (v != vert);
-
- return wn;
- }
-
- bool diagonalIsCandidate(diag_t diag) const {
- VertexInfo *v1 = diag.first;
- VertexInfo *v2 = diag.second;
- return (inCone(v1, P(v2)) && inCone(v2, P(v1)));
- }
-
- bool testDiagonal(diag_t diag) const {
- // test whether v1-v2 is a valid diagonal.
- VertexInfo *v1 = diag.first;
- VertexInfo *v2 = diag.second;
- geom2d::P2 v1p = P(v1);
- geom2d::P2 v2p = P(v2);
-
- bool intersected = false;
-
- for (VertexInfo *t = v1->next; !intersected && t != v1->prev; t = t->next) {
- VertexInfo *u = t->next;
- if (t == v2 || u == v2) continue;
-
- geom2d::P2 tp = P(t);
- geom2d::P2 up = P(u);
-
- double l_a1 = carve::geom2d::orient2d(v1p, v2p, tp);
- double l_a2 = carve::geom2d::orient2d(v1p, v2p, up);
-
- double l_b1 = carve::geom2d::orient2d(tp, up, v1p);
- double l_b2 = carve::geom2d::orient2d(tp, up, v2p);
-
- if (l_a1 > l_a2) std::swap(l_a1, l_a2);
- if (l_b1 > l_b2) std::swap(l_b1, l_b2);
-
- if (l_a1 == 0.0 && l_a2 == 0.0 &&
- l_b1 == 0.0 && l_b2 == 0.0) {
- // colinear
- if (std::max(tp.x, up.x) >= std::min(v1p.x, v2p.x) && std::min(tp.x, up.x) <= std::max(v1p.x, v2p.x)) {
- // colinear and intersecting
- intersected = true;
- }
- continue;
- }
-
- if (l_a2 <= 0.0 || l_a1 >= 0.0 || l_b2 <= 0.0 || l_b1 >= 0.0) {
- // no intersection
- continue;
- }
-
- intersected = true;
- }
-
- if (!intersected) {
- // test whether midpoint winding == 1
-
- carve::geom2d::P2 mid = (v1p + v2p) / 2;
- if (windingNumber(v1, mid) == 1) {
- // this diagonal is ok
- return true;
- }
- }
- return false;
- }
-
- // Find the vertex half way around the loop (rounds upwards).
- VertexInfo *findMidpoint(VertexInfo *vert) const {
- VertexInfo *v = vert;
- VertexInfo *r = vert;
- while (1) {
- r = r->next;
- v = v->next; if (v == vert) return r;
- v = v->next; if (v == vert) return r;
- }
- }
-
- // Test all diagonals with a separation of a-b by walking both
- // pointers around the loop. In the case where a-b divides the
- // loop exactly in half, this will test each diagonal twice,
- // but avoiding this case is not worth the extra effort
- // required.
- diag_t scanDiagonals(VertexInfo *a, VertexInfo *b) const {
- VertexInfo *v1 = a;
- VertexInfo *v2 = b;
-
- do {
- diag_t d(v1, v2);
- if (diagonalIsCandidate(d) && testDiagonal(d)) {
- return d;
- }
- v1 = v1->next;
- v2 = v2->next;
- } while (v1 != a);
-
- return diag_t(NULL, NULL);
- }
-
- diag_t scanAllDiagonals(VertexInfo *a) const {
- // Rationale: We want to find a diagonal that splits the
- // loop into two as evenly as possible, to reduce the number
- // of times that diagonal splitting is required. Start by
- // scanning all diagonals separated by loop_len / 2, then
- // decrease the separation until we find something.
-
- // loops of length 2 or 3 have no possible diagonal.
- if (a->next == a || a->next->next == a) return diag_t(NULL, NULL);
-
- VertexInfo *b = findMidpoint(a);
- while (b != a->next) {
- diag_t d = scanDiagonals(a, b);
- if (d != diag_t(NULL, NULL)) return d;
- b = b->prev;
- }
-
- return diag_t(NULL, NULL);
- }
-
- diag_t findDiagonal(VertexInfo *vert) const {
- return scanAllDiagonals(vert);
- }
-
- diag_t findHighScoringDiagonal(VertexInfo *vert) const {
- typedef std::pair<double, diag_t> heap_entry_t;
- VertexInfo *v1, *v2;
- std::vector<heap_entry_t> heap;
- size_t loop_len = 0;
-
- v1 = vert;
- do {
- ++loop_len;
- v1 = v1->next;
- } while (v1 != vert);
-
- v1 = vert;
- do {
- v2 = v1->next->next;
- size_t dist = 2;
- do {
- if (diagonalIsCandidate(diag_t(v1, v2))) {
- double score = std::min(dist, loop_len - dist);
- // double score = (v1->edge->vert->v - v2->edge->vert->v).length2();
- heap.push_back(heap_entry_t(score, diag_t(v1, v2)));
- }
- v2 = v2->next;
- ++dist;
- } while (v2 != vert && v2 != v1->prev);
- v1 = v1->next;
- } while (v1->next->next != vert);
-
- std::make_heap(heap.begin(), heap.end());
-
- while (heap.size()) {
- std::pop_heap(heap.begin(), heap.end());
- heap_entry_t h = heap.back();
- heap.pop_back();
-
- if (testDiagonal(h.second)) return h.second;
- }
-
- // couldn't find a diagonal that was ok.
- return diag_t(NULL, NULL);
- }
-
- void splitEdgeLoop(VertexInfo *v1, VertexInfo *v2) {
- VertexInfo *v1_copy = new VertexInfo(new Edge<ndim>(v1->edge->vert, NULL), v1->p);
- VertexInfo *v2_copy = new VertexInfo(new Edge<ndim>(v2->edge->vert, NULL), v2->p);
-
- v1_copy->edge->rev = v2_copy->edge;
- v2_copy->edge->rev = v1_copy->edge;
-
- v1_copy->edge->prev = v1->edge->prev;
- v1_copy->edge->next = v2->edge;
-
- v2_copy->edge->prev = v2->edge->prev;
- v2_copy->edge->next = v1->edge;
-
- v1->edge->prev->next = v1_copy->edge;
- v1->edge->prev = v2_copy->edge;
-
- v2->edge->prev->next = v2_copy->edge;
- v2->edge->prev = v1_copy->edge;
-
- v1_copy->prev = v1->prev;
- v1_copy->next = v2;
-
- v2_copy->prev = v2->prev;
- v2_copy->next = v1;
-
- v1->prev->next = v1_copy;
- v1->prev = v2_copy;
-
- v2->prev->next = v2_copy;
- v2->prev = v1_copy;
- }
-
- VertexInfo *findDegenerateEar(VertexInfo *edge) {
- VertexInfo *v = edge;
-
- if (v->next == v || v->next->next == v) return NULL;
-
- do {
- if (P(v) == P(v->next)) {
- return v;
- } else if (P(v) == P(v->next->next)) {
- if (P(v->next) == P(v->next->next->next)) {
- // a 'z' in the loop: z (a) b a b c -> remove a-b-a -> z (a) a b c -> remove a-a-b (next loop) -> z a b c
- // z --(a)-- b
- // /
- // /
- // a -- b -- d
- return v->next;
- } else {
- // a 'shard' in the loop: z (a) b a c d -> remove a-b-a -> z (a) a b c d -> remove a-a-b (next loop) -> z a b c d
- // z --(a)-- b
- // /
- // /
- // a -- c -- d
- // n.b. can only do this if the shard is pointing out of the polygon. i.e. b is outside z-a-c
- if (!carve::geom2d::internalToAngle(P(v->next->next->next), P(v), P(v->prev), P(v->next))) {
- return v->next;
- }
- }
- }
- v = v->next;
- } while (v != edge);
-
- return NULL;
- }
-
- // Clip off a vertex at vert, producing a triangle (with appropriate rev pointers)
- template<typename out_iter_t>
- VertexInfo *clipEar(VertexInfo *vert, out_iter_t out) {
- CARVE_ASSERT(testForConvexVertex(vert->edge));
-
- edge_t *p_edge = vert->edge->prev;
- edge_t *n_edge = vert->edge->next;
-
- edge_t *p_copy = new edge_t(p_edge->vert, NULL);
- edge_t *n_copy = new edge_t(n_edge->vert, NULL);
-
- n_copy->next = p_copy;
- n_copy->prev = vert->edge;
-
- p_copy->next = vert->edge;
- p_copy->prev = n_copy;
-
- vert->edge->next = n_copy;
- vert->edge->prev = p_copy;
-
- p_edge->next = n_edge;
- n_edge->prev = p_edge;
-
- if (p_edge->rev) {
- p_edge->rev->rev = p_copy;
- }
- p_copy->rev = p_edge->rev;
-
- p_edge->rev = n_copy;
- n_copy->rev = p_edge;
-
- *out++ = vert->edge;
-
- if (vert->edge->face) {
- if (vert->edge->face->edge == vert->edge) {
- vert->edge->face->edge = n_edge;
- }
- vert->edge->face->n_edges--;
- vert->edge->face = NULL;
- }
-
- vert->next->prev = vert->prev;
- vert->prev->next = vert->next;
-
- VertexInfo *n = vert->next;
- delete vert;
- return n;
- }
-
- template<typename out_iter_t>
- size_t removeDegeneracies(VertexInfo *&begin, out_iter_t out) {
- VertexInfo *v;
- size_t count = 0;
-
- while ((v = findDegenerateEar(begin)) != NULL) {
- begin = clipEar(v, out);
- ++count;
- }
- return count;
- }
-
- template<typename out_iter_t>
- bool splitAndResume(VertexInfo *begin, out_iter_t out) {
- diag_t diag;
-
- diag = findDiagonal(begin);
- if (diag == diag_t(NULL, NULL)) {
- std::cerr << "failed to find diagonal" << std::endl;
- return false;
- }
-
- // add a splitting edge between v1 and v2.
- VertexInfo *v1 = diag.first;
- VertexInfo *v2 = diag.second;
-
- splitEdgeLoop(v1, v2);
-
- v1->recompute();
- v1->next->recompute();
-
- v2->recompute();
- v2->next->recompute();
-
-#if defined(CARVE_DEBUG)
- dumpPoly(v1->edge, v2->edge);
-#endif
-
-#if defined(CARVE_DEBUG)
- CARVE_ASSERT(!checkSelfIntersection(v1));
- CARVE_ASSERT(!checkSelfIntersection(v2));
-#endif
-
- bool r1 = doTriangulate(v1, out);
- bool r2 = doTriangulate(v2, out);
-
- return r1 && r2;
- }
-
- template<typename out_iter_t>
- bool doTriangulate(VertexInfo *begin, out_iter_t out);
-
- TriangulationData(proj_t _proj) : proj(_proj) {
- }
-
- VertexInfo *init(edge_t *begin) {
- edge_t *e = begin;
- VertexInfo *head = NULL, *tail = NULL, *v;
- do {
- VertexInfo *v = new VertexInfo(e, proj(e->vert->v));
- if (tail != NULL) {
- tail->next = v;
- v->prev = tail;
- } else {
- head = v;
- }
- tail = v;
-
- e = e->next;
- } while (e != begin);
- tail->next = head;
- head->prev = tail;
-
- v = head;
- do {
- v->recompute();
- v = v->next;
- } while (v != head);
- return head;
- }
-
- class EarQueue {
- TriangulationData &data;
- std::vector<VertexInfo *> queue;
-
- void checkheap() {
-#if defined(HAVE_IS_HEAP)
- CARVE_ASSERT(std::__is_heap(queue.begin(), queue.end(), order_by_score()));
-#endif
- }
-
- public:
- EarQueue(TriangulationData &_data) : data(_data), queue() {
- }
-
- size_t size() const {
- return queue.size();
- }
-
- void push(VertexInfo *v) {
-#if defined(CARVE_DEBUG)
- checkheap();
-#endif
- queue.push_back(v);
- std::push_heap(queue.begin(), queue.end(), order_by_score());
- }
-
- VertexInfo *pop() {
-#if defined(CARVE_DEBUG)
- checkheap();
-#endif
- std::pop_heap(queue.begin(), queue.end(), order_by_score());
- VertexInfo *v = queue.back();
- queue.pop_back();
- return v;
- }
-
- void remove(VertexInfo *v) {
-#if defined(CARVE_DEBUG)
- checkheap();
-#endif
- CARVE_ASSERT(std::find(queue.begin(), queue.end(), v) != queue.end());
- double score = v->score;
- if (v != queue[0]) {
- v->score = queue[0]->score + 1;
- std::make_heap(queue.begin(), queue.end(), order_by_score());
- }
- CARVE_ASSERT(v == queue[0]);
- std::pop_heap(queue.begin(), queue.end(), order_by_score());
- CARVE_ASSERT(queue.back() == v);
- queue.pop_back();
- v->score = score;
- }
-
- void changeScore(VertexInfo *v, double s_from, double s_to) {
-#if defined(CARVE_DEBUG)
- checkheap();
-#endif
- CARVE_ASSERT(std::find(queue.begin(), queue.end(), v) != queue.end());
- if (s_from != s_to) {
- v->score = s_to;
- std::make_heap(queue.begin(), queue.end(), order_by_score());
- }
- }
-
- void update(VertexInfo *v) {
- VertexInfo pre = *v;
- v->recompute();
- VertexInfo post = *v;
-
- if (pre.isCandidate()) {
- if (post.isCandidate()) {
- changeScore(v, pre.score, post.score);
- } else {
- remove(v);
- }
- } else {
- if (post.isCandidate()) {
- push(v);
- }
- }
- }
- };
-
-
- bool checkSelfIntersection(const VertexInfo *vert) {
- const VertexInfo *v1 = vert;
- do {
- const VertexInfo *v2 = vert->next->next;
- do {
- carve::geom2d::P2 a = v1->p;
- carve::geom2d::P2 b = v1->next->p;
- CARVE_ASSERT(a == proj(v1->edge->vert->v));
- CARVE_ASSERT(b == proj(v1->edge->next->vert->v));
-
- carve::geom2d::P2 c = v2->p;
- carve::geom2d::P2 d = v2->next->p;
- CARVE_ASSERT(c == proj(v2->edge->vert->v));
- CARVE_ASSERT(d == proj(v2->edge->next->vert->v));
-
- bool intersected = false;
- if (a == c || a == d || b == c || b == d) {
- } else {
- intersected = true;
-
- double l_a1 = carve::geom2d::orient2d(a, b, c);
- double l_a2 = carve::geom2d::orient2d(a, b, d);
- if (l_a1 > l_a2) std::swap(l_a1, l_a2);
- if (l_a2 <= 0.0 || l_a1 >= 0.0) {
- intersected = false;
- }
-
- double l_b1 = carve::geom2d::orient2d(c, d, a);
- double l_b2 = carve::geom2d::orient2d(c, d, b);
- if (l_b1 > l_b2) std::swap(l_b1, l_b2);
- if (l_b2 <= 0.0 || l_b1 >= 0.0) {
- intersected = false;
- }
-
- if (l_a1 == 0.0 && l_a2 == 0.0 && l_b1 == 0.0 && l_b2 == 0.0) {
- if (std::max(a.x, b.x) >= std::min(c.x, d.x) && std::min(a.x, b.x) <= std::max(c.x, d.x)) {
- // colinear and intersecting.
- } else {
- // colinear but not intersecting.
- intersected = false;
- }
- }
- }
- if (intersected) {
- carve::geom2d::P2 p[4] = { a, b, c, d };
- carve::geom::aabb<2> A(p, p+4);
- A.expand(5);
-
- std::cerr << "\
-<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\
-<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n\
-<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n\
- x=\"" << A.min().x << "px\" y=\"" << A.min().y << "\"\n\
- width=\"" << A.extent.x * 2 << "\" height=\"" << A.extent.y * 2 << "\"\n\
- viewBox=\"" << A.min().x << " " << A.min().y << " " << A.max().x << " " << A.max().y << "\"\n\
- enable-background=\"new " << A.min().x << " " << A.min().y << " " << A.max().x << " " << A.max().y << "\"\n\
- xml:space=\"preserve\">\n\
-<line fill=\"none\" stroke=\"#000000\" x1=\"" << a.x << "\" y1=\"" << a.y << "\" x2=\"" << b.x << "\" y2=\"" << b.y << "\"/>\n\
-<line fill=\"none\" stroke=\"#000000\" x1=\"" << c.x << "\" y1=\"" << c.y << "\" x2=\"" << d.x << "\" y2=\"" << d.y << "\"/>\n\
-</svg>\n";
- return true;
- }
- v2 = v2->next;
- } while (v2 != vert);
- v1 = v1->next;
- } while (v1 != vert);
- return false;
- }
-
- carve::geom::aabb<2> make2d(const edge_t *edge, std::vector<geom2d::P2> &points) {
- const edge_t *e = edge;
- do {
- points.push_back(P(e));
- e = e->next;
- } while(e != edge);
- return carve::geom::aabb<2>(points.begin(), points.end());
- }
-
- void dumpLoop(std::ostream &out,
- const std::vector<carve::geom2d::P2> &points,
- const char *fill,
- const char *stroke,
- double stroke_width,
- double offx,
- double offy,
- double scale
- ) {
- out << "<polygon fill=\"" << fill << "\" stroke=\"" << stroke << "\" stroke-width=\"" << stroke_width << "\" points=\"";
- for (size_t i = 0; i < points.size(); ++i) {
- if (i) out << ' ';
- double x, y;
- x = scale * (points[i].x - offx) + 5;
- y = scale * (points[i].y - offy) + 5;
- out << x << ',' << y;
- }
- out << "\" />" << std::endl;
- }
-
- void dumpPoly(const edge_t *edge, const edge_t *edge2 = NULL, const char *pfx = "poly_") {
- static int step = 0;
- std::ostringstream filename;
- filename << pfx << step++ << ".svg";
- std::cerr << "dumping to " << filename.str() << std::endl;
- std::ofstream out(filename.str().c_str());
-
- std::vector <geom2d::P2> points, points2;
-
- carve::geom::aabb<2> A = make2d(edge, points);
- if (edge2) {
- A.unionAABB(make2d(edge2, points2));
- }
- A.expand(5);
-
- out << "\
-<?xml version=\"1.0\"?>\n\
-<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n\
-<svg\n\
- x=\"" << A.min().x << "px\" y=\"" << A.min().y << "\"\n\
- width=\"" << A.extent.x * 2 << "\" height=\"" << A.extent.y * 2 << "\"\n\
- viewBox=\"" << A.min().x << " " << A.min().y << " " << A.max().x << " " << A.max().y << "\"\n\
- enable-background=\"new " << A.min().x << " " << A.min().y << " " << A.max().x << " " << A.max().y << "\"\n\
- xml:space=\"preserve\">\n";
-
- dumpLoop(out, points, "rgb(0,0,0)", "blue", 0.1, 0, 0, 1);
- if (points2.size()) dumpLoop(out, points2, "rgb(255,0,0)", "blue", 0.1, 0, 0, 1);
-
- out << "</svg>" << std::endl;
- }
- };
-
- template<unsigned ndim, typename proj_t>
- template<typename out_iter_t>
- bool TriangulationData<ndim, proj_t>::doTriangulate(VertexInfo *begin, out_iter_t out) {
- EarQueue vq(*this);
-
-#if defined(CARVE_DEBUG)
- dumpPoly(begin->edge, NULL, "input_");
- CARVE_ASSERT(!checkSelfIntersection(begin));
-#endif
-
- VertexInfo *v = begin, *n, *p;
- size_t remain = 0;
- do {
- if (v->isCandidate()) vq.push(v);
- v = v->next;
- remain++;
- } while (v != begin);
-
- while (remain > 3 && vq.size()) {
- { static int __c = 0; if (++__c % 50 == 0) { break; } }
- v = vq.pop();
- if (!v->isClipable()) {
- v->fail();
- continue;
- }
-
- continue_clipping:
- n = clipEar(v, out);
- p = n->prev;
- begin = n;
- if (--remain == 3) break;
- // if (checkSelfIntersection(begin)) {
- // dumpPoly(begin->edge, NULL, "badclip_");
- // CARVE_ASSERT(!!!"clip created self intersection");
- // }
-
- vq.update(n);
- vq.update(p);
-
- if (n->score < p->score) { std::swap(n, p); }
- if (n->score > 0.25 && n->isCandidate() && n->isClipable()) {
- vq.remove(n);
- v = n;
- goto continue_clipping;
- }
- if (p->score > 0.25 && p->isCandidate() && p->isClipable()) {
- vq.remove(p);
- v = p;
- goto continue_clipping;
- }
- }
-
- bool ret = false;
-
-#if defined(CARVE_DEBUG)
- dumpPoly(begin->edge, NULL, "remainder_");
-#endif
-
- if (remain > 3) {
- std::vector<carve::geom2d::P2> temp;
- temp.reserve(remain);
- VertexInfo *v = begin;
- do {
- temp.push_back(P(v));
- v = v->next;
- } while (v != begin);
-
- if (carve::geom2d::signedArea(temp) == 0) {
- // XXX: this test will fail in cases where the boundary is
- // twisted so that a negative area balances a positive area.
- std::cerr << "got to here" << std::endl;
- dumpPoly(begin->edge, NULL, "interesting_case_");
- goto done;
- }
- }
-
- if (remain > 3) {
- remain -= removeDegeneracies(begin, out);
- }
-
- if (remain > 3) {
- return splitAndResume(begin, out);
- }
-
- { double a = loopArea(begin->edge, proj); CARVE_ASSERT(a <= 0.0); }
- *out++ = begin->edge;
-
- v = begin;
- do {
- n = v->next;
- delete v;
- v = n;
- } while (v != begin);
-
- ret = true;
-
- done:
- return ret;
- }
- }
-
-
-
- template<unsigned ndim, typename proj_t, typename out_iter_t>
- void triangulate(Edge<ndim> *edge, proj_t proj, out_iter_t out) {
- detail::TriangulationData<ndim, proj_t> triangulator(proj);
- typename detail::TriangulationData<ndim, proj_t>::VertexInfo *v = triangulator.init(edge);
- triangulator.removeDegeneracies(v, out);
- triangulator.doTriangulate(v, out);
- }
-
- // given edge a-b, part of triangles a-b-c and b-a-d, make triangles c-a-d and b-c-d
- template<unsigned ndim>
- void flipTriEdge(Edge<ndim> *edge) {
- CARVE_ASSERT(edge->rev != NULL);
- CARVE_ASSERT(edge->face->nEdges() == 3);
- CARVE_ASSERT(edge->rev->face->nEdges() == 3);
-
- CARVE_ASSERT(edge->prev != edge);
- CARVE_ASSERT(edge->next != edge);
- CARVE_ASSERT(edge->rev->prev != edge->rev);
- CARVE_ASSERT(edge->rev->next != edge->rev);
-
- typedef Edge<ndim> edge_t;
- typedef Face<ndim> face_t;
-
- edge_t *t1[3], *t2[3];
- face_t *f1, *f2;
-
- t1[1] = edge; t2[1] = edge->rev;
- t1[0] = t1[1]->prev; t1[2] = t1[1]->next;
- t2[0] = t2[1]->prev; t2[2] = t2[1]->next;
-
- f1 = t1[1]->face; f2 = t2[1]->face;
-
- // std::cerr << t1[0]->vert << "->" << t1[1]->vert << "->" << t1[2]->vert << std::endl;
- // std::cerr << t2[0]->vert << "->" << t2[1]->vert << "->" << t2[2]->vert << std::endl;
-
- t1[1]->vert = t2[0]->vert;
- t2[1]->vert = t1[0]->vert;
-
- // std::cerr << t1[0]->vert << "->" << t2[2]->vert << "->" << t1[1]->vert << std::endl;
- // std::cerr << t2[0]->vert << "->" << t1[2]->vert << "->" << t2[1]->vert << std::endl;
-
- detail::link(t1[0], t2[2], t1[1], f1);
- detail::link(t2[0], t1[2], t2[1], f2);
-
- if (t1[0]->rev) CARVE_ASSERT(t1[0]->v2() == t1[0]->rev->v1());
- if (t2[0]->rev) CARVE_ASSERT(t2[0]->v2() == t2[0]->rev->v1());
- if (t1[2]->rev) CARVE_ASSERT(t1[2]->v2() == t1[2]->rev->v1());
- if (t2[2]->rev) CARVE_ASSERT(t2[2]->v2() == t2[2]->rev->v1());
- }
-
- template<unsigned ndim>
- void splitEdgeLoop(Edge<ndim> *v1, Edge<ndim> *v2) {
- // v1 and v2 end up on different sides of the split.
- Edge<ndim> *v1_copy = new Edge<ndim>(v1->vert, NULL);
- Edge<ndim> *v2_copy = new Edge<ndim>(v2->vert, NULL);
-
- v1_copy->rev = v2_copy;
- v2_copy->rev = v1_copy;
-
- v1_copy->prev = v1->prev;
- v1_copy->next = v2;
-
- v2_copy->prev = v2->prev;
- v2_copy->next = v1;
-
- v1->prev->next = v1_copy;
- v1->prev = v2_copy;
-
- v2->prev->next = v2_copy;
- v2->prev = v1_copy;
- }
-
- template<unsigned ndim>
- Edge<ndim> *clipVertex(Edge<ndim> *edge) {
- Edge<ndim> *prev = edge->prev;
- Edge<ndim> *next = edge->next;
- splitEdgeLoop(edge->prev, edge->next);
- return next;
- }
- }
-}
diff --git a/extern/carve/include/carve/mesh_simplify.hpp b/extern/carve/include/carve/mesh_simplify.hpp
deleted file mode 100644
index 9c7371b3df5..00000000000
--- a/extern/carve/include/carve/mesh_simplify.hpp
+++ /dev/null
@@ -1,1599 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-#include <carve/mesh.hpp>
-#include <carve/mesh_ops.hpp>
-#include <carve/geom2d.hpp>
-#include <carve/heap.hpp>
-#include <carve/rtree.hpp>
-#include <carve/triangle_intersection.hpp>
-
-#include <fstream>
-#include <string>
-#include <utility>
-#include <set>
-#include <algorithm>
-#include <vector>
-
-
-namespace carve {
- namespace mesh {
-
-
- class MeshSimplifier {
- typedef carve::mesh::MeshSet<3> meshset_t;
- typedef carve::mesh::Mesh<3> mesh_t;
- typedef mesh_t::vertex_t vertex_t;
- typedef vertex_t::vector_t vector_t;
- typedef mesh_t::edge_t edge_t;
- typedef mesh_t::face_t face_t;
- typedef face_t::aabb_t aabb_t;
-
- typedef carve::geom::RTreeNode<3, carve::mesh::Face<3> *> face_rtree_t;
-
-
- struct EdgeInfo {
- edge_t *edge;
- double delta_v;
-
- double c[4];
- double l[2], t1[2], t2[2];
- size_t heap_idx;
-
- void update() {
- const vertex_t *v1 = edge->vert;
- const vertex_t *v2 = edge->next->vert;
- const vertex_t *v3 = edge->next->next->vert;
- const vertex_t *v4 = edge->rev ? edge->rev->next->next->vert : NULL;
-
- l[0] = (v1->v - v2->v).length();
-
- t1[0] = (v3->v - v1->v).length();
- t1[1] = (v3->v - v2->v).length();
-
- c[0] = std::max((t1[0] + t1[1]) / l[0] - 1.0, 0.0);
-
- if (v4) {
- l[1] = (v3->v - v4->v).length();
- t2[0] = (v4->v - v1->v).length();
- t2[1] = (v4->v - v2->v).length();
- c[1] = std::max((t2[0] + t2[1]) / l[0] - 1.0, 0.0);
- c[2] = std::max((t1[0] + t2[0]) / l[1] - 1.0, 0.0);
- c[3] = std::max((t1[1] + t2[1]) / l[1] - 1.0, 0.0);
- delta_v = carve::geom3d::tetrahedronVolume(v1->v, v2->v, v3->v, v4->v);
- } else {
- l[1] = 0.0;
- t2[0] = t2[1] = 0.0;
- c[1] = c[2] = c[3] = 0.0;
- delta_v = 0.0;
- }
- }
-
- EdgeInfo(edge_t *e) : edge(e) {
- update();
- }
-
- EdgeInfo() : edge(NULL) {
- delta_v = 0.0;
- c[0] = c[1] = c[2] = c[3] = 0.0;
- l[0] = l[1] = 0.0;
- t1[0] = t1[1] = 0.0;
- t2[0] = t2[1] = 0.0;
- }
-
- struct NotifyPos {
- void operator()(EdgeInfo *edge, size_t pos) const { edge->heap_idx = pos; }
- void operator()(EdgeInfo &edge, size_t pos) const { edge.heap_idx = pos; }
- };
- };
-
-
-
- struct FlippableBase {
- double min_dp;
-
- FlippableBase(double _min_dp = 0.0) : min_dp(_min_dp) {
- }
-
- bool open(const EdgeInfo *e) const {
- return e->edge->rev == NULL;
- }
-
- bool wouldCreateDegenerateEdge(const EdgeInfo *e) const {
- return e->edge->prev->vert == e->edge->rev->prev->vert;
- }
-
- bool flippable_DotProd(const EdgeInfo *e) const {
- using carve::geom::dot;
- using carve::geom::cross;
-
- if (open(e)) return false;
-
- edge_t *edge = e->edge;
-
- const vertex_t *v1 = edge->vert;
- const vertex_t *v2 = edge->next->vert;
- const vertex_t *v3 = edge->next->next->vert;
- const vertex_t *v4 = edge->rev->next->next->vert;
-
- if (dot(cross(v3->v - v2->v, v1->v - v2->v).normalized(),
- cross(v4->v - v1->v, v2->v - v1->v).normalized()) < min_dp) return false;
-
- if (dot(cross(v3->v - v4->v, v1->v - v4->v).normalized(),
- cross(v4->v - v3->v, v2->v - v3->v).normalized()) < min_dp) return false;
-
- return true;
- }
-
- virtual bool canFlip(const EdgeInfo *e) const {
- return !open(e) && !wouldCreateDegenerateEdge(e) && score(e) > 0.0;
- }
-
- virtual double score(const EdgeInfo *e) const {
- return std::min(e->c[2], e->c[3]) - std::min(e->c[0], e->c[1]);
- }
-
- class Priority {
- Priority &operator=(const Priority &);
- const FlippableBase &flip;
-
- public:
- Priority(const FlippableBase &_flip) : flip(_flip) {}
- bool operator()(const EdgeInfo *a, const EdgeInfo *b) const { return flip.score(a) > flip.score(b); }
- };
-
- Priority priority() const {
- return Priority(*this);
- }
- };
-
-
-
- struct FlippableConservative : public FlippableBase {
- FlippableConservative() : FlippableBase(0.0) {
- }
-
- bool connectsAlmostCoplanarFaces(const EdgeInfo *e) const {
- // XXX: remove hard coded constants.
- if (e->c[0] < 1e-10 || e->c[1] < 1e-10) return true;
- return fabs(carve::geom::dot(e->edge->face->plane.N, e->edge->rev->face->plane.N) - 1.0) < 1e-10;
- }
-
- bool connectsExactlyCoplanarFaces(const EdgeInfo *e) const {
- edge_t *edge = e->edge;
- return
- carve::geom3d::orient3d(edge->vert->v,
- edge->next->vert->v,
- edge->next->next->vert->v,
- edge->rev->next->next->vert->v) == 0.0 &&
- carve::geom3d::orient3d(edge->rev->vert->v,
- edge->rev->next->vert->v,
- edge->rev->next->next->vert->v,
- edge->next->next->vert->v) == 0.0;
- }
-
- virtual bool canFlip(const EdgeInfo *e) const {
- return FlippableBase::canFlip(e) && connectsExactlyCoplanarFaces(e) && flippable_DotProd(e);
- }
- };
-
-
-
- struct FlippableColinearPair : public FlippableBase {
-
- FlippableColinearPair() {
- }
-
-
- virtual double score(const EdgeInfo *e) const {
- return e->l[0] - e->l[1];
- }
-
- virtual bool canFlip(const EdgeInfo *e) const {
- if (!FlippableBase::canFlip(e)) return false;
-
- if (e->c[0] > 1e-3 || e->c[1] > 1e-3) return false;
-
- return true;
- }
- };
-
-
-
- struct Flippable : public FlippableBase {
- double min_colinearity;
- double min_delta_v;
-
- Flippable(double _min_colinearity,
- double _min_delta_v,
- double _min_normal_angle) :
- FlippableBase(cos(_min_normal_angle)),
- min_colinearity(_min_colinearity),
- min_delta_v(_min_delta_v) {
- }
-
-
- virtual bool canFlip(const EdgeInfo *e) const {
- if (!FlippableBase::canFlip(e)) return false;
-
- if (fabs(e->delta_v) > min_delta_v) return false;
-
- // if (std::min(e->c[0], e->c[1]) > min_colinearity) return false;
-
- return flippable_DotProd(e);
- }
- };
-
-
-
- struct EdgeMerger {
- double min_edgelen;
-
- virtual bool canMerge(const EdgeInfo *e) const {
- return e->l[0] <= min_edgelen;
- }
-
- EdgeMerger(double _min_edgelen) : min_edgelen(_min_edgelen) {
- }
-
- double score(const EdgeInfo *e) const {
- return min_edgelen - e->l[0];
- }
-
- class Priority {
- Priority &operator=(const Priority &);
-
- public:
- const EdgeMerger &merger;
- Priority(const EdgeMerger &_merger) : merger(_merger) {
- }
- bool operator()(const EdgeInfo *a, const EdgeInfo *b) const {
- // collapse edges in order from shortest to longest.
- return merger.score(a) < merger.score(b);
- }
- };
-
- Priority priority() const {
- return Priority(*this);
- }
- };
-
-
-
- typedef std::unordered_map<edge_t *, EdgeInfo *> edge_info_map_t;
- std::unordered_map<edge_t *, EdgeInfo *> edge_info;
-
-
-
- void initEdgeInfo(mesh_t *mesh) {
- for (size_t i = 0; i < mesh->faces.size(); ++i) {
- edge_t *e = mesh->faces[i]->edge;
- do {
- edge_info[e] = new EdgeInfo(e);
- e = e->next;
- } while (e != mesh->faces[i]->edge);
- }
- }
-
-
-
- void initEdgeInfo(meshset_t *meshset) {
- for (size_t m = 0; m < meshset->meshes.size(); ++m) {
- mesh_t *mesh = meshset->meshes[m];
- initEdgeInfo(mesh);
- }
- }
-
-
-
- void clearEdgeInfo() {
- for (edge_info_map_t::iterator i = edge_info.begin(); i != edge_info.end(); ++i) {
- delete (*i).second;
- }
- }
-
-
-
- void updateEdgeFlipHeap(std::vector<EdgeInfo *> &edge_heap,
- edge_t *edge,
- const FlippableBase &flipper) {
- std::unordered_map<edge_t *, EdgeInfo *>::const_iterator i = edge_info.find(edge);
- CARVE_ASSERT(i != edge_info.end());
- EdgeInfo *e = (*i).second;
-
- bool heap_pre = e->heap_idx != ~0U;
- (*i).second->update();
- bool heap_post = edge->v1() < edge->v2() && flipper.canFlip(e);
-
- if (!heap_pre && heap_post) {
- edge_heap.push_back(e);
- carve::heap::push_heap(edge_heap.begin(),
- edge_heap.end(),
- flipper.priority(),
- EdgeInfo::NotifyPos());
- } else if (heap_pre && !heap_post) {
- CARVE_ASSERT(edge_heap[e->heap_idx] == e);
- carve::heap::remove_heap(edge_heap.begin(),
- edge_heap.end(),
- edge_heap.begin() + e->heap_idx,
- flipper.priority(),
- EdgeInfo::NotifyPos());
- CARVE_ASSERT(edge_heap.back() == e);
- edge_heap.pop_back();
- e->heap_idx = ~0U;
- } else if (heap_pre && heap_post) {
- CARVE_ASSERT(edge_heap[e->heap_idx] == e);
- carve::heap::adjust_heap(edge_heap.begin(),
- edge_heap.end(),
- edge_heap.begin() + e->heap_idx,
- flipper.priority(),
- EdgeInfo::NotifyPos());
- CARVE_ASSERT(edge_heap[e->heap_idx] == e);
- }
- }
-
-
- std::string vk(const vertex_t *v1,
- const vertex_t *v2,
- const vertex_t *v3) {
- const vertex_t *v[3];
- v[0] = v1; v[1] = v2; v[2] = v3;
- std::sort(v, v+3);
- std::ostringstream s;
- s << v[0] << ";" << v[1] << ";" << v[2];
- return s.str();
- }
-
- std::string vk(const face_t *f) { return vk(f->edge->vert, f->edge->next->vert, f->edge->next->next->vert); }
-
- int mapTriangle(const face_t *face,
- const vertex_t *remap1, const vertex_t *remap2,
- const vector_t &tgt,
- vector_t tri[3]) {
- edge_t *edge = face->edge;
- int n_remaps = 0;
- for (size_t i = 0; i < 3; edge = edge->next, ++i) {
- if (edge->vert == remap1) { tri[i] = tgt; ++n_remaps; }
- else if (edge->vert == remap2) { tri[i] = tgt; ++n_remaps; }
- else { tri[i] = edge->vert->v; }
- }
- return n_remaps;
- }
-
- template<typename iter1_t, typename iter2_t>
- int countIntersectionPairs(iter1_t fabegin, iter1_t faend,
- iter2_t fbbegin, iter2_t fbend,
- const vertex_t *remap1, const vertex_t *remap2,
- const vector_t &tgt) {
- vector_t tri_a[3], tri_b[3];
- int remap_a, remap_b;
- std::set<std::pair<const face_t *, const face_t *> > ints;
-
- for (iter1_t i = fabegin; i != faend; ++i) {
- remap_a = mapTriangle(*i, remap1, remap2, tgt, tri_a);
- if (remap_a >= 2) continue;
- for (iter2_t j = fbbegin; j != fbend; ++j) {
- remap_b = mapTriangle(*j, remap1, remap2, tgt, tri_b);
- if (remap_b >= 2) continue;
- if (carve::geom::triangle_intersection_exact(tri_a, tri_b) == carve::geom::TR_TYPE_INT) {
- ints.insert(std::make_pair(std::min(*i, *j), std::max(*i, *j)));
- }
- }
- }
-
- return ints.size();
- }
-
- int countIntersections(const vertex_t *v1,
- const vertex_t *v2,
- const vertex_t *v3,
- const std::vector<face_t *> &faces) {
- int n_int = 0;
- vector_t tri_a[3], tri_b[3];
- tri_a[0] = v1->v;
- tri_a[1] = v2->v;
- tri_a[2] = v3->v;
-
- for (std::vector<face_t *>::const_iterator i = faces.begin(); i != faces.end(); ++i) {
- face_t *fb = *i;
- if (fb->nEdges() != 3) continue;
- tri_b[0] = fb->edge->vert->v;
- tri_b[1] = fb->edge->next->vert->v;
- tri_b[2] = fb->edge->next->next->vert->v;
-
- if (carve::geom::triangle_intersection_exact(tri_a, tri_b) == carve::geom::TR_TYPE_INT) {
- n_int++;
- }
- }
- return n_int;
- }
-
-
-
- int _findSelfIntersections(const face_rtree_t *a_node,
- const face_rtree_t *b_node,
- bool descend_a = true) {
- int r = 0;
-
- if (!a_node->bbox.intersects(b_node->bbox)) {
- return 0;
- }
-
- if (a_node->child && (descend_a || !b_node->child)) {
- for (face_rtree_t *node = a_node->child; node; node = node->sibling) {
- r += _findSelfIntersections(node, b_node, false);
- }
- } else if (b_node->child) {
- for (face_rtree_t *node = b_node->child; node; node = node->sibling) {
- r += _findSelfIntersections(a_node, node, true);
- }
- } else {
- for (size_t i = 0; i < a_node->data.size(); ++i) {
- face_t *fa = a_node->data[i];
- if (fa->nVertices() != 3) continue;
-
- aabb_t aabb_a = fa->getAABB();
-
- vector_t tri_a[3];
- tri_a[0] = fa->edge->vert->v;
- tri_a[1] = fa->edge->next->vert->v;
- tri_a[2] = fa->edge->next->next->vert->v;
-
- if (!aabb_a.intersects(b_node->bbox)) continue;
-
- for (size_t j = 0; j < b_node->data.size(); ++j) {
- face_t *fb = b_node->data[j];
- if (fb->nVertices() != 3) continue;
-
- vector_t tri_b[3];
- tri_b[0] = fb->edge->vert->v;
- tri_b[1] = fb->edge->next->vert->v;
- tri_b[2] = fb->edge->next->next->vert->v;
-
- if (carve::geom::triangle_intersection_exact(tri_a, tri_b) == carve::geom::TR_TYPE_INT) {
- ++r;
- }
- }
- }
- }
-
- return r;
- }
-
-
-
- int countSelfIntersections(meshset_t *meshset) {
- int n_ints = 0;
- face_rtree_t *tree = face_rtree_t::construct_STR(meshset->faceBegin(), meshset->faceEnd(), 4, 4);
-
- for (meshset_t::face_iter f = meshset->faceBegin(); f != meshset->faceEnd(); ++f) {
- face_t *fa = *f;
- if (fa->nVertices() != 3) continue;
-
- vector_t tri_a[3];
- tri_a[0] = fa->edge->vert->v;
- tri_a[1] = fa->edge->next->vert->v;
- tri_a[2] = fa->edge->next->next->vert->v;
-
- std::vector<face_t *> near_faces;
- tree->search(fa->getAABB(), std::back_inserter(near_faces));
-
- for (size_t f2 = 0; f2 < near_faces.size(); ++f2) {
- const face_t *fb = near_faces[f2];
- if (fb->nVertices() != 3) continue;
-
- if (fa >= fb) continue;
-
- vector_t tri_b[3];
- tri_b[0] = fb->edge->vert->v;
- tri_b[1] = fb->edge->next->vert->v;
- tri_b[2] = fb->edge->next->next->vert->v;
-
- if (carve::geom::triangle_intersection_exact(tri_a, tri_b) == carve::geom::TR_TYPE_INT) {
- ++n_ints;
- }
- }
- }
-
- delete tree;
-
- return n_ints;
- }
-
- size_t flipEdges(meshset_t *mesh,
- const FlippableBase &flipper) {
- face_rtree_t *tree = face_rtree_t::construct_STR(mesh->faceBegin(), mesh->faceEnd(), 4, 4);
-
- size_t n_mods = 0;
-
- std::vector<EdgeInfo *> edge_heap;
-
- edge_heap.reserve(edge_info.size());
-
- for (edge_info_map_t::iterator i = edge_info.begin();
- i != edge_info.end();
- ++i) {
- EdgeInfo *e = (*i).second;
- e->update();
- if (e->edge->v1() < e->edge->v2() && flipper.canFlip(e)) {
- edge_heap.push_back(e);
- } else {
- e->heap_idx = ~0U;
- }
- }
-
- carve::heap::make_heap(edge_heap.begin(),
- edge_heap.end(),
- flipper.priority(),
- EdgeInfo::NotifyPos());
-
- while (edge_heap.size()) {
-// std::cerr << "test" << std::endl;
-// for (size_t m = 0; m < mesh->meshes.size(); ++m) {
-// for (size_t f = 0; f < mesh->meshes[m]->faces.size(); ++f) {
-// if (mesh->meshes[m]->faces[f]->edge) mesh->meshes[m]->faces[f]->edge->validateLoop();
-// }
-// }
-
- carve::heap::pop_heap(edge_heap.begin(),
- edge_heap.end(),
- flipper.priority(),
- EdgeInfo::NotifyPos());
- EdgeInfo *e = edge_heap.back();
-// std::cerr << "flip " << e << std::endl;
- edge_heap.pop_back();
- e->heap_idx = ~0U;
-
- aabb_t aabb;
- aabb = e->edge->face->getAABB();
- aabb.unionAABB(e->edge->rev->face->getAABB());
-
- std::vector<face_t *> overlapping;
- tree->search(aabb, std::back_inserter(overlapping));
-
- // overlapping.erase(e->edge->face);
- // overlapping.erase(e->edge->rev->face);
-
- const vertex_t *v1 = e->edge->vert;
- const vertex_t *v2 = e->edge->next->vert;
- const vertex_t *v3 = e->edge->next->next->vert;
- const vertex_t *v4 = e->edge->rev->next->next->vert;
-
- int n_int1 = countIntersections(v1, v2, v3, overlapping);
- int n_int2 = countIntersections(v2, v1, v4, overlapping);
- int n_int3 = countIntersections(v3, v4, v2, overlapping);
- int n_int4 = countIntersections(v4, v3, v1, overlapping);
-
- if ((n_int3 + n_int4) - (n_int1 + n_int2) > 0) {
- std::cerr << "delta[ints] = " << (n_int3 + n_int4) - (n_int1 + n_int2) << std::endl;
- // avoid creating a self intersection.
- continue;
- }
-
- n_mods++;
- CARVE_ASSERT(flipper.canFlip(e));
- edge_info[e->edge]->update();
- edge_info[e->edge->rev]->update();
-
- carve::mesh::flipTriEdge(e->edge);
-
- tree->updateExtents(aabb);
-
- updateEdgeFlipHeap(edge_heap, e->edge, flipper);
- updateEdgeFlipHeap(edge_heap, e->edge->rev, flipper);
-
- CARVE_ASSERT(!flipper.canFlip(e));
-
- updateEdgeFlipHeap(edge_heap, e->edge->next, flipper);
- updateEdgeFlipHeap(edge_heap, e->edge->next->next, flipper);
- updateEdgeFlipHeap(edge_heap, e->edge->rev->next, flipper);
- updateEdgeFlipHeap(edge_heap, e->edge->rev->next->next, flipper);
- updateEdgeFlipHeap(edge_heap, e->edge->next->rev, flipper);
- updateEdgeFlipHeap(edge_heap, e->edge->next->next->rev, flipper);
- updateEdgeFlipHeap(edge_heap, e->edge->rev->next->rev, flipper);
- updateEdgeFlipHeap(edge_heap, e->edge->rev->next->next->rev, flipper);
- }
-
- delete tree;
-
- return n_mods;
- }
-
-
-
- void removeFromEdgeMergeHeap(std::vector<EdgeInfo *> &edge_heap,
- EdgeInfo *edge,
- const EdgeMerger &merger) {
- if (edge->heap_idx != ~0U) {
- CARVE_ASSERT(edge_heap[edge->heap_idx] == edge);
- carve::heap::remove_heap(edge_heap.begin(),
- edge_heap.end(),
- edge_heap.begin() + edge->heap_idx,
- merger.priority(),
- EdgeInfo::NotifyPos());
- CARVE_ASSERT(edge_heap.back() == edge);
- edge_heap.pop_back();
- edge->heap_idx = ~0U;
- }
- }
-
- void updateEdgeMergeHeap(std::vector<EdgeInfo *> &edge_heap,
- EdgeInfo *edge,
- const EdgeMerger &merger) {
- bool heap_pre = edge->heap_idx != ~0U;
- edge->update();
- bool heap_post = merger.canMerge(edge);
-
- if (!heap_pre && heap_post) {
- edge_heap.push_back(edge);
- carve::heap::push_heap(edge_heap.begin(),
- edge_heap.end(),
- merger.priority(),
- EdgeInfo::NotifyPos());
- } else if (heap_pre && !heap_post) {
- CARVE_ASSERT(edge_heap[edge->heap_idx] == edge);
- carve::heap::remove_heap(edge_heap.begin(),
- edge_heap.end(),
- edge_heap.begin() + edge->heap_idx,
- merger.priority(),
- EdgeInfo::NotifyPos());
- CARVE_ASSERT(edge_heap.back() == edge);
- edge_heap.pop_back();
- edge->heap_idx = ~0U;
- } else if (heap_pre && heap_post) {
- CARVE_ASSERT(edge_heap[edge->heap_idx] == edge);
- carve::heap::adjust_heap(edge_heap.begin(),
- edge_heap.end(),
- edge_heap.begin() + edge->heap_idx,
- merger.priority(),
- EdgeInfo::NotifyPos());
- CARVE_ASSERT(edge_heap[edge->heap_idx] == edge);
- }
- }
-
-
-
- // collapse edges edges based upon the predicate implemented by EdgeMerger.
- size_t collapseEdges(meshset_t *mesh,
- const EdgeMerger &merger) {
- face_rtree_t *tree = face_rtree_t::construct_STR(mesh->faceBegin(), mesh->faceEnd(), 4, 4);
-
- size_t n_mods = 0;
-
- std::vector<EdgeInfo *> edge_heap;
- std::unordered_map<vertex_t *, std::set<EdgeInfo *> > vert_to_edges;
-
- edge_heap.reserve(edge_info.size());
-
- for (edge_info_map_t::iterator i = edge_info.begin();
- i != edge_info.end();
- ++i) {
- EdgeInfo *e = (*i).second;
-
- vert_to_edges[e->edge->v1()].insert(e);
- vert_to_edges[e->edge->v2()].insert(e);
-
- if (merger.canMerge(e)) {
- edge_heap.push_back(e);
- } else {
- e->heap_idx = ~0U;
- }
- }
-
- carve::heap::make_heap(edge_heap.begin(),
- edge_heap.end(),
- merger.priority(),
- EdgeInfo::NotifyPos());
-
- while (edge_heap.size()) {
-// std::cerr << "test" << std::endl;
-// for (size_t m = 0; m < mesh->meshes.size(); ++m) {
-// for (size_t f = 0; f < mesh->meshes[m]->faces.size(); ++f) {
-// if (mesh->meshes[m]->faces[f]->edge) mesh->meshes[m]->faces[f]->edge->validateLoop();
-// }
-// }
- carve::heap::pop_heap(edge_heap.begin(),
- edge_heap.end(),
- merger.priority(),
- EdgeInfo::NotifyPos());
- EdgeInfo *e = edge_heap.back();
- edge_heap.pop_back();
- e->heap_idx = ~0U;
-
- edge_t *edge = e->edge;
- vertex_t *v1 = edge->v1();
- vertex_t *v2 = edge->v2();
-
- std::set<face_t *> affected_faces;
- for (std::set<EdgeInfo *>::iterator f = vert_to_edges[v1].begin();
- f != vert_to_edges[v1].end();
- ++f) {
- affected_faces.insert((*f)->edge->face);
- affected_faces.insert((*f)->edge->rev->face);
- }
- for (std::set<EdgeInfo *>::iterator f = vert_to_edges[v2].begin();
- f != vert_to_edges[v2].end();
- ++f) {
- affected_faces.insert((*f)->edge->face);
- affected_faces.insert((*f)->edge->rev->face);
- }
-
- std::vector<EdgeInfo *> edges_to_merge;
- std::vector<EdgeInfo *> v1_incident;
- std::vector<EdgeInfo *> v2_incident;
-
- std::set_intersection(vert_to_edges[v1].begin(), vert_to_edges[v1].end(),
- vert_to_edges[v2].begin(), vert_to_edges[v2].end(),
- std::back_inserter(edges_to_merge));
-
- CARVE_ASSERT(edges_to_merge.size() > 0);
-
- std::set_difference(vert_to_edges[v1].begin(), vert_to_edges[v1].end(),
- edges_to_merge.begin(), edges_to_merge.end(),
- std::back_inserter(v1_incident));
- std::set_difference(vert_to_edges[v2].begin(), vert_to_edges[v2].end(),
- edges_to_merge.begin(), edges_to_merge.end(),
- std::back_inserter(v2_incident));
-
- vector_t aabb_min, aabb_max;
- assign_op(aabb_min, v1->v, v2->v, carve::util::min_functor());
- assign_op(aabb_max, v1->v, v2->v, carve::util::max_functor());
-
- for (size_t i = 0; i < v1_incident.size(); ++i) {
- assign_op(aabb_min, aabb_min, v1_incident[i]->edge->v1()->v, carve::util::min_functor());
- assign_op(aabb_max, aabb_max, v1_incident[i]->edge->v1()->v, carve::util::max_functor());
- assign_op(aabb_min, aabb_min, v1_incident[i]->edge->v2()->v, carve::util::min_functor());
- assign_op(aabb_max, aabb_max, v1_incident[i]->edge->v2()->v, carve::util::max_functor());
- }
-
- for (size_t i = 0; i < v2_incident.size(); ++i) {
- assign_op(aabb_min, aabb_min, v2_incident[i]->edge->v1()->v, carve::util::min_functor());
- assign_op(aabb_max, aabb_max, v2_incident[i]->edge->v1()->v, carve::util::max_functor());
- assign_op(aabb_min, aabb_min, v2_incident[i]->edge->v2()->v, carve::util::min_functor());
- assign_op(aabb_max, aabb_max, v2_incident[i]->edge->v2()->v, carve::util::max_functor());
- }
-
- aabb_t aabb;
- aabb.fit(aabb_min, aabb_max);
-
- std::vector<face_t *> near_faces;
- tree->search(aabb, std::back_inserter(near_faces));
-
- double frac = 0.5; // compute this based upon v1_incident and v2_incident?
- vector_t merge = frac * v1->v + (1 - frac) * v2->v;
-
- int i1 = countIntersectionPairs(affected_faces.begin(), affected_faces.end(),
- near_faces.begin(), near_faces.end(),
- NULL, NULL, merge);
- int i2 = countIntersectionPairs(affected_faces.begin(), affected_faces.end(),
- near_faces.begin(), near_faces.end(),
- v1, v2, merge);
- if (i2 != i1) {
- std::cerr << "near faces: " << near_faces.size() << " affected faces: " << affected_faces.size() << std::endl;
- std::cerr << "merge delta[ints] = " << i2 - i1 << " pre: " << i1 << " post: " << i2 << std::endl;
- if (i2 > i1) continue;
- }
-
- std::cerr << "collapse " << e << std::endl;
-
- v2->v = merge;
- ++n_mods;
-
- for (size_t i = 0; i < v1_incident.size(); ++i) {
- if (v1_incident[i]->edge->vert == v1) {
- v1_incident[i]->edge->vert = v2;
- }
- }
-
- for (size_t i = 0; i < v1_incident.size(); ++i) {
- updateEdgeMergeHeap(edge_heap, v1_incident[i], merger);
- }
-
- for (size_t i = 0; i < v2_incident.size(); ++i) {
- updateEdgeMergeHeap(edge_heap, v2_incident[i], merger);
- }
-
- vert_to_edges[v2].insert(vert_to_edges[v1].begin(), vert_to_edges[v1].end());
- vert_to_edges.erase(v1);
-
- for (size_t i = 0; i < edges_to_merge.size(); ++i) {
- EdgeInfo *e = edges_to_merge[i];
-
- removeFromEdgeMergeHeap(edge_heap, e, merger);
- edge_info.erase(e->edge);
-
- vert_to_edges[v1].erase(e);
- vert_to_edges[v2].erase(e);
-
- face_t *f1 = e->edge->face;
-
- e->edge->removeHalfEdge();
-
- if (f1->n_edges == 2) {
- edge_t *e1 = f1->edge;
- edge_t *e2 = f1->edge->next;
- if (e1->rev) e1->rev->rev = e2->rev;
- if (e2->rev) e2->rev->rev = e1->rev;
- EdgeInfo *e1i = edge_info[e1];
- EdgeInfo *e2i = edge_info[e2];
- CARVE_ASSERT(e1i != NULL);
- CARVE_ASSERT(e2i != NULL);
- vert_to_edges[e1->v1()].erase(e1i);
- vert_to_edges[e1->v2()].erase(e1i);
- vert_to_edges[e2->v1()].erase(e2i);
- vert_to_edges[e2->v2()].erase(e2i);
- removeFromEdgeMergeHeap(edge_heap, e1i, merger);
- removeFromEdgeMergeHeap(edge_heap, e2i, merger);
- edge_info.erase(e1);
- edge_info.erase(e2);
- f1->clearEdges();
- tree->remove(f1, aabb);
-
- delete e1i;
- delete e2i;
- }
- delete e;
- }
-
- tree->updateExtents(aabb);
- }
-
- delete tree;
-
- return n_mods;
- }
-
-
-
- size_t mergeCoplanarFaces(mesh_t *mesh, double min_normal_angle) {
- std::unordered_set<edge_t *> coplanar_face_edges;
- double min_dp = cos(min_normal_angle);
- size_t n_merge = 0;
-
- for (size_t i = 0; i < mesh->closed_edges.size(); ++i) {
- edge_t *e = mesh->closed_edges[i];
- face_t *f1 = e->face;
- face_t *f2 = e->rev->face;
-
- if (carve::geom::dot(f1->plane.N, f2->plane.N) < min_dp) {
- continue;
- }
-
- coplanar_face_edges.insert(std::min(e, e->rev));
- }
-
- while (coplanar_face_edges.size()) {
- edge_t *edge = *coplanar_face_edges.begin();
- if (edge->face == edge->rev->face) {
- coplanar_face_edges.erase(edge);
- continue;
- }
-
- edge_t *removed = edge->mergeFaces();
- if (removed == NULL) {
- coplanar_face_edges.erase(edge);
- ++n_merge;
- } else {
- edge_t *e = removed;
- do {
- edge_t *n = e->next;
- coplanar_face_edges.erase(std::min(e, e->rev));
- delete e->rev;
- delete e;
- e = n;
- } while (e != removed);
- }
- }
- return n_merge;
- }
-
-
-
- uint8_t affected_axes(const face_t *face) {
- uint8_t r = 0;
- if (fabs(carve::geom::dot(face->plane.N, carve::geom::VECTOR(1,0,0))) > 0.001) r |= 1;
- if (fabs(carve::geom::dot(face->plane.N, carve::geom::VECTOR(0,1,0))) > 0.001) r |= 2;
- if (fabs(carve::geom::dot(face->plane.N, carve::geom::VECTOR(0,0,1))) > 0.001) r |= 4;
- return r;
- }
-
-
-
- double median(std::vector<double> &v) {
- if (v.size() & 1) {
- size_t N = v.size() / 2 + 1;
- std::nth_element(v.begin(), v.begin() + N, v.end());
- return v[N];
- } else {
- size_t N = v.size() / 2;
- std::nth_element(v.begin(), v.begin() + N, v.end());
- return (v[N] + *std::min_element(v.begin() + N + 1, v.end())) / 2.0;
- }
- }
-
-
-
- double harmonicmean(const std::vector<double> &v) {
- double m = 0.0;
- for (size_t i = 0; i < v.size(); ++i) {
- m *= v[i];
- }
- return pow(m, 1.0 / v.size());
- }
-
-
-
- double mean(const std::vector<double> &v) {
- double m = 0.0;
- for (size_t i = 0; i < v.size(); ++i) {
- m += v[i];
- }
- return m / v.size();
- }
-
-
-
- template<typename iter_t>
- void snapFaces(iter_t begin, iter_t end, double grid, int axis) {
- std::set<vertex_t *> vertices;
- for (iter_t i = begin; i != end; ++i) {
- face_t *face = *i;
- edge_t *edge = face->edge;
- do {
- vertices.insert(edge->vert);
- edge = edge->next;
- } while (edge != face->edge);
- }
-
- std::vector<double> pos;
- pos.reserve(vertices.size());
- for (std::set<vertex_t *>::iterator i = vertices.begin(); i != vertices.end(); ++i) {
- pos.push_back((*i)->v.v[axis]);
- }
-
- double med = median(pos);
-
- double snap_pos = med;
- if (grid) snap_pos = round(snap_pos / grid) * grid;
-
- for (std::set<vertex_t *>::iterator i = vertices.begin(); i != vertices.end(); ++i) {
- (*i)->v.v[axis] = snap_pos;
- }
-
- for (iter_t i = begin; i != end; ++i) {
- face_t *face = *i;
- face->recalc();
- edge_t *edge = face->edge;
- do {
- if (edge->rev && edge->rev->face) edge->rev->face->recalc();
- edge = edge->next;
- } while (edge != face->edge);
- }
- }
-
- carve::geom::plane<3> quantizePlane(const face_t *face,
- int angle_xy_quantization,
- int angle_z_quantization) {
- if (!angle_xy_quantization && !angle_z_quantization) {
- return face->plane;
- }
- carve::geom::vector<3> normal = face->plane.N;
-
- if (angle_z_quantization) {
- if (normal.x || normal.y) {
- double a = asin(std::min(std::max(normal.z, 0.0), 1.0));
- a = round(a * angle_z_quantization / (M_PI * 2)) * (M_PI * 2) / angle_z_quantization;
- normal.z = sin(a);
- double s = sqrt((1 - normal.z * normal.z) / (normal.x * normal.x + normal.y * normal.y));
- normal.x = normal.x * s;
- normal.y = normal.y * s;
- }
- }
- if (angle_xy_quantization) {
- if (normal.x || normal.y) {
- double a = atan2(normal.y, normal.x);
- a = round(a * angle_xy_quantization / (M_PI * 2)) * (M_PI * 2) / angle_xy_quantization;
- double s = sqrt(1 - normal.z * normal.z);
- s = std::min(std::max(s, 0.0), 1.0);
- normal.x = cos(a) * s;
- normal.y = sin(a) * s;
- }
- }
-
- std::cerr << "normal = " << normal << std::endl;
-
- std::vector<double> d_vec;
- d_vec.reserve(face->nVertices());
- edge_t *e = face->edge;
- do {
- d_vec.push_back(-carve::geom::dot(normal, e->vert->v));
- e = e->next;
- } while (e != face->edge);
-
- return carve::geom::plane<3>(normal, mean(d_vec));
- }
-
-
-
- double summedError(const carve::geom::vector<3> &vert, const std::list<carve::geom::plane<3> > &planes) {
- double d = 0;
- for (std::list<carve::geom::plane<3> >::const_iterator i = planes.begin(); i != planes.end(); ++i) {
- d += fabs(carve::geom::distance2(*i, vert));
- }
- return d;
- }
-
-
-
- double minimize(carve::geom::vector<3> &vert, const std::list<carve::geom::plane<3> > &planes, int axis) {
- double num = 0.0;
- double den = 0.0;
- int a1 = (axis + 1) % 3;
- int a2 = (axis + 2) % 3;
- for (std::list<carve::geom::plane<3> >::const_iterator i = planes.begin(); i != planes.end(); ++i) {
- const carve::geom::vector<3> &N = (*i).N;
- const double d = (*i).d;
- den += N.v[axis] * N.v[axis];
- num -= N.v[axis] * (N.v[a1] * vert.v[a1] + N.v[a2] * vert.v[a2] + d);
- }
- if (fabs(den) < 1e-5) return vert.v[axis];
- return num / den;
- }
-
-
-
- size_t cleanFaceEdges(mesh_t *mesh) {
- size_t n_removed = 0;
- for (size_t i = 0; i < mesh->faces.size(); ++i) {
- face_t *face = mesh->faces[i];
- edge_t *start = face->edge;
- edge_t *edge = start;
- do {
- if (edge->next == edge->rev || edge->prev == edge->rev) {
- edge = edge->removeEdge();
- ++n_removed;
- start = edge->prev;
- } else {
- edge = edge->next;
- }
- } while (edge != start);
- }
- return n_removed;
- }
-
-
-
- size_t cleanFaceEdges(meshset_t *mesh) {
- size_t n_removed = 0;
- for (size_t i = 0; i < mesh->meshes.size(); ++i) {
- n_removed += cleanFaceEdges(mesh->meshes[i]);
- }
- return n_removed;
- }
-
-
-
- void removeRemnantFaces(mesh_t *mesh) {
- size_t n = 0;
- for (size_t i = 0; i < mesh->faces.size(); ++i) {
- if (mesh->faces[i]->nEdges() == 0) {
- delete mesh->faces[i];
- } else {
- mesh->faces[n++] = mesh->faces[i];
- }
- }
- mesh->faces.resize(n);
- }
-
-
-
- void removeRemnantFaces(meshset_t *mesh) {
- for (size_t i = 0; i < mesh->meshes.size(); ++i) {
- removeRemnantFaces(mesh->meshes[i]);
- }
- }
-
-
-
- edge_t *removeFin(edge_t *e) {
- // e and e->next are shared with the same reverse triangle.
- edge_t *e1 = e->prev;
- edge_t *e2 = e->rev->next;
- CARVE_ASSERT(e1->v2() == e2->v1());
- CARVE_ASSERT(e2->v2() == e1->v1());
-
- CARVE_ASSERT(e1->rev != e2 && e2->rev != e1);
-
- edge_t *e1r = e1->rev;
- edge_t *e2r = e2->rev;
- if (e1r) e1r->rev = e2r;
- if (e2r) e2r->rev = e1r;
-
- face_t *f1 = e1->face;
- face_t *f2 = e2->face;
- f1->clearEdges();
- f2->clearEdges();
-
- return e1r;
- }
-
- size_t removeFin(face_t *face) {
- if (face->edge == NULL || face->nEdges() != 3) return 0;
- edge_t *e = face->edge;
- do {
- if (e->rev != NULL) {
- face_t *revface = e->rev->face;
- if (revface->nEdges() == 3) {
- if (e->next->rev && e->next->rev->face == revface) {
- if (e->next->next->rev && e->next->next->rev->face == revface) {
- // isolated tripair
- face->clearEdges();
- revface->clearEdges();
- return 1;
- }
- // fin
- edge_t *spliced_edge = removeFin(e);
- return 1 + removeFin(spliced_edge->face);
- }
- }
- }
- e = e->next;
- } while (e != face->edge);
- return 0;
- }
-
-
-
- public:
- // Merge adjacent coplanar faces (where coplanar is determined
- // by dot-product >= cos(min_normal_angle)).
- size_t mergeCoplanarFaces(meshset_t *meshset, double min_normal_angle) {
- size_t n_removed = 0;
- for (size_t i = 0; i < meshset->meshes.size(); ++i) {
- n_removed += mergeCoplanarFaces(meshset->meshes[i], min_normal_angle);
- removeRemnantFaces(meshset->meshes[i]);
- cleanFaceEdges(meshset->meshes[i]);
- meshset->meshes[i]->cacheEdges();
- }
- return n_removed;
- }
-
- size_t improveMesh_conservative(meshset_t *meshset) {
- initEdgeInfo(meshset);
- size_t modifications = flipEdges(meshset, FlippableConservative());
- clearEdgeInfo();
- return modifications;
- }
-
- void dissolveMeshEdges(mesh_t *mesh, std::unordered_set<edge_t *> dissolve_edges) {
- while (dissolve_edges.size()) {
- MeshSet<3>::edge_t *edge = *dissolve_edges.begin();
- if (edge->face == edge->rev->face) {
- dissolve_edges.erase(edge);
- continue;
- }
-
- MeshSet<3>::edge_t *removed = edge->mergeFaces();
- if (removed == NULL) {
- dissolve_edges.erase(edge);
- } else {
- MeshSet<3>::edge_t *e = removed;
- do {
- MeshSet<3>::edge_t *n = e->next;
- dissolve_edges.erase(std::min(e, e->rev));
- delete e->rev;
- delete e;
- e = n;
- } while (e != removed);
- }
- }
-
- removeRemnantFaces(mesh);
- cleanFaceEdges(mesh);
- mesh->cacheEdges();
- }
-
-
- size_t improveMesh(meshset_t *meshset,
- double min_colinearity,
- double min_delta_v,
- double min_normal_angle) {
- initEdgeInfo(meshset);
- size_t modifications = flipEdges(meshset, Flippable(min_colinearity, min_delta_v, min_normal_angle));
- clearEdgeInfo();
- return modifications;
- }
-
-
-
- size_t eliminateShortEdges(meshset_t *meshset,
- double min_length) {
- initEdgeInfo(meshset);
- size_t modifications = collapseEdges(meshset, EdgeMerger(min_length));
- removeRemnantFaces(meshset);
- clearEdgeInfo();
- return modifications;
- }
-
-
-
- // Snap vertices to grid, aligning almost flat axis-aligned
- // faces to the axis, and flattening other faces as much as is
- // possible. Passing a number less than DBL_MIN_EXPONENT (-1021)
- // turns off snapping to grid (but face alignment is still
- // performed).
- void snap(meshset_t *meshset,
- int log2_grid,
- int angle_xy_quantization = 0,
- int angle_z_quantization = 0) {
- double grid = 0.0;
- if (log2_grid >= std::numeric_limits<double>::min_exponent) grid = pow(2.0, (double)log2_grid);
-
- typedef std::unordered_map<face_t *, uint8_t> axis_influence_map_t;
- axis_influence_map_t axis_influence;
-
- typedef std::unordered_map<face_t *, std::set<face_t *> > interaction_graph_t;
- interaction_graph_t interacting_faces;
-
- for (size_t m = 0; m < meshset->meshes.size(); ++m) {
- mesh_t *mesh = meshset->meshes[m];
- for (size_t f = 0; f < mesh->faces.size(); ++f) {
- face_t *face = mesh->faces[f];
- axis_influence[face] = affected_axes(face);
- }
- }
-
- std::map<vertex_t *, std::list<carve::geom::plane<3> > > non_axis_vertices;
- std::unordered_map<vertex_t *, uint8_t> vertex_constraints;
-
- for (axis_influence_map_t::iterator i = axis_influence.begin(); i != axis_influence.end(); ++i) {
- face_t *face = (*i).first;
- uint8_t face_axes = (*i).second;
- edge_t *edge = face->edge;
- if (face_axes != 1 && face_axes != 2 && face_axes != 4) {
- do {
- non_axis_vertices[edge->vert].push_back(quantizePlane(face,
- angle_xy_quantization,
- angle_z_quantization));
- edge = edge->next;
- } while (edge != face->edge);
- } else {
- interacting_faces[face].insert(face);
- do {
- vertex_constraints[edge->vert] |= face_axes;
-
- if (edge->rev && edge->rev->face) {
- face_t *face2 = edge->rev->face;
- uint8_t face2_axes = axis_influence[face2];
- if (face2_axes == face_axes) {
- interacting_faces[face].insert(face2);
- }
- }
- edge = edge->next;
- } while (edge != face->edge);
- }
- }
-
- while (interacting_faces.size()) {
- std::set<face_t *> face_set;
- uint8_t axes = 0;
-
- std::set<face_t *> open;
- open.insert((*interacting_faces.begin()).first);
- while (open.size()) {
- face_t *curr = *open.begin();
- open.erase(open.begin());
- face_set.insert(curr);
- axes |= axis_influence[curr];
- for (interaction_graph_t::data_type::iterator i = interacting_faces[curr].begin(), e = interacting_faces[curr].end(); i != e; ++i) {
- face_t *f = *i;
- if (face_set.find(f) != face_set.end()) continue;
- open.insert(f);
- }
- }
-
- switch (axes) {
- case 1: snapFaces(face_set.begin(), face_set.end(), grid, 0); break;
- case 2: snapFaces(face_set.begin(), face_set.end(), grid, 1); break;
- case 4: snapFaces(face_set.begin(), face_set.end(), grid, 2); break;
- default: CARVE_FAIL("should not be reached");
- }
-
- for (std::set<face_t *>::iterator i = face_set.begin(); i != face_set.end(); ++i) {
- interacting_faces.erase((*i));
- }
- }
-
- for (std::map<vertex_t *, std::list<carve::geom::plane<3> > >::iterator i = non_axis_vertices.begin(); i != non_axis_vertices.end(); ++i) {
- vertex_t *vert = (*i).first;
- std::list<carve::geom::plane<3> > &planes = (*i).second;
- uint8_t constraint = vertex_constraints[vert];
-
- if (constraint == 7) continue;
-
- double d = summedError(vert->v, planes);
- for (size_t N = 0; ; N = (N+1) % 3) {
- if (constraint & (1 << N)) continue;
- vert->v[N] = minimize(vert->v, planes, N);
- double d_next = summedError(vert->v, planes);
- if (d - d_next < 1e-20) break;
- d = d_next;
- }
-
- if (grid) {
- carve::geom::vector<3> v_best = vert->v;
- double d_best = 0.0;
-
- for (int axes = 0; axes < 8; ++axes) {
- carve::geom::vector<3> v = vert->v;
- for (int N = 0; N < 3; ++N) {
- if (constraint & (1 << N)) continue;
- if (axes & (1<<N)) {
- v.v[N] = ceil(v.v[N] / grid) * grid;
- } else {
- v.v[N] = floor(v.v[N] / grid) * grid;
- }
- }
- double d = summedError(v, planes);
- if (axes == 0 || d < d_best) {
- v_best = v;
- d_best = d;
- }
- }
-
- vert->v = v_best;
- }
- }
- }
-
-
-
- size_t simplify(meshset_t *meshset,
- double min_colinearity,
- double min_delta_v,
- double min_normal_angle,
- double min_length) {
- size_t modifications = 0;
- size_t n, n_flip, n_merge;
-
- initEdgeInfo(meshset);
-
- std::cerr << "initial merge" << std::endl;
- modifications = collapseEdges(meshset, EdgeMerger(0.0));
- removeRemnantFaces(meshset);
-
- do {
- n_flip = n_merge = 0;
- // std::cerr << "flip colinear pairs";
- // n = flipEdges(meshset, FlippableColinearPair());
- // std::cerr << " " << n << std::endl;
- // n_flip = n;
-
- std::cerr << "flip conservative";
- n = flipEdges(meshset, FlippableConservative());
- std::cerr << " " << n << std::endl;
- n_flip += n;
-
- std::cerr << "flip";
- n = flipEdges(meshset, Flippable(min_colinearity, min_delta_v, min_normal_angle));
- std::cerr << " " << n << std::endl;
- n_flip += n;
-
- std::cerr << "merge";
- n = collapseEdges(meshset, EdgeMerger(min_length));
- removeRemnantFaces(meshset);
- std::cerr << " " << n << std::endl;
- n_merge = n;
-
- modifications += n_flip + n_merge;
- std::cerr << "stats:" << n_flip << " " << n_merge << std::endl;
- } while (n_flip || n_merge);
-
- clearEdgeInfo();
-
- for (size_t i = 0; i < meshset->meshes.size(); ++i) {
- meshset->meshes[i]->cacheEdges();
- }
-
- return modifications;
- }
-
-
-
- size_t removeFins(mesh_t *mesh) {
- size_t n_removed = 0;
- for (size_t i = 0; i < mesh->faces.size(); ++i) {
- n_removed += removeFin(mesh->faces[i]);
- }
- if (n_removed) removeRemnantFaces(mesh);
- return n_removed;
- }
-
-
-
- size_t removeFins(meshset_t *meshset) {
- size_t n_removed = 0;
- for (size_t i = 0; i < meshset->meshes.size(); ++i) {
- n_removed += removeFins(meshset->meshes[i]);
- }
- return n_removed;
- }
-
-
-
- size_t removeLowVolumeManifolds(meshset_t *meshset, double min_abs_volume) {
- size_t n_removed = 0;
- for (size_t i = 0; i < meshset->meshes.size(); ++i) {
- if (fabs(meshset->meshes[i]->volume()) < min_abs_volume) {
- delete meshset->meshes[i];
- meshset->meshes[i] = NULL;
- ++n_removed;
- }
- }
- meshset->meshes.erase(std::remove_if(meshset->meshes.begin(),
- meshset->meshes.end(),
- std::bind2nd(std::equal_to<mesh_t *>(), (mesh_t *)NULL)),
- meshset->meshes.end());
- return n_removed;
- }
-
- struct point_enumerator_t {
- struct heapval_t {
- double dist;
- vector_t pt;
- heapval_t(double _dist, vector_t _pt) : dist(_dist), pt(_pt) {
- }
- heapval_t() {}
- bool operator==(const heapval_t &other) const { return dist == other.dist && pt == other.pt; }
- bool operator<(const heapval_t &other) const { return dist > other.dist || (dist == other.dist && pt > other.pt); }
- };
-
- vector_t origin;
- double rounding_fac;
- heapval_t last;
- std::vector<heapval_t> heap;
-
- point_enumerator_t(vector_t _origin, int _base, int _n_dp) : origin(_origin), rounding_fac(pow((double)_base, _n_dp)), last(-1.0, _origin), heap() {
- for (int i = 0; i < (1 << 3); ++i) {
- vector_t t = origin;
- for (int j = 0; j < 3; ++j) {
- if (i & (1U << j)) {
- t[j] = ceil(t[j] * rounding_fac) / rounding_fac;
- } else {
- t[j] = floor(t[j] * rounding_fac) / rounding_fac;
- }
- }
- heap.push_back(heapval_t(carve::geom::distance2(origin, t), t));
- }
- std::make_heap(heap.begin(), heap.end());
- }
-
- vector_t next() {
- heapval_t curr;
- do {
- CARVE_ASSERT(heap.size());
- std::pop_heap(heap.begin(), heap.end());
- curr = heap.back();
- heap.pop_back();
- } while (curr == last);
-
- vector_t t;
-
- for (int dx = -1; dx <= +1; ++dx) {
- t.x = floor(curr.pt.x * rounding_fac + dx) / rounding_fac;
- for (int dy = -1; dy <= +1; ++dy) {
- t.y = floor(curr.pt.y * rounding_fac + dy) / rounding_fac;
- for (int dz = -1; dz <= +1; ++dz) {
- t.z = floor(curr.pt.z * rounding_fac + dz) / rounding_fac;
- heapval_t h2(carve::geom::distance2(origin, t), t);
- if (h2 < curr) {
- heap.push_back(h2);
- std::push_heap(heap.begin(), heap.end());
- }
- }
- }
- }
- last = curr;
- return curr.pt;
- }
- };
-
- struct quantization_info_t {
- point_enumerator_t *pt;
- std::set<face_t *> faces;
-
- quantization_info_t() : pt(NULL), faces() {
- }
-
- ~quantization_info_t() {
- if (pt) delete pt;
- }
-
- aabb_t getAABB() const {
- std::set<face_t *>::const_iterator i = faces.begin();
- aabb_t aabb = (*i)->getAABB();
- while (++i != faces.end()) {
- aabb.unionAABB((*i)->getAABB());
- }
- return aabb;
- }
- };
-
- void selfIntersectionAwareQuantize(meshset_t *meshset, int base, int n_dp) {
- typedef std::unordered_map<vertex_t *, quantization_info_t> vfsmap_t;
-
- vfsmap_t vertex_qinfo;
-
- for (size_t m = 0; m < meshset->meshes.size(); ++m) {
- mesh_t *mesh = meshset->meshes[m];
- for (size_t f = 0; f < mesh->faces.size(); ++f) {
- face_t *face = mesh->faces[f];
- edge_t *e = face->edge;
- do {
- vertex_qinfo[e->vert].faces.insert(face);
- e = e->next;
- } while (e != face->edge);
- }
- }
-
- face_rtree_t *tree = face_rtree_t::construct_STR(meshset->faceBegin(), meshset->faceEnd(), 4, 4);
-
- for (vfsmap_t::iterator i = vertex_qinfo.begin(); i != vertex_qinfo.end(); ++i) {
- (*i).second.pt = new point_enumerator_t((*i).first->v, base, n_dp);
- }
-
- while (vertex_qinfo.size()) {
- std::vector<vertex_t *> quantized;
-
- std::cerr << "vertex_qinfo.size() == " << vertex_qinfo.size() << std::endl;
-
- for (vfsmap_t::iterator i = vertex_qinfo.begin(); i != vertex_qinfo.end(); ++i) {
- vertex_t *vert = (*i).first;
- quantization_info_t &qi = (*i).second;
- vector_t q_pt = qi.pt->next();
- aabb_t aabb = qi.getAABB();
- aabb.unionAABB(aabb_t(q_pt));
-
- std::vector<face_t *> overlapping;
- tree->search(aabb, std::back_inserter(overlapping));
-
-
- int n_intersections = countIntersectionPairs(qi.faces.begin(), qi.faces.end(),
- overlapping.begin(), overlapping.end(),
- vert, NULL, q_pt);
-
- if (n_intersections == 0) {
- vert->v = q_pt;
- quantized.push_back((*i).first);
- tree->updateExtents(aabb);
- }
- }
- for (size_t i = 0; i < quantized.size(); ++i) {
- vertex_qinfo.erase(quantized[i]);
- }
-
- if (!quantized.size()) break;
- }
- }
-
-
- };
- }
-}
diff --git a/extern/carve/include/carve/octree_decl.hpp b/extern/carve/include/carve/octree_decl.hpp
deleted file mode 100644
index 46d5d4a22fe..00000000000
--- a/extern/carve/include/carve/octree_decl.hpp
+++ /dev/null
@@ -1,193 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/geom3d.hpp>
-#include <carve/aabb.hpp>
-
-#include <carve/polyhedron_base.hpp>
-
-namespace carve {
-
- namespace csg {
-
- const double SLACK_FACTOR=1.0009765625;
- const unsigned FACE_SPLIT_THRESHOLD=50U;
- const unsigned EDGE_SPLIT_THRESHOLD=50U;
- const unsigned POINT_SPLIT_THRESHOLD=20U;
- const unsigned MAX_SPLIT_DEPTH=32;
-
- class Octree {
-
- public:
- class Node {
- private:
- Node(const Node &node); // undefined.
- Node &operator=(const Node &node); // undefined.
-
- public:
- Node *parent;
- Node *children[8];
- bool is_leaf;
-
- carve::geom3d::Vector min;
- carve::geom3d::Vector max;
-
- std::vector<const carve::poly::Geometry<3>::face_t *> faces;
- std::vector<const carve::poly::Geometry<3>::edge_t *> edges;
- std::vector<const carve::poly::Geometry<3>::vertex_t *> vertices;
-
- carve::geom3d::AABB aabb;
-
- Node();
-
- Node(const carve::geom3d::Vector &newMin, const carve::geom3d::Vector &newMax);
- Node(Node *p, double x1, double y1, double z1, double x2, double y2, double z2);
-
- ~Node();
-
- bool mightContain(const carve::poly::Geometry<3>::face_t &face);
- bool mightContain(const carve::poly::Geometry<3>::edge_t &edge);
- bool mightContain(const carve::poly::Geometry<3>::vertex_t &p);
- bool hasChildren();
- bool hasGeometry();
-
- template <class T>
- void putInside(const T &input, Node *child, T &output);
-
- bool split();
- };
-
-
-
- Node *root;
-
-
-
- struct no_filter {
- bool operator()(const carve::poly::Geometry<3>::edge_t *) { return true; }
- bool operator()(const carve::poly::Geometry<3>::face_t *) { return true; }
- };
-
-
-
- Octree();
-
- ~Octree();
-
-
-
- void setBounds(const carve::geom3d::Vector &min, const carve::geom3d::Vector &max);
- void setBounds(carve::geom3d::AABB aabb);
-
-
-
- void addEdges(const std::vector<carve::poly::Geometry<3>::edge_t > &edges);
- void addFaces(const std::vector<carve::poly::Geometry<3>::face_t > &faces);
- void addVertices(const std::vector<const carve::poly::Geometry<3>::vertex_t *> &vertices);
-
-
-
- static carve::geom3d::AABB makeAABB(const Node *node);
-
-
-
- void doFindEdges(const carve::geom::aabb<3> &aabb,
- Node *node,
- std::vector<const carve::poly::Geometry<3>::edge_t *> &out,
- unsigned depth) const;
- void doFindEdges(const carve::geom3d::LineSegment &l,
- Node *node,
- std::vector<const carve::poly::Geometry<3>::edge_t *> &out,
- unsigned depth) const;
- void doFindEdges(const carve::geom3d::Vector &v,
- Node *node,
- std::vector<const carve::poly::Geometry<3>::edge_t *> &out,
- unsigned depth) const;
- void doFindFaces(const carve::geom::aabb<3> &aabb,
- Node *node,
- std::vector<const carve::poly::Geometry<3>::face_t *> &out,
- unsigned depth) const;
- void doFindFaces(const carve::geom3d::LineSegment &l,
- Node *node,
- std::vector<const carve::poly::Geometry<3>::face_t *> &out,
- unsigned depth) const;
-
-
-
- void doFindVerticesAllowDupes(const carve::geom3d::Vector &v,
- Node *node,
- std::vector<const carve::poly::Geometry<3>::vertex_t *> &out,
- unsigned depth) const;
-
- void findVerticesNearAllowDupes(const carve::geom3d::Vector &v,
- std::vector<const carve::poly::Geometry<3>::vertex_t *> &out) const;
-
-
-
- template<typename filter_t>
- void doFindEdges(const carve::poly::Geometry<3>::face_t &f, Node *node,
- std::vector<const carve::poly::Geometry<3>::edge_t *> &out,
- unsigned depth,
- filter_t filter) const;
-
- template<typename filter_t>
- void findEdgesNear(const carve::poly::Geometry<3>::face_t &f,
- std::vector<const carve::poly::Geometry<3>::edge_t *> &out,
- filter_t filter) const;
-
- void findEdgesNear(const carve::poly::Geometry<3>::face_t &f,
- std::vector<const carve::poly::Geometry<3>::edge_t *> &out) const {
- return findEdgesNear(f, out, no_filter());
- }
-
-
-
- void findEdgesNear(const carve::geom::aabb<3> &aabb, std::vector<const carve::poly::Geometry<3>::edge_t *> &out) const;
- void findEdgesNear(const carve::geom3d::LineSegment &l, std::vector<const carve::poly::Geometry<3>::edge_t *> &out) const;
- void findEdgesNear(const carve::poly::Geometry<3>::edge_t &e, std::vector<const carve::poly::Geometry<3>::edge_t *> &out) const;
- void findEdgesNear(const carve::geom3d::Vector &v, std::vector<const carve::poly::Geometry<3>::edge_t *> &out) const;
-
-
-
- void findFacesNear(const carve::geom::aabb<3> &aabb, std::vector<const carve::poly::Geometry<3>::face_t *> &out) const;
- void findFacesNear(const carve::geom3d::LineSegment &l, std::vector<const carve::poly::Geometry<3>::face_t *> &out) const;
- void findFacesNear(const carve::poly::Geometry<3>::edge_t &e, std::vector<const carve::poly::Geometry<3>::face_t *> &out) const;
-
-
-
- static void doSplit(int maxSplit, Node *node);
-
-
-
- template <typename FUNC>
- void doIterate(int level, Node *node, const FUNC &f) const;
-
- template <typename FUNC>
- void iterateNodes(const FUNC &f) const;
-
-
-
- void splitTree();
-
- };
-
- }
-}
diff --git a/extern/carve/include/carve/octree_impl.hpp b/extern/carve/include/carve/octree_impl.hpp
deleted file mode 100644
index ade170dfe5a..00000000000
--- a/extern/carve/include/carve/octree_impl.hpp
+++ /dev/null
@@ -1,79 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-namespace carve {
- namespace csg {
- template<typename filter_t>
- void Octree::doFindEdges(const carve::poly::Geometry<3>::face_t &f,
- Node *node,
- std::vector<const carve::poly::Geometry<3>::edge_t *> &out,
- unsigned depth,
- filter_t filter) const {
- if (node == NULL) {
- return;
- }
-
- if (node->aabb.intersects(f.aabb) && node->aabb.intersects(f.plane_eqn)) {
- if (node->hasChildren()) {
- for (int i = 0; i < 8; ++i) {
- doFindEdges(f, node->children[i], out, depth + 1, filter);
- }
- } else {
- if (depth < MAX_SPLIT_DEPTH && node->edges.size() > EDGE_SPLIT_THRESHOLD) {
- if (!node->split()) {
- for (int i = 0; i < 8; ++i) {
- doFindEdges(f, node->children[i], out, depth + 1, filter);
- }
- return;
- }
- }
- for (std::vector<const carve::poly::Geometry<3>::edge_t*>::const_iterator it = node->edges.begin(), e = node->edges.end(); it != e; ++it) {
- if ((*it)->tag_once()) {
- if (filter(*it)) {
- out.push_back(*it);
- }
- }
- }
- }
- }
- }
-
- template<typename filter_t>
- void Octree::findEdgesNear(const carve::poly::Geometry<3>::face_t &f, std::vector<const carve::poly::Geometry<3>::edge_t *> &out, filter_t filter) const {
- tagable::tag_begin();
- doFindEdges(f, root, out, 0, filter);
- }
-
- template <typename func_t>
- void Octree::doIterate(int level, Node *node, const func_t &f) const{
- f(level, node);
- if (node->hasChildren()) {
- for (int i = 0; i < 8; ++i) {
- doIterate(level + 1, node->children[i], f);
- }
- }
- }
-
- template <typename func_t>
- void Octree::iterateNodes(const func_t &f) const {
- doIterate(0, root, f);
- }
-
- }
-}
diff --git a/extern/carve/include/carve/pointset.hpp b/extern/carve/include/carve/pointset.hpp
deleted file mode 100644
index bc637c8eb4f..00000000000
--- a/extern/carve/include/carve/pointset.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/pointset_decl.hpp>
-#include <carve/pointset_impl.hpp>
-#include <carve/pointset_iter.hpp>
diff --git a/extern/carve/include/carve/pointset_decl.hpp b/extern/carve/include/carve/pointset_decl.hpp
deleted file mode 100644
index 1687768219a..00000000000
--- a/extern/carve/include/carve/pointset_decl.hpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
-#include <iterator>
-#include <list>
-#include <iterator>
-#include <limits>
-
-#include <carve/carve.hpp>
-#include <carve/tag.hpp>
-#include <carve/geom.hpp>
-#include <carve/kd_node.hpp>
-#include <carve/geom3d.hpp>
-#include <carve/aabb.hpp>
-
-namespace carve {
- namespace point {
-
- struct Vertex : public tagable {
- carve::geom3d::Vector v;
- };
-
-
-
- struct vec_adapt_vertex_ptr {
- const carve::geom3d::Vector &operator()(const Vertex * const &v) { return v->v; }
- carve::geom3d::Vector &operator()(Vertex *&v) { return v->v; }
- };
-
-
-
- struct PointSet {
- std::vector<Vertex> vertices;
- carve::geom3d::AABB aabb;
-
- PointSet(const std::vector<carve::geom3d::Vector> &points);
- PointSet() {
- }
-
- void sortVertices(const carve::geom3d::Vector &axis);
-
- size_t vertexToIndex_fast(const Vertex *v) const;
- };
-
- }
-}
diff --git a/extern/carve/include/carve/pointset_impl.hpp b/extern/carve/include/carve/pointset_impl.hpp
deleted file mode 100644
index d4256a018be..00000000000
--- a/extern/carve/include/carve/pointset_impl.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
-#include <vector>
-
-#include <carve/carve.hpp>
-#include <carve/tag.hpp>
-#include <carve/geom.hpp>
-#include <carve/kd_node.hpp>
-#include <carve/geom3d.hpp>
-#include <carve/aabb.hpp>
-
-namespace carve {
- namespace point {
-
- inline size_t PointSet::vertexToIndex_fast(const Vertex *v) const {
- return (size_t)(v - &vertices[0]);
- }
-
- }
-}
diff --git a/extern/carve/include/carve/pointset_iter.hpp b/extern/carve/include/carve/pointset_iter.hpp
deleted file mode 100644
index 293441b8178..00000000000
--- a/extern/carve/include/carve/pointset_iter.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
diff --git a/extern/carve/include/carve/poly.hpp b/extern/carve/include/carve/poly.hpp
deleted file mode 100644
index 0d2d6b126f6..00000000000
--- a/extern/carve/include/carve/poly.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/poly_decl.hpp>
-
-#include <carve/poly_impl.hpp>
diff --git a/extern/carve/include/carve/poly_decl.hpp b/extern/carve/include/carve/poly_decl.hpp
deleted file mode 100644
index ac904813627..00000000000
--- a/extern/carve/include/carve/poly_decl.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/vertex_decl.hpp>
-#include <carve/edge_decl.hpp>
-#include <carve/face_decl.hpp>
-#include <carve/polyhedron_decl.hpp>
diff --git a/extern/carve/include/carve/poly_impl.hpp b/extern/carve/include/carve/poly_impl.hpp
deleted file mode 100644
index c3302a021a2..00000000000
--- a/extern/carve/include/carve/poly_impl.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/vertex_impl.hpp>
-#include <carve/edge_impl.hpp>
-#include <carve/face_impl.hpp>
-#include <carve/polyhedron_impl.hpp>
diff --git a/extern/carve/include/carve/polyhedron_base.hpp b/extern/carve/include/carve/polyhedron_base.hpp
deleted file mode 100644
index 35e49e967c3..00000000000
--- a/extern/carve/include/carve/polyhedron_base.hpp
+++ /dev/null
@@ -1,149 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/geom3d.hpp>
-
-#include <carve/vertex_decl.hpp>
-#include <carve/edge_decl.hpp>
-#include <carve/face_decl.hpp>
-
-#include <stddef.h>
-
-namespace carve {
- namespace poly {
-
-
-
- struct Object {
- };
-
-
-
- template<typename array_t>
- ptrdiff_t ptrToIndex_fast(const array_t &a, const typename array_t::value_type *v) {
- return v - &a[0];
- }
-
- template<typename array_t>
- ptrdiff_t ptrToIndex(const array_t &a, const typename array_t::value_type *v) {
- if (v < &a.front() || v > &a.back()) return -1;
- return v - &a[0];
- }
-
-
- template<unsigned ndim>
- struct Geometry : public Object {
- struct Connectivity {
- } connectivity;
- };
-
-
-
- template<>
- struct Geometry<2> : public Object {
- typedef Vertex<2> vertex_t;
- typedef Edge<2> edge_t;
-
- struct Connectivity {
- std::vector<std::vector<const edge_t *> > vertex_to_edge;
- } connectivity;
-
- std::vector<vertex_t> vertices;
- std::vector<edge_t> edges;
-
- ptrdiff_t vertexToIndex_fast(const vertex_t *v) const { return ptrToIndex_fast(vertices, v); }
- ptrdiff_t vertexToIndex(const vertex_t *v) const { return ptrToIndex(vertices, v); }
-
- ptrdiff_t edgeToIndex_fast(const edge_t *e) const { return ptrToIndex_fast(edges, e); }
- ptrdiff_t edgeToIndex(const edge_t *e) const { return ptrToIndex(edges, e); }
-
-
-
- // *** connectivity queries
-
- template<typename T>
- int vertexToEdges(const vertex_t *v, T result) const;
- };
-
-
-
- template<>
- struct Geometry<3> : public Object {
- typedef Vertex<3> vertex_t;
- typedef Edge<3> edge_t;
- typedef Face<3> face_t;
-
- struct Connectivity {
- std::vector<std::vector<const edge_t *> > vertex_to_edge;
- std::vector<std::vector<const face_t *> > vertex_to_face;
- std::vector<std::vector<const face_t *> > edge_to_face;
- } connectivity;
-
- std::vector<vertex_t> vertices;
- std::vector<edge_t> edges;
- std::vector<face_t> faces;
-
- ptrdiff_t vertexToIndex_fast(const vertex_t *v) const { return ptrToIndex_fast(vertices, v); }
- ptrdiff_t vertexToIndex(const vertex_t *v) const { return ptrToIndex(vertices, v); }
-
- ptrdiff_t edgeToIndex_fast(const edge_t *e) const { return ptrToIndex_fast(edges, e); }
- ptrdiff_t edgeToIndex(const edge_t *e) const { return ptrToIndex(edges, e); }
-
- ptrdiff_t faceToIndex_fast(const face_t *f) const { return ptrToIndex_fast(faces, f); }
- ptrdiff_t faceToIndex(const face_t *f) const { return ptrToIndex(faces, f); }
-
- template<typename order_t>
- bool orderVertices(order_t order);
-
- bool orderVertices() { return orderVertices(std::less<vertex_t::vector_t>()); }
-
-
-
- // *** connectivity queries
-
- const face_t *connectedFace(const face_t *, const edge_t *) const;
-
- template<typename T>
- int _faceNeighbourhood(const face_t *f, int depth, T *result) const;
-
- template<typename T>
- int faceNeighbourhood(const face_t *f, int depth, T result) const;
-
- template<typename T>
- int faceNeighbourhood(const edge_t *e, int m_id, int depth, T result) const;
-
- template<typename T>
- int faceNeighbourhood(const vertex_t *v, int m_id, int depth, T result) const;
-
- template<typename T>
- int vertexToEdges(const vertex_t *v, T result) const;
-
- template<typename T>
- int edgeToFaces(const edge_t *e, T result) const;
-
- template<typename T>
- int vertexToFaces(const vertex_t *v, T result) const;
- };
-
-
-
- }
-}
diff --git a/extern/carve/include/carve/polyhedron_decl.hpp b/extern/carve/include/carve/polyhedron_decl.hpp
deleted file mode 100644
index 9b3d515c927..00000000000
--- a/extern/carve/include/carve/polyhedron_decl.hpp
+++ /dev/null
@@ -1,184 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/geom3d.hpp>
-
-#include <carve/polyhedron_base.hpp>
-#include <carve/octree_decl.hpp>
-#include <carve/collection_types.hpp>
-
-#include <assert.h>
-#include <list>
-
-
-namespace carve {
- namespace mesh {
- template<unsigned ndim>
- class MeshSet;
- }
-
- namespace poly {
- class Polyhedron;
- }
-
- poly::Polyhedron *polyhedronFromMesh(const mesh::MeshSet<3> *, int);
-
- namespace poly {
-
- class Polyhedron : public Geometry<3> {
- private:
- friend Polyhedron *carve::polyhedronFromMesh(const mesh::MeshSet<3> *, int);
-
- Polyhedron() {
- }
-
- Polyhedron &operator=(const Polyhedron &); // not implemented
-
- // *** initialization
-
- bool initSpatialIndex();
- void initVertexConnectivity();
- void setFaceAndVertexOwner();
-
- bool initConnectivity();
- bool markManifolds();
- bool calcManifoldEmbedding();
-
- bool init();
- void faceRecalc();
-
- void commonFaceInit(bool _recalc);
-
- public:
- static void collectFaceVertices(std::vector<face_t > &faces,
- std::vector<vertex_t > &vertices,
- std::unordered_map<const vertex_t *, const vertex_t *> &vmap);
-
- static void collectFaceVertices(std::vector<face_t > &faces,
- std::vector<vertex_t > &vertices);
-
- std::vector<bool> manifold_is_closed;
- std::vector<bool> manifold_is_negative;
-
- carve::geom3d::AABB aabb;
- carve::csg::Octree octree;
-
-
-
- // *** construction of Polyhedron objects
-
- Polyhedron(const Polyhedron &);
-
- // copy a single manifold
- Polyhedron(const Polyhedron &, int m_id);
-
- // copy a subset of manifolds
- Polyhedron(const Polyhedron &, const std::vector<bool> &selected_manifolds);
-
- Polyhedron(std::vector<face_t > &_faces,
- std::vector<vertex_t > &_vertices,
- bool _recalc = false);
-
- Polyhedron(std::vector<face_t > &_faces,
- bool _recalc = false);
-
- Polyhedron(std::list<face_t > &_faces,
- bool _recalc = false);
-
- Polyhedron(const std::vector<carve::geom3d::Vector> &vertices,
- int n_faces,
- const std::vector<int> &face_indices);
-
- ~Polyhedron();
-
-
-
- // *** containment queries
-
- void testVertexAgainstClosedManifolds(const carve::geom3d::Vector &v,
- std::map<int, PointClass> &result,
- bool ignore_orentation) const;
-
- PointClass containsVertex(const carve::geom3d::Vector &v,
- const face_t **hit_face = NULL,
- bool even_odd = false,
- int manifold_id = -1) const;
-
-
-
- // *** locality queries
-
- void findEdgesNear(const carve::geom::aabb<3> &aabb, std::vector<const edge_t *> &edges) const;
- void findEdgesNear(const carve::geom3d::LineSegment &l, std::vector<const edge_t *> &edges) const;
- void findEdgesNear(const carve::geom3d::Vector &v, std::vector<const edge_t *> &edges) const;
- void findEdgesNear(const face_t &face, std::vector<const edge_t *> &edges) const;
- void findEdgesNear(const edge_t &edge, std::vector<const edge_t *> &edges) const;
-
- void findFacesNear(const carve::geom::aabb<3> &aabb, std::vector<const face_t *> &faces) const;
- void findFacesNear(const carve::geom3d::LineSegment &l, std::vector<const face_t *> &faces) const;
- void findFacesNear(const edge_t &edge, std::vector<const face_t *> &faces) const;
-
-
-
- // *** manifold queries
-
- inline bool vertexOnManifold(const vertex_t *v, int m_id) const;
- inline bool edgeOnManifold(const edge_t *e, int m_id) const;
-
- template<typename T>
- int vertexManifolds(const vertex_t *v, T result) const;
-
- template<typename T>
- int edgeManifolds(const edge_t *e, T result) const;
-
- size_t manifoldCount() const;
-
- bool hasOpenManifolds() const;
-
-
-
-
- // *** transformation
-
- // flip face directions
- void invertAll();
- void invert(const std::vector<bool> &selected_manifolds);
-
- void invert(int m_id);
- void invert();
-
- // matrix transform of vertices
- void transform(const carve::math::Matrix &xform);
-
- // arbitrary function transform of vertices
- template<typename T>
- void transform(const T &xform);
-
- void print(std::ostream &) const;
-
- void canonicalize();
- };
-
- std::ostream &operator<<(std::ostream &, const Polyhedron &);
-
- }
-
-}
diff --git a/extern/carve/include/carve/polyhedron_impl.hpp b/extern/carve/include/carve/polyhedron_impl.hpp
deleted file mode 100644
index 141ccfabf45..00000000000
--- a/extern/carve/include/carve/polyhedron_impl.hpp
+++ /dev/null
@@ -1,286 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/timing.hpp>
-
-#include <assert.h>
-#include <list>
-
-namespace carve {
- namespace poly {
-
-
-
- template<typename order_t>
- struct VPtrSort {
- order_t order;
-
- VPtrSort(const order_t &_order) : order(_order) {}
- bool operator()(carve::poly::Polyhedron::vertex_t const *a,
- carve::poly::Polyhedron::vertex_t const *b) const {
- return order(a->v, b->v);
- }
- };
-
- template<typename order_t>
- bool Geometry<3>::orderVertices(order_t order) {
- static carve::TimingName FUNC_NAME("Geometry<3>::orderVertices()");
- carve::TimingBlock block(FUNC_NAME);
-
- std::vector<vertex_t *> vptr;
- std::vector<vertex_t *> vmap;
- std::vector<vertex_t> vout;
- const size_t N = vertices.size();
-
- vptr.reserve(N);
- vout.reserve(N);
- vmap.resize(N);
-
- for (size_t i = 0; i != N; ++i) {
- vptr.push_back(&vertices[i]);
- }
- std::sort(vptr.begin(), vptr.end(), VPtrSort<order_t>(order));
-
- for (size_t i = 0; i != N; ++i) {
- vout.push_back(*vptr[i]);
- vmap[(size_t)vertexToIndex_fast(vptr[i])] = &vout[i];
- }
-
- for (size_t i = 0; i < faces.size(); ++i) {
- face_t &f = faces[i];
- for (size_t j = 0; j < f.nVertices(); ++j) {
- f.vertex(j) = vmap[(size_t)vertexToIndex_fast(f.vertex(j))];
- }
- }
- for (size_t i = 0; i < edges.size(); ++i) {
- edges[i].v1 = vmap[(size_t)vertexToIndex_fast(edges[i].v1)];
- edges[i].v2 = vmap[(size_t)vertexToIndex_fast(edges[i].v2)];
- }
-
- vout.swap(vertices);
-
- return true;
- }
-
-
-
- template<typename T>
- int Geometry<3>::_faceNeighbourhood(const face_t *f, int depth, T *result) const {
- if (depth < 0 || f->is_tagged()) return 0;
-
- f->tag();
- *(*result)++ = f;
-
- int r = 1;
- for (size_t i = 0; i < f->nEdges(); ++i) {
- const face_t *f2 = connectedFace(f, f->edge(i));
- if (f2) {
- r += _faceNeighbourhood(f2, depth - 1, (*result));
- }
- }
- return r;
- }
-
-
-
- template<typename T>
- int Geometry<3>::faceNeighbourhood(const face_t *f, int depth, T result) const {
- tagable::tag_begin();
-
- return _faceNeighbourhood(f, depth, &result);
- }
-
-
-
- template<typename T>
- int Geometry<3>::faceNeighbourhood(const edge_t *e, int m_id, int depth, T result) const {
- tagable::tag_begin();
-
- int r = 0;
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[(size_t)edgeToIndex_fast(e)];
- for (size_t i = 0; i < edge_faces.size(); ++i) {
- const face_t *f = edge_faces[i];
- if (f && f->manifold_id == m_id) { r += _faceNeighbourhood(f, depth, &result); }
- }
- return r;
- }
-
-
-
- template<typename T>
- int Geometry<3>::faceNeighbourhood(const vertex_t *v, int m_id, int depth, T result) const {
- tagable::tag_begin();
-
- int r = 0;
- const std::vector<const face_t *> &vertex_faces = connectivity.vertex_to_face[(size_t)vertexToIndex_fast(v)];
- for (size_t i = 0; i < vertex_faces.size(); ++i) {
- const face_t *f = vertex_faces[i];
- if (f && f->manifold_id == m_id) { r += _faceNeighbourhood(f, depth, &result); }
- }
- return r;
- }
-
-
-
- // accessing connectivity information.
- template<typename T>
- int Geometry<3>::vertexToEdges(const vertex_t *v, T result) const {
- const std::vector<const edge_t *> &e = connectivity.vertex_to_edge[(size_t)vertexToIndex_fast(v)];
- std::copy(e.begin(), e.end(), result);
- return e.size();
- }
-
-
-
- template<typename T>
- int Geometry<3>::vertexToFaces(const vertex_t *v, T result) const {
- const std::vector<const face_t *> &vertex_faces = connectivity.vertex_to_face[(size_t)vertexToIndex_fast(v)];
- int c = 0;
- for (size_t i = 0; i < vertex_faces.size(); ++i) {
- *result++ = vertex_faces[i]; ++c;
- }
- return c;
- }
-
-
-
- template<typename T>
- int Geometry<3>::edgeToFaces(const edge_t *e, T result) const {
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[(size_t)edgeToIndex_fast(e)];
- int c = 0;
- for (size_t i = 0; i < edge_faces.size(); ++i) {
- if (edge_faces[i] != NULL) { *result++ = edge_faces[i]; ++c; }
- }
- return c;
- }
-
-
-
- inline const Geometry<3>::face_t *Geometry<3>::connectedFace(const face_t *f, const edge_t *e) const {
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[(size_t)edgeToIndex_fast(e)];
- for (size_t i = 0; i < (edge_faces.size() & ~1U); i++) {
- if (edge_faces[i] == f) return edge_faces[i^1];
- }
- return NULL;
- }
-
-
-
- inline void Polyhedron::invert(int m_id) {
- std::vector<bool> selected_manifolds(manifold_is_closed.size(), false);
- if (m_id >=0 && (size_t)m_id < selected_manifolds.size()) selected_manifolds[(size_t)m_id] = true;
- invert(selected_manifolds);
- }
-
-
-
- inline void Polyhedron::invert() {
- invertAll();
- }
-
-
-
- inline bool Polyhedron::edgeOnManifold(const edge_t *e, int m_id) const {
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[(size_t)edgeToIndex_fast(e)];
-
- for (size_t i = 0; i < edge_faces.size(); ++i) {
- if (edge_faces[i] && edge_faces[i]->manifold_id == m_id) return true;
- }
- return false;
- }
-
- inline bool Polyhedron::vertexOnManifold(const vertex_t *v, int m_id) const {
- const std::vector<const face_t *> &f = connectivity.vertex_to_face[(size_t)vertexToIndex_fast(v)];
-
- for (size_t i = 0; i < f.size(); ++i) {
- if (f[i]->manifold_id == m_id) return true;
- }
- return false;
- }
-
-
-
- template<typename T>
- int Polyhedron::edgeManifolds(const edge_t *e, T result) const {
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[(size_t)edgeToIndex_fast(e)];
-
- for (size_t i = 0; i < (edge_faces.size() & ~1U); i += 2) {
- const face_t *f1 = edge_faces[i];
- const face_t *f2 = edge_faces[i+1];
- assert (f1 || f2);
- if (f1)
- *result++ = f1->manifold_id;
- else if (f2)
- *result++ = f2->manifold_id;
- }
- return (int)(edge_faces.size() >> 1);
- }
-
-
-
- template<typename T>
- int Polyhedron::vertexManifolds(const vertex_t *v, T result) const {
- const std::vector<const face_t *> &f = connectivity.vertex_to_face[(size_t)vertexToIndex_fast(v)];
- std::set<int> em;
-
- for (size_t i = 0; i < f.size(); ++i) {
- em.insert(f[i]->manifold_id);
- }
-
- std::copy(em.begin(), em.end(), result);
- return em.size();
- }
-
-
-
- template<typename T>
- void Polyhedron::transform(const T &xform) {
- for (size_t i = 0; i < vertices.size(); i++) {
- vertices[i].v = xform(vertices[i].v);
- }
- faceRecalc();
- init();
- }
-
-
-
- inline size_t Polyhedron::manifoldCount() const {
- return manifold_is_closed.size();
- }
-
-
-
- inline bool Polyhedron::hasOpenManifolds() const {
- for (size_t i = 0; i < manifold_is_closed.size(); ++i) {
- if (!manifold_is_closed[i]) return true;
- }
- return false;
- }
-
-
-
- inline std::ostream &operator<<(std::ostream &o, const Polyhedron &p) {
- p.print(o);
- return o;
- }
-
-
-
- }
-}
diff --git a/extern/carve/include/carve/polyline.hpp b/extern/carve/include/carve/polyline.hpp
deleted file mode 100644
index 091563d07ad..00000000000
--- a/extern/carve/include/carve/polyline.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/polyline_decl.hpp>
-#include <carve/polyline_impl.hpp>
-#include <carve/polyline_iter.hpp>
diff --git a/extern/carve/include/carve/polyline_decl.hpp b/extern/carve/include/carve/polyline_decl.hpp
deleted file mode 100644
index f321384f113..00000000000
--- a/extern/carve/include/carve/polyline_decl.hpp
+++ /dev/null
@@ -1,156 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
-#include <iterator>
-#include <list>
-#include <iterator>
-#include <limits>
-
-#include <carve/carve.hpp>
-#include <carve/tag.hpp>
-#include <carve/geom.hpp>
-#include <carve/kd_node.hpp>
-#include <carve/geom3d.hpp>
-#include <carve/aabb.hpp>
-
-namespace carve {
- namespace line {
-
- struct PolylineEdge;
- struct Polyline;
- struct polyline_vertex_const_iter;
- struct polyline_vertex_iter;
- struct polyline_edge_const_iter;
- struct polyline_edge_iter;
-
-
-
- struct Vertex : public tagable {
- carve::geom3d::Vector v;
- std::list<std::pair<PolylineEdge *, PolylineEdge *> > edge_pairs;
-
- void addEdgePair(PolylineEdge *in, PolylineEdge *out) {
- edge_pairs.push_back(std::make_pair(in, out));
- }
- };
-
-
-
- struct vec_adapt_vertex_ptr {
- const carve::geom3d::Vector &operator()(const Vertex * const &v) { return v->v; }
- carve::geom3d::Vector &operator()(Vertex *&v) { return v->v; }
- };
-
-
-
- struct PolylineEdge : public tagable {
- Polyline *parent;
- size_t edgenum;
- Vertex *v1, *v2;
-
- PolylineEdge(Polyline *_parent, size_t _edgenum, Vertex *_v1, Vertex *_v2);
-
- carve::geom3d::AABB aabb() const;
-
- inline PolylineEdge *prevEdge() const;
- inline PolylineEdge *nextEdge() const;
- };
-
-
-
- struct Polyline {
- bool closed;
- std::vector<PolylineEdge *> edges;
-
- Polyline();
-
- size_t vertexCount() const;
-
- size_t edgeCount() const;
-
- const PolylineEdge *edge(size_t e) const;
-
- PolylineEdge *edge(size_t e);
-
- const Vertex *vertex(size_t v) const;
-
- Vertex *vertex(size_t v);
-
- bool isClosed() const;
-
- polyline_vertex_const_iter vbegin() const;
- polyline_vertex_const_iter vend() const;
- polyline_vertex_iter vbegin();
- polyline_vertex_iter vend();
-
- polyline_edge_const_iter ebegin() const;
- polyline_edge_const_iter eend() const;
- polyline_edge_iter ebegin();
- polyline_edge_iter eend();
-
- carve::geom3d::AABB aabb() const;
-
- template<typename iter_t>
- void _init(bool c, iter_t begin, iter_t end, std::vector<Vertex> &vertices);
-
- template<typename iter_t>
- void _init(bool closed, iter_t begin, iter_t end, std::vector<Vertex> &vertices, std::forward_iterator_tag);
-
- template<typename iter_t>
- void _init(bool closed, iter_t begin, iter_t end, std::vector<Vertex> &vertices, std::random_access_iterator_tag);
-
- template<typename iter_t>
- Polyline(bool closed, iter_t begin, iter_t end, std::vector<Vertex> &vertices);
-
- ~Polyline() {
- for (size_t i = 0; i < edges.size(); ++i) {
- delete edges[i];
- }
- }
- };
-
-
-
- struct PolylineSet {
- typedef std::list<Polyline *> line_list;
- typedef line_list::iterator line_iter;
- typedef line_list::const_iterator const_line_iter;
-
- std::vector<Vertex> vertices;
- line_list lines;
- carve::geom3d::AABB aabb;
-
- PolylineSet(const std::vector<carve::geom3d::Vector> &points);
- PolylineSet() {
- }
- ~PolylineSet() {
- for (line_iter i = lines.begin(); i != lines.end(); ++i) {
- delete *i;
- }
- }
-
- template<typename iter_t>
- void addPolyline(bool closed, iter_t begin, iter_t end);
-
- void sortVertices(const carve::geom3d::Vector &axis);
-
- size_t vertexToIndex_fast(const Vertex *v) const;
- };
-
- }
-}
diff --git a/extern/carve/include/carve/polyline_impl.hpp b/extern/carve/include/carve/polyline_impl.hpp
deleted file mode 100644
index ac02cbd9b7b..00000000000
--- a/extern/carve/include/carve/polyline_impl.hpp
+++ /dev/null
@@ -1,160 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
-namespace carve {
- namespace line {
-
- inline PolylineEdge::PolylineEdge(Polyline *_parent, size_t _edgenum, Vertex *_v1, Vertex *_v2) :
- tagable(), parent(_parent), edgenum(_edgenum), v1(_v1), v2(_v2) {
- }
-
- inline carve::geom3d::AABB PolylineEdge::aabb() const {
- carve::geom3d::AABB a;
- a.fit(v1->v, v2->v);
- return a;
- }
-
- inline PolylineEdge *PolylineEdge::prevEdge() const {
- if (edgenum) {
- return parent->edge(edgenum - 1);
- } else {
- if (parent->closed) {
- return parent->edge(parent->edgeCount() - 1);
- } else {
- return NULL;
- }
- }
- }
-
- inline PolylineEdge *PolylineEdge::nextEdge() const {
- if (edgenum + 1 < parent->edgeCount()) {
- return parent->edge(edgenum + 1);
- } else {
- if (parent->closed) {
- return parent->edge(0);
- } else {
- return NULL;
- }
- }
- }
-
-
-
- inline Polyline::Polyline() : edges() {
- }
-
- inline size_t Polyline::vertexCount() const {
- return edgeCount() + (closed ? 0 : 1);
- }
-
- inline size_t Polyline::edgeCount() const {
- return edges.size();
- }
-
- inline const PolylineEdge *Polyline::edge(size_t e) const {
- return edges[e % edges.size()];
- }
-
- inline PolylineEdge *Polyline::edge(size_t e) {
- return edges[e % edges.size()];
- }
-
- inline const Vertex *Polyline::vertex(size_t v) const {
- if (closed) {
- v %= edgeCount();
- } else if (v >= edgeCount()) {
- return v == edgeCount() ? edges.back()->v2 : NULL;
- }
- return edges[v]->v1;
- }
-
- inline Vertex *Polyline::vertex(size_t v) {
- if (closed) {
- v %= edgeCount();
- } else if (v >= edgeCount()) {
- return v == edgeCount() ? edges.back()->v2 : NULL;
- }
- return edges[v]->v1;
- }
-
- inline bool Polyline::isClosed() const {
- return closed;
- }
-
- template<typename iter_t>
- void Polyline::_init(bool c, iter_t begin, iter_t end, std::vector<Vertex> &vertices) {
- closed = c;
-
- PolylineEdge *e;
- if (begin == end) return;
- size_t v1 = (size_t)*begin++;
- if (begin == end) return;
-
- while (begin != end) {
- size_t v2 = (size_t)*begin++;
- e = new PolylineEdge(this, edges.size(), &vertices[v1], &vertices[v2]);
- edges.push_back(e);
- v1 = v2;
- }
-
- if (closed) {
- e = new PolylineEdge(this, edges.size(), edges.back()->v2, edges.front()->v1);
- edges.push_back(e);
-
- edges.front()->v1->addEdgePair(edges.back(), edges.front());
- for (size_t i = 1; i < edges.size(); ++i) {
- edges[i]->v1->addEdgePair(edges[i-1], edges[i]);
- }
- } else {
- edges.front()->v1->addEdgePair(NULL, edges.front());
- for (size_t i = 1; i < edges.size(); ++i) {
- edges[i]->v1->addEdgePair(edges[i-1], edges[i]);
- }
- edges.back()->v2->addEdgePair(edges.back(), NULL);
- }
- }
-
- template<typename iter_t>
- void Polyline::_init(bool closed, iter_t begin, iter_t end, std::vector<Vertex> &vertices, std::forward_iterator_tag) {
- _init(closed, begin, end, vertices);
- }
-
- template<typename iter_t>
- void Polyline::_init(bool closed, iter_t begin, iter_t end, std::vector<Vertex> &vertices, std::random_access_iterator_tag) {
- edges.reserve(end - begin - (closed ? 0 : 1));
- _init(closed, begin, end, vertices);
- }
-
- template<typename iter_t>
- Polyline::Polyline(bool closed, iter_t begin, iter_t end, std::vector<Vertex> &vertices) {
- _init(closed, begin, end, vertices, typename std::iterator_traits<iter_t>::iterator_category());
- }
-
-
-
- template<typename iter_t>
- void PolylineSet::addPolyline(bool closed, iter_t begin, iter_t end) {
- Polyline *p = new Polyline(closed, begin, end, vertices);
- lines.push_back(p);
- }
-
- inline size_t PolylineSet::vertexToIndex_fast(const Vertex *v) const {
- return (size_t)(v - &vertices[0]);
- }
- }
-}
diff --git a/extern/carve/include/carve/polyline_iter.hpp b/extern/carve/include/carve/polyline_iter.hpp
deleted file mode 100644
index c6958a18f28..00000000000
--- a/extern/carve/include/carve/polyline_iter.hpp
+++ /dev/null
@@ -1,203 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-#pragma once
-
-#include <iterator>
-#include <list>
-#include <iterator>
-#include <limits>
-#include <cstddef>
-
-#include <carve/polyline_decl.hpp>
-
-namespace carve {
- namespace line {
-
- struct polyline_vertex_iter : public std::iterator<std::random_access_iterator_tag, Vertex *> {
- Polyline *base;
- ssize_t idx;
-
- polyline_vertex_iter(Polyline *_base) : base(_base), idx(0) {
- }
-
- polyline_vertex_iter(Polyline *_base, ssize_t _idx) : base(_base), idx(_idx) {
- }
-
- polyline_vertex_iter operator++(int) { return polyline_vertex_iter(base, idx++); }
- polyline_vertex_iter &operator++() { ++idx; return *this; }
- polyline_vertex_iter &operator+=(int v) { idx += v; return *this; }
-
- polyline_vertex_iter operator--(int) { return polyline_vertex_iter(base, idx--); }
- polyline_vertex_iter &operator--() { --idx; return *this; }
- polyline_vertex_iter &operator-=(int v) { idx -= v; return *this; }
-
- Vertex *operator*() const {
- CARVE_ASSERT(idx >= 0 && idx < base->vertexCount());
- return base->vertex((size_t)idx);
- }
- };
-
-
-
- static inline ssize_t operator-(const polyline_vertex_iter &a, const polyline_vertex_iter &b) { return a.idx - b.idx; }
-
- static inline bool operator==(const polyline_vertex_iter&a, const polyline_vertex_iter &b) { return a.idx == b.idx; }
- static inline bool operator!=(const polyline_vertex_iter&a, const polyline_vertex_iter &b) { return a.idx != b.idx; }
- static inline bool operator<(const polyline_vertex_iter&a, const polyline_vertex_iter &b) { return a.idx < b.idx; }
- static inline bool operator>(const polyline_vertex_iter&a, const polyline_vertex_iter &b) { return a.idx > b.idx; }
- static inline bool operator<=(const polyline_vertex_iter&a, const polyline_vertex_iter &b) { return a.idx <= b.idx; }
- static inline bool operator>=(const polyline_vertex_iter&a, const polyline_vertex_iter &b) { return a.idx >= b.idx; }
-
-
-
- struct polyline_vertex_const_iter : public std::iterator<std::random_access_iterator_tag, Vertex *> {
- const Polyline *base;
- ssize_t idx;
-
- polyline_vertex_const_iter(const Polyline *_base) : base(_base), idx(0) {
- }
-
- polyline_vertex_const_iter(const Polyline *_base, ssize_t _idx) : base(_base), idx(_idx) {
- }
-
- polyline_vertex_const_iter operator++(int) { return polyline_vertex_const_iter(base, idx++); }
- polyline_vertex_const_iter &operator++() { ++idx; return *this; }
- polyline_vertex_const_iter &operator+=(int v) { idx += v; return *this; }
-
- polyline_vertex_const_iter operator--(int) { return polyline_vertex_const_iter(base, idx--); }
- polyline_vertex_const_iter &operator--() { --idx; return *this; }
- polyline_vertex_const_iter &operator-=(int v) { idx -= v; return *this; }
-
- const Vertex *operator*() const {
- CARVE_ASSERT(idx >= 0 && idx < base->vertexCount());
- return base->vertex((size_t)idx);
- }
- };
-
-
-
- static inline ssize_t operator-(const polyline_vertex_const_iter &a, const polyline_vertex_const_iter &b) { return a.idx - b.idx; }
-
- static inline bool operator==(const polyline_vertex_const_iter&a, const polyline_vertex_const_iter &b) { return a.idx == b.idx; }
- static inline bool operator!=(const polyline_vertex_const_iter&a, const polyline_vertex_const_iter &b) { return a.idx != b.idx; }
- static inline bool operator<(const polyline_vertex_const_iter&a, const polyline_vertex_const_iter &b) { return a.idx < b.idx; }
- static inline bool operator>(const polyline_vertex_const_iter&a, const polyline_vertex_const_iter &b) { return a.idx > b.idx; }
- static inline bool operator<=(const polyline_vertex_const_iter&a, const polyline_vertex_const_iter &b) { return a.idx <= b.idx; }
- static inline bool operator>=(const polyline_vertex_const_iter&a, const polyline_vertex_const_iter &b) { return a.idx >= b.idx; }
-
- inline polyline_vertex_const_iter Polyline::vbegin() const {
- return polyline_vertex_const_iter(this, 0);
- }
- inline polyline_vertex_const_iter Polyline::vend() const {
- return polyline_vertex_const_iter(this, (ssize_t)vertexCount());
- }
- inline polyline_vertex_iter Polyline::vbegin() {
- return polyline_vertex_iter(this, 0);
- }
- inline polyline_vertex_iter Polyline::vend() {
- return polyline_vertex_iter(this, (ssize_t)vertexCount());
- }
-
-
-
- struct polyline_edge_iter : public std::iterator<std::random_access_iterator_tag, PolylineEdge *> {
- Polyline *base;
- ssize_t idx;
-
- polyline_edge_iter(Polyline *_base) : base(_base), idx(0) {
- }
-
- polyline_edge_iter(Polyline *_base, ssize_t _idx) : base(_base), idx(_idx) {
- }
-
- polyline_edge_iter operator++(int) { return polyline_edge_iter(base, idx++); }
- polyline_edge_iter &operator++() { ++idx; return *this; }
- polyline_edge_iter &operator+=(int v) { idx += v; return *this; }
-
- polyline_edge_iter operator--(int) { return polyline_edge_iter(base, idx--); }
- polyline_edge_iter &operator--() { --idx; return *this; }
- polyline_edge_iter &operator-=(int v) { idx -= v; return *this; }
-
- PolylineEdge *operator*() const {
- CARVE_ASSERT(idx >= 0 && idx < base->edgeCount());
- return base->edge((size_t)idx);
- }
- };
-
-
-
- static inline ssize_t operator-(const polyline_edge_iter&a, const polyline_edge_iter &b) { return a.idx - b.idx; }
-
- static inline bool operator==(const polyline_edge_iter&a, const polyline_edge_iter &b) { return a.idx == b.idx; }
- static inline bool operator!=(const polyline_edge_iter&a, const polyline_edge_iter &b) { return a.idx != b.idx; }
- static inline bool operator<(const polyline_edge_iter&a, const polyline_edge_iter &b) { return a.idx < b.idx; }
- static inline bool operator>(const polyline_edge_iter&a, const polyline_edge_iter &b) { return a.idx > b.idx; }
- static inline bool operator<=(const polyline_edge_iter&a, const polyline_edge_iter &b) { return a.idx <= b.idx; }
- static inline bool operator>=(const polyline_edge_iter&a, const polyline_edge_iter &b) { return a.idx >= b.idx; }
-
-
-
- struct polyline_edge_const_iter : public std::iterator<std::random_access_iterator_tag, PolylineEdge *> {
- const Polyline *base;
- ssize_t idx;
-
- polyline_edge_const_iter(const Polyline *_base) : base(_base), idx(0) {
- }
-
- polyline_edge_const_iter(const Polyline *_base, ssize_t _idx) : base(_base), idx(_idx) {
- }
-
- polyline_edge_const_iter operator++(int) { return polyline_edge_const_iter(base, idx++); }
- polyline_edge_const_iter &operator++() { ++idx; return *this; }
- polyline_edge_const_iter &operator+=(int v) { idx += v; return *this; }
-
- polyline_edge_const_iter operator--(int) { return polyline_edge_const_iter(base, idx--); }
- polyline_edge_const_iter &operator--() { --idx; return *this; }
- polyline_edge_const_iter &operator-=(int v) { idx -= v; return *this; }
-
- const PolylineEdge *operator*() const {
- CARVE_ASSERT(idx >= 0 && idx < base->edgeCount());
- return base->edge((size_t)idx);
- }
- };
-
-
-
- static inline ssize_t operator-(const polyline_edge_const_iter&a, const polyline_edge_const_iter &b) { return a.idx - b.idx; }
-
- static inline bool operator==(const polyline_edge_const_iter&a, const polyline_edge_const_iter &b) { return a.idx == b.idx; }
- static inline bool operator!=(const polyline_edge_const_iter&a, const polyline_edge_const_iter &b) { return a.idx != b.idx; }
- static inline bool operator<(const polyline_edge_const_iter&a, const polyline_edge_const_iter &b) { return a.idx < b.idx; }
- static inline bool operator>(const polyline_edge_const_iter&a, const polyline_edge_const_iter &b) { return a.idx > b.idx; }
- static inline bool operator<=(const polyline_edge_const_iter&a, const polyline_edge_const_iter &b) { return a.idx <= b.idx; }
- static inline bool operator>=(const polyline_edge_const_iter&a, const polyline_edge_const_iter &b) { return a.idx >= b.idx; }
-
- inline polyline_edge_const_iter Polyline::ebegin() const {
- return polyline_edge_const_iter(this, 0);
- }
- inline polyline_edge_const_iter Polyline::eend() const {
- return polyline_edge_const_iter(this, (ssize_t)edgeCount());
- }
- inline polyline_edge_iter Polyline::ebegin() {
- return polyline_edge_iter(this, 0);
- }
- inline polyline_edge_iter Polyline::eend() {
- return polyline_edge_iter(this, (ssize_t)edgeCount());
- }
-
- }
-}
diff --git a/extern/carve/include/carve/random/random.h b/extern/carve/include/carve/random/random.h
deleted file mode 100644
index 634063cb90c..00000000000
--- a/extern/carve/include/carve/random/random.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <cassert>
-#include <cmath>
-#include <vector>
-
-namespace boost {
-#if __cplusplus > 199711L
-# include <random>
-typedef std::mt19937 mt19937;
-#else
-# include <stdlib.h>
-struct mt19937 {
- int operator()() {
- return rand();
- }
-
- int max() {
- return RAND_MAX;
- }
-};
-#endif
-
-template<typename T>
-struct uniform_on_sphere {
- typedef std::vector<T> result_type;
-
- uniform_on_sphere(int dimension) {
- assert(dimension == 3);
- }
-
- std::vector<T>
- operator()(float u1, float u2) {
- T z = 1.0 - 2.0*u1;
- T r = std::sqrt(std::max(0.0, 1.0 - z*z));
- T phi = 2.0*M_PI*u2;
- T x = r*std::cos(phi);
- T y = r*std::sin(phi);
- std::vector<T> result;
- result.push_back(x);
- result.push_back(y);
- result.push_back(z);
- return result;
- }
-};
-
-template<typename RNG, typename DISTR>
-struct variate_generator {
-
- variate_generator(RNG rng, DISTR distr)
- : rng_(rng), distr_(distr) {}
-
- typename DISTR::result_type
- operator()() {
- float rng_max_inv = 1.0 / rng_.max();
- return distr_(rng_() * rng_max_inv, rng_() * rng_max_inv);
- }
-
- RNG rng_;
- DISTR distr_;
-};
-
-}
diff --git a/extern/carve/include/carve/rescale.hpp b/extern/carve/include/carve/rescale.hpp
deleted file mode 100644
index 9269d271d8e..00000000000
--- a/extern/carve/include/carve/rescale.hpp
+++ /dev/null
@@ -1,100 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/vector.hpp>
-#include <carve/aabb.hpp>
-#include <carve/matrix.hpp>
-
-#include <limits>
-
-namespace carve {
- namespace rescale {
-
- template<typename T>
- T calc_scale(T max) {
- const int radix = std::numeric_limits<T>::radix;
-
- T div = T(1);
- T m = fabs(max);
- while (div < m) div *= radix;
- m *= radix;
- while (div > m) div /= radix;
- return div;
- }
-
- template<typename T>
- T calc_delta(T min, T max) {
- const int radix = std::numeric_limits<T>::radix;
-
- if (min >= T(0) || max <= T(0)) {
- bool neg = false;
- if (max <= T(0)) {
- min = -min;
- max = -max;
- std::swap(min, max);
- neg = true;
- }
- T t = T(1);
- while (t > max) t /= radix;
- while (t <= max/radix) t *= radix;
- volatile T temp = t + min;
- temp -= t;
- if (neg) temp = -temp;
- return temp;
- } else {
- return T(0);
- }
- }
-
- struct rescale {
- double dx, dy, dz, scale;
-
- void init(double minx, double miny, double minz, double maxx, double maxy, double maxz) {
- dx = calc_delta(minx, maxx); minx -= dx; maxx -= dx;
- dy = calc_delta(miny, maxy); miny -= dy; maxy -= dy;
- dz = calc_delta(minz, maxz); minz -= dz; maxz -= dz;
- scale = calc_scale(std::max(std::max(fabs(minz), fabs(maxz)),
- std::max(std::max(fabs(minx), fabs(maxx)),
- std::max(fabs(miny), fabs(maxy)))));
- }
-
- rescale(double minx, double miny, double minz, double maxx, double maxy, double maxz) {
- init(minx, miny, minz, maxx, maxy, maxz);
- }
- rescale(const carve::geom3d::Vector &min, const carve::geom3d::Vector &max) {
- init(min.x, min.y, min.z, max.x, max.y, max.z);
- }
- };
-
- struct fwd {
- rescale r;
- fwd(const rescale &_r) : r(_r) { }
- carve::geom3d::Vector operator()(const carve::geom3d::Vector &v) const { return carve::geom::VECTOR((v.x - r.dx) / r.scale, (v.y - r.dy) / r.scale, (v.z - r.dz) / r.scale); }
- };
-
- struct rev {
- rescale r;
- rev(const rescale &_r) : r(_r) { }
- carve::geom3d::Vector operator()(const carve::geom3d::Vector &v) const { return carve::geom::VECTOR((v.x * r.scale) + r.dx, (v.y * r.scale) + r.dy, (v.z * r.scale) + r.dz); }
- };
-
- }
-}
diff --git a/extern/carve/include/carve/rtree.hpp b/extern/carve/include/carve/rtree.hpp
deleted file mode 100644
index 2d5a59f9e34..00000000000
--- a/extern/carve/include/carve/rtree.hpp
+++ /dev/null
@@ -1,514 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/geom.hpp>
-#include <carve/aabb.hpp>
-
-#include <iostream>
-
-#include <cmath>
-#include <limits>
-
-#if defined(HAVE_STDINT_H)
-# include <stdint.h>
-#endif
-
-namespace carve {
- namespace geom {
-
- template<unsigned ndim,
- typename data_t,
- typename aabb_calc_t = carve::geom::get_aabb<ndim, data_t> >
- struct RTreeNode {
- typedef aabb<ndim> aabb_t;
- typedef vector<ndim> vector_t;
- typedef RTreeNode<ndim, data_t, aabb_calc_t> node_t;
-
- aabb_t bbox;
- node_t *child;
- node_t *sibling;
- std::vector<data_t> data;
-
- aabb_t getAABB() const { return bbox; }
-
- struct data_aabb_t {
- aabb_t bbox;
- data_t data;
-
- data_aabb_t() { }
- data_aabb_t(const data_t &_data) : bbox(aabb_calc_t()(_data)), data(_data) {
- }
-
- aabb_t getAABB() const { return bbox; }
-
- struct cmp {
- size_t dim;
- cmp(size_t _dim) : dim(_dim) { }
- bool operator()(const data_aabb_t &a, const data_aabb_t &b) {
- return a.bbox.pos.v[dim] < b.bbox.pos.v[dim];
- }
- };
- };
-
- // Fill an rtree node with a set of (data, aabb) pairs.
- template<typename iter_t>
- void _fill(iter_t begin, iter_t end, data_aabb_t) {
- data.reserve(std::distance(begin, end));
- for (iter_t i = begin; i != end; ++i) {
- data.push_back((*i).data);
- }
- bbox.fit(begin, end);
- }
-
- // Fill an rtree node with a set of data.
- template<typename iter_t>
- void _fill(iter_t begin, iter_t end, data_t) {
- data.reserve(std::distance(begin, end));
- std::copy(begin, end, std::back_inserter(data));
- bbox.fit(begin, end, aabb_calc_t());
- }
-
- // Fill an rtree node with a set of child nodes.
- template<typename iter_t>
- void _fill(iter_t begin, iter_t end, node_t *) {
- iter_t i = begin;
- node_t *curr = child = *i;
- while (++i != end) {
- curr->sibling = *i;
- curr = curr->sibling;
- }
- bbox.fit(begin, end);
- }
-
- // Search the rtree for objects that intersect obj (generally an aabb).
- // The aabb class must provide a method intersects(obj_t).
- template<typename obj_t, typename out_iter_t>
- void search(const obj_t &obj, out_iter_t out) const {
- if (!bbox.intersects(obj)) return;
- if (child) {
- for (node_t *node = child; node; node = node->sibling) {
- node->search(obj, out);
- }
- } else {
- std::copy(data.begin(), data.end(), out);
- }
- }
-
- // update the bounding box extents of nodes that intersect obj (generally an aabb).
- // The aabb class must provide a method intersects(obj_t).
- template<typename obj_t>
- void updateExtents(const obj_t &obj) {
- if (!bbox.intersects(obj)) return;
-
- if (child) {
- node_t *node = child;
- node->updateExtents(obj);
- bbox = node->bbox;
- for (node = node->sibling; node; node = node->sibling) {
- node->updateExtents(obj);
- bbox.unionAABB(node->bbox);
- }
- } else {
- bbox.fit(data.begin(), data.end());
- }
- }
-
- // update the bounding box extents of nodes that intersect obj (generally an aabb).
- // The aabb class must provide a method intersects(obj_t).
- bool remove(const data_t &val, const aabb_t &val_aabb) {
- if (!bbox.intersects(val_aabb)) return false;
-
- if (child) {
- node_t *node = child;
- node->remove(val, val_aabb);
- bbox = node->bbox;
- bool removed = false;
- for (node = node->sibling; node; node = node->sibling) {
- if (!removed) removed = node->remove(val, val_aabb);
- bbox.unionAABB(node->bbox);
- }
- return removed;
- } else {
- typename std::vector<data_t>::iterator i = std::remove(data.begin(), data.end(), val);
- if (i == data.end()) {
- return false;
- }
- data.erase(i, data.end());
- bbox.fit(data.begin(), data.end());
- return true;
- }
- }
-
- template<typename iter_t>
- RTreeNode(iter_t begin, iter_t end) : bbox(), child(NULL), sibling(NULL), data() {
- _fill(begin, end, typename std::iterator_traits<iter_t>::value_type());
- }
-
- ~RTreeNode() {
- if (child) {
- RTreeNode *next = child;
- while (next) {
- RTreeNode *curr = next;
- next = next->sibling;
- delete curr;
- }
- }
- }
-
-
-
- // functor for ordering nodes by increasing aabb midpoint, along a specified axis.
- struct aabb_cmp_mid {
- size_t dim;
- aabb_cmp_mid(size_t _dim) : dim(_dim) { }
-
- bool operator()(const node_t *a, const node_t *b) {
- return a->bbox.mid(dim) < b->bbox.mid(dim);
- }
- bool operator()(const data_aabb_t &a, const data_aabb_t &b) {
- return a.bbox.mid(dim) < b.bbox.mid(dim);
- }
- };
-
- // functor for ordering nodes by increasing aabb minimum, along a specified axis.
- struct aabb_cmp_min {
- size_t dim;
- aabb_cmp_min(size_t _dim) : dim(_dim) { }
-
- bool operator()(const node_t *a, const node_t *b) {
- return a->bbox.min(dim) < b->bbox.min(dim);
- }
- bool operator()(const data_aabb_t &a, const data_aabb_t &b) {
- return a.bbox.min(dim) < b.bbox.min(dim);
- }
- };
-
- // functor for ordering nodes by increasing aabb maximum, along a specified axis.
- struct aabb_cmp_max {
- size_t dim;
- aabb_cmp_max(size_t _dim) : dim(_dim) { }
-
- bool operator()(const node_t *a, const node_t *b) {
- return a->bbox.max(dim) < b->bbox.max(dim);
- }
- bool operator()(const data_aabb_t &a, const data_aabb_t &b) {
- return a.bbox.max(dim) < b.bbox.max(dim);
- }
- };
-
- // facade for projecting node bounding box onto an axis.
- struct aabb_extent {
- size_t dim;
- aabb_extent(size_t _dim) : dim(_dim) { }
-
- double min(const node_t *a) { return a->bbox.pos.v[dim] - a->bbox.extent.v[dim]; }
- double max(const node_t *a) { return a->bbox.pos.v[dim] + a->bbox.extent.v[dim]; }
- double len(const node_t *a) { return 2.0 * a->bbox.extent.v[dim]; }
- double min(const data_aabb_t &a) { return a.bbox.pos.v[dim] - a.bbox.extent.v[dim]; }
- double max(const data_aabb_t &a) { return a.bbox.pos.v[dim] + a.bbox.extent.v[dim]; }
- double len(const data_aabb_t &a) { return 2.0 * a.bbox.extent.v[dim]; }
- };
-
- template<typename iter_t>
- static void makeNodes(const iter_t begin,
- const iter_t end,
- size_t dim_num,
- uint32_t dim_mask,
- size_t child_size,
- std::vector<node_t *> &out) {
- const size_t N = std::distance(begin, end);
-
- size_t dim = ndim;
- double r_best = N+1;
-
- // find the sparsest remaining dimension to partition by.
- for (size_t i = 0; i < ndim; ++i) {
- if (dim_mask & (1U << i)) continue;
- aabb_extent extent(i);
- double dmin, dmax, dsum;
-
- dmin = extent.min(*begin);
- dmax = extent.max(*begin);
- dsum = 0.0;
- for (iter_t j = begin; j != end; ++j) {
- dmin = std::min(dmin, extent.min(*j));
- dmax = std::max(dmax, extent.max(*j));
- dsum += extent.len(*j);
- }
- double r = dsum ? dsum / (dmax - dmin) : 0.0;
- if (r_best > r) {
- dim = i;
- r_best = r;
- }
- }
-
- CARVE_ASSERT(dim < ndim);
-
- // dim = dim_num;
-
- const size_t P = (N + child_size - 1) / child_size;
- const size_t n_parts = (size_t)std::ceil(std::pow((double)P, 1.0 / (ndim - dim_num)));
-
- std::sort(begin, end, aabb_cmp_mid(dim));
-
- if (dim_num == ndim - 1 || n_parts == 1) {
- for (size_t i = 0, s = 0, e = 0; i < P; ++i, s = e) {
- e = N * (i+1) / P;
- CARVE_ASSERT(e - s <= child_size);
- out.push_back(new node_t(begin + s, begin + e));
- }
- } else {
- for (size_t i = 0, s = 0, e = 0; i < n_parts; ++i, s = e) {
- e = N * (i+1) / n_parts;
- makeNodes(begin + s, begin + e, dim_num + 1, dim_mask | (1U << dim), child_size, out);
- }
- }
- }
-
- static node_t *construct_STR(std::vector<data_aabb_t> &data, size_t leaf_size, size_t internal_size) {
- std::vector<node_t *> out;
- makeNodes(data.begin(), data.end(), 0, 0, leaf_size, out);
-
- while (out.size() > 1) {
- std::vector<node_t *> next;
- makeNodes(out.begin(), out.end(), 0, 0, internal_size, next);
- std::swap(out, next);
- }
-
- CARVE_ASSERT(out.size() == 1);
- return out[0];
- }
-
- template<typename iter_t>
- static node_t *construct_STR(const iter_t &begin,
- const iter_t &end,
- size_t leaf_size,
- size_t internal_size) {
- std::vector<data_aabb_t> data;
- data.reserve(std::distance(begin, end));
- for (iter_t i = begin; i != end; ++i) {
- data.push_back(*i);
- }
- return construct_STR(data, leaf_size, internal_size);
- }
-
-
- template<typename iter_t>
- static node_t *construct_STR(const iter_t &begin1,
- const iter_t &end1,
- const iter_t &begin2,
- const iter_t &end2,
- size_t leaf_size,
- size_t internal_size) {
- std::vector<data_aabb_t> data;
- data.reserve(std::distance(begin1, end1) + std::distance(begin2, end2));
- for (iter_t i = begin1; i != end1; ++i) {
- data.push_back(*i);
- }
- for (iter_t i = begin2; i != end2; ++i) {
- data.push_back(*i);
- }
- return construct_STR(data, leaf_size, internal_size);
- }
-
-
- struct partition_info {
- double score;
- size_t partition_pos;
-
- partition_info() : score(std::numeric_limits<double>::max()), partition_pos(0) {
- }
- partition_info(double _score, size_t _partition_pos) :
- score(_score),
- partition_pos(_partition_pos) {
- }
- };
-
- static partition_info findPartition(typename std::vector<data_aabb_t>::iterator base,
- std::vector<size_t>::iterator begin,
- std::vector<size_t>::iterator end,
- size_t part_size) {
- CARVE_ASSERT(begin < end);
-
- partition_info best(std::numeric_limits<double>::max(), 0);
- const size_t N = (size_t)std::distance(begin, end);
-
- std::vector<double> rhs_vol(N, 0.0);
-
- aabb_t rhs = base[begin[N-1]].aabb;
- rhs_vol[N-1] = rhs.volume();
- for (size_t i = N - 1; i > 0; ) {
- rhs.unionAABB(base[begin[--i]].aabb);
- rhs_vol[i] = rhs.volume();
- }
-
- aabb_t lhs = base[begin[0]].aabb;
- for (size_t i = 1; i < N; ++i) {
- lhs.unionAABB(base[begin[i]].aabb);
- if (i % part_size == 0 || (N - i) % part_size == 0) {
- partition_info curr(lhs.volume() + rhs_vol[i], i);
- if (best.score > curr.score) best = curr;
- }
- }
- return best;
- }
-
- static void partition(typename std::vector<data_aabb_t>::iterator base,
- std::vector<size_t>::iterator begin,
- std::vector<size_t>::iterator end,
- size_t part_size,
- std::vector<size_t> &part_num,
- size_t &part_next) {
- CARVE_ASSERT(begin < end);
-
- const size_t N = (size_t)std::distance(begin, end);
-
- partition_info best;
- partition_info curr;
- size_t part_curr = part_num[*begin];
-
- std::vector<size_t> tmp(begin, end);
-
- for (size_t dim = 0; dim < ndim; ++dim) {
- std::sort(tmp.begin(), tmp.end(), make_index_sort(base, aabb_cmp_min(dim)));
- curr = findPartition(base, tmp.begin(), tmp.end(), part_size);
- if (best.score > curr.score) {
- best = curr;
- std::copy(tmp.begin(), tmp.end(), begin);
- }
-
- std::sort(tmp.begin(), tmp.end(), make_index_sort(base, aabb_cmp_mid(dim)));
- curr = findPartition(base, tmp.begin(), tmp.end(), part_size);
- if (best.score > curr.score) {
- best = curr;
- std::copy(tmp.begin(), tmp.end(), begin);
- }
-
- std::sort(tmp.begin(), tmp.end(), make_index_sort(base, aabb_cmp_max(dim)));
- curr = findPartition(base, tmp.begin(), tmp.end(), part_size);
- if (best.score > curr.score) {
- best = curr;
- std::copy(tmp.begin(), tmp.end(), begin);
- }
- }
-
- for (size_t j = 0; j < best.partition_pos; ++j) part_num[begin[(ssize_t)j]] = part_curr;
- for (size_t j = best.partition_pos; j < N; ++j) part_num[begin[(ssize_t)j]] = part_next;
- ++part_next;
-
- if (best.partition_pos > part_size) {
- partition(base, begin, begin + best.partition_pos, part_size, part_num, part_next);
- }
- if (N - best.partition_pos > part_size) {
- partition(base, begin + best.partition_pos, end, part_size, part_num, part_next);
- }
- }
-
- static size_t makePartitions(typename std::vector<data_aabb_t>::iterator begin,
- typename std::vector<data_aabb_t>::iterator end,
- size_t part_size,
- std::vector<size_t> &part_num) {
- const size_t N = std::distance(begin, end);
- std::vector<size_t> idx;
- idx.reserve(N);
- for (size_t i = 0; i < N; ++i) { idx.push_back(i); }
- size_t part_next = 1;
-
- partition(begin, idx.begin(), idx.end(), part_size, part_num, part_next);
- return part_next;
- }
-
- static node_t *construct_TGS(typename std::vector<data_aabb_t>::iterator begin,
- typename std::vector<data_aabb_t>::iterator end,
- size_t leaf_size,
- size_t internal_size) {
- size_t N = std::distance(begin, end);
-
- if (N <= leaf_size) {
- return new node_t(begin, end);
- } else {
- size_t P = (N + internal_size - 1) / internal_size;
- std::vector<size_t> part_num(N, 0);
- P = makePartitions(begin, end, P, part_num);
-
- size_t S = 0, E = 0;
- std::vector<node_t *> children;
- for (size_t i = 0; i < P; ++i) {
- size_t j = S, k = N;
- while (true) {
- while (true) {
- if (j == k) goto done;
- else if (part_num[j] == i) ++j;
- else break;
- }
- --k;
- while (true) {
- if (j == k) goto done;
- else if (part_num[k] != i) --k;
- else break;
- }
- std::swap(*(begin+j), *(begin+k));
- std::swap(part_num[j], part_num[k]);
- ++j;
- }
- done:
- E = j;
- children.push_back(construct_TGS(begin + S, begin + E, leaf_size, internal_size));
- S = E;
- }
- return new node_t(children.begin(), children.end());
- }
- }
-
- template<typename iter_t>
- static node_t *construct_TGS(const iter_t &begin,
- const iter_t &end,
- size_t leaf_size,
- size_t internal_size) {
- std::vector<data_aabb_t> data;
- data.reserve(std::distance(begin, end));
- for (iter_t i = begin; i != end; ++i) {
- data.push_back(*i);
- }
- return construct_TGS(data.begin(), data.end(), leaf_size, internal_size);
- }
-
- template<typename iter_t>
- static node_t *construct_TGS(const iter_t &begin1,
- const iter_t &end1,
- const iter_t &begin2,
- const iter_t &end2,
- size_t leaf_size,
- size_t internal_size) {
- std::vector<data_aabb_t> data;
- data.reserve(std::distance(begin1, end1) + std::distance(begin2, end2));
- for (iter_t i = begin1; i != end1; ++i) {
- data.push_back(*i);
- }
- for (iter_t i = begin2; i != end2; ++i) {
- data.push_back(*i);
- }
- return construct_TGS(data.begin(), data.end(), leaf_size, internal_size);
- }
- };
-
- }
-}
diff --git a/extern/carve/include/carve/spacetree.hpp b/extern/carve/include/carve/spacetree.hpp
deleted file mode 100644
index 7208228caab..00000000000
--- a/extern/carve/include/carve/spacetree.hpp
+++ /dev/null
@@ -1,264 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/geom.hpp>
-#include <carve/aabb.hpp>
-#include <carve/vertex_decl.hpp>
-#include <carve/edge_decl.hpp>
-#include <carve/face_decl.hpp>
-
-namespace carve {
-
- namespace space {
-
- static inline bool intersection_test(const carve::geom::aabb<3> &aabb, const carve::poly::Face<3> *face) {
- if (face->nVertices() == 3) {
- return aabb.intersects(carve::geom::tri<3>(face->vertex(0)->v, face->vertex(1)->v, face->vertex(2)->v));
- } else {
- // partial, conservative SAT.
- return aabb.intersects(face->aabb) && aabb.intersects(face->plane_eqn);
- }
- }
-
- static inline bool intersection_test(const carve::geom::aabb<3> &aabb, const carve::poly::Edge<3> *edge) {
- return aabb.intersectsLineSegment(edge->v1->v, edge->v2->v);
- }
-
- static inline bool intersection_test(const carve::geom::aabb<3> &aabb, const carve::poly::Vertex<3> *vertex) {
- return aabb.intersects(vertex->v);
- }
-
-
-
- struct nodedata_FaceEdge {
- std::vector<const carve::poly::Face<3> *> faces;
- std::vector<const carve::poly::Edge<3> *> edges;
-
- void add(const carve::poly::Face<3> *face) {
- faces.push_back(face);
- }
-
- void add(const carve::poly::Edge<3> *edge) {
- edges.push_back(edge);
- }
-
- template<typename iter_t>
- void _fetch(iter_t &iter, const carve::poly::Edge<3> *) {
- std::copy(edges.begin(), edges.end(), iter);
- }
-
- template<typename iter_t>
- void _fetch(iter_t &iter, const carve::poly::Face<3> *) {
- std::copy(faces.begin(), faces.end(), iter);
- }
-
- template<typename node_t>
- void propagate(node_t *node) {
- }
-
- template<typename iter_t>
- void fetch(iter_t &iter) {
- return _fetch(iter, std::iterator_traits<iter_t>::value_type);
- }
- };
-
-
-
- const static double SLACK_FACTOR = 1.0009765625;
- const static unsigned MAX_SPLIT_DEPTH = 32;
-
-
-
- template<unsigned n_dim, typename nodedata_t>
- class SpatialSubdivTree {
-
- typedef carve::geom::aabb<n_dim> aabb_t;
- typedef carve::geom::vector<n_dim> vector_t;
-
- public:
-
- class Node {
- enum {
- n_children = 1 << n_dim
- };
-
- public:
- Node *parent;
- Node *children;
-
- vector_t min;
- vector_t max;
-
- aabb_t aabb;
-
- nodedata_t data;
-
- private:
- Node(const Node &node); // undefined.
- Node &operator=(const Node &node); // undefined.
-
- Node() {
- }
-
- inline aabb_t makeAABB() const {
- vector_t centre = 0.5 * (min + max);
- vector_t size = SLACK_FACTOR * 0.5 * (max - min);
- return aabb_t(centre, size);
- }
-
- void setup(Node *_parent, const vector_t &_min, const vector_t &_max) {
- parent = _parent;
- min = _min;
- max = _max;
- aabb = makeAABB();
- }
-
- void alloc_children() {
- vector_t mid = 0.5 * (min + max);
- children = new Node[n_children];
- for (size_t i = 0; i < (n_children); ++i) {
- vector_t new_min, new_max;
- for (size_t c = 0; c < n_dim; ++c) {
- if (i & (1 << c)) {
- new_min.v[c] = min.v[c];
- new_max.v[c] = mid.v[c];
- } else {
- new_min.v[c] = mid.v[c];
- new_max.v[c] = max.v[c];
- }
- }
- children[i].setup(this, new_min, new_max);
- }
- }
-
- void dealloc_children() {
- delete [] children;
- }
-
- public:
-
- inline bool isLeaf() const { return children == NULL; }
-
- Node(Node *_parent, const vector_t &_min, const vector_t &_max) : parent(_parent), children(NULL), min(_min), max(_max) {
- aabb = makeAABB();
- }
-
- ~Node() {
- dealloc_children();
- }
-
- bool split() {
- if (isLeaf()) {
- alloc_children();
- data.propagate(this);
- }
- return isLeaf();
- }
-
- template<typename obj_t>
- void insert(const obj_t &object) {
- if (!isLeaf()) {
- for (size_t i = 0; i < n_children; ++i) {
- if (intersection_test(children[i].aabb, object)) {
- children[i].insert(object);
- }
- }
- } else {
- data.add(object);
- }
- }
-
- template<typename obj_t>
- void insertVector(typename std::vector<obj_t>::iterator beg, typename std::vector<obj_t>::iterator end) {
- if (isLeaf()) {
- while (beg != end) {
- data.add(*beg);
- }
- } else {
- for (size_t i = 0; i < n_children; ++i) {
- typename std::vector<obj_t>::iterator mid = std::partition(beg, end, std::bind1st(intersection_test, children[i].aabb));
- children[i].insertVector(beg, mid);
- }
- }
- }
-
- template<typename iter_t>
- void insertMany(iter_t begin, iter_t end) {
- if (isLeaf()) {
- }
- }
-
- template<typename obj_t, typename iter_t, typename filter_t>
- void findObjectsNear(const obj_t &object, iter_t &output, filter_t filter) {
- if (!isLeaf()) {
- for (size_t i = 0; i < n_children; ++i) {
- if (intersection_test(children[i].aabb, object)) {
- children[i].findObjectsNear(object, output, filter);
- }
- }
- return;
- }
- data.fetch(output);
- }
-
- // bool hasGeometry();
-
- // template <class T>
- // void putInside(const T &input, Node *child, T &output);
-
- };
-
-
-
- Node *root;
-
- SpatialSubdivTree(const vector_t &_min, const vector_t &_max) : root(new Node(NULL, _min, _max)) {
- }
-
- ~SpatialSubdivTree() {
- delete root;
- }
-
- struct no_filter {
- template<typename obj_t>
- bool operator()(const obj_t &obj) const {
- return true;
- }
- };
-
- struct tag_filter {
- template<typename obj_t>
- bool operator()(const obj_t &obj) const {
- return obj.tag_once();
- }
- };
-
- // in order to be used as an input, aabb_t::intersect(const obj_t &) must exist.
- template<typename obj_t, typename iter_t, typename filter_t>
- void findObjectsNear(const obj_t &object, iter_t output, filter_t filter) {
- if (!intersection_test(root->aabb, object)) return;
- root->findObjectsNear(root, object, output, filter);
- }
-
- };
-
- }
-}
diff --git a/extern/carve/include/carve/tag.hpp b/extern/carve/include/carve/tag.hpp
deleted file mode 100644
index 3581f348a68..00000000000
--- a/extern/carve/include/carve/tag.hpp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-namespace carve {
-
- class tagable {
- private:
- static int s_count;
-
- protected:
- mutable int __tag;
-
- public:
- tagable(const tagable &) : __tag(s_count - 1) { }
- tagable &operator=(const tagable &) { return *this; }
-
- tagable() : __tag(s_count - 1) { }
-
- void tag() const { __tag = s_count; }
- void untag() const { __tag = s_count - 1; }
- bool is_tagged() const { return __tag == s_count; }
- bool tag_once() const { if (__tag == s_count) return false; __tag = s_count; return true; }
-
- static void tag_begin() { s_count++; }
- };
-}
diff --git a/extern/carve/include/carve/timing.hpp b/extern/carve/include/carve/timing.hpp
deleted file mode 100644
index df18ee46502..00000000000
--- a/extern/carve/include/carve/timing.hpp
+++ /dev/null
@@ -1,96 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#ifndef CARVE_USE_TIMINGS
-#define CARVE_USE_TIMINGS 0
-#endif
-
-namespace carve {
-
-#if CARVE_USE_TIMINGS
-
- class TimingName {
- public:
- TimingName(const char *name);
- int id;
- };
-
- class TimingBlock {
- public:
- /**
- * Starts timing at the end of this constructor, using the given ID. To
- * associate an ID with a textual name, use Timing::registerID.
- */
- TimingBlock(int id);
- TimingBlock(const TimingName &name);
- ~TimingBlock();
- };
-
- class Timing {
- public:
-
- /**
- * Starts timing against a particular ID.
- */
- static void start(int id);
-
- static void start(const TimingName &id) {
- start(id.id);
- }
-
- /**
- * Stops the most recent timing block.
- */
- static double stop();
-
- /**
- * This will print out the current state of recorded time blocks. It will
- * display the tree of timings, as well as the summaries down the bottom.
- */
- static void printTimings();
-
- /**
- * Associates a particular ID with a text string. This is used when
- * printing out the timings.
- */
- static void registerID(int id, const char *name);
-
- };
-
-#else
-
- struct TimingName {
- TimingName(const char *) {}
- };
- struct TimingBlock {
- TimingBlock(int /* id */) {}
- TimingBlock(const TimingName & /* name */) {}
- };
- struct Timing {
- static void start(int /* id */) {}
- static void start(const TimingName & /* id */) {}
- static double stop() { return 0; }
- static void printTimings() {}
- static void registerID(int /* id */, const char * /* name */) {}
- };
-
-#endif
-}
diff --git a/extern/carve/include/carve/tree.hpp b/extern/carve/include/carve/tree.hpp
deleted file mode 100644
index 1a3f6b04ef7..00000000000
--- a/extern/carve/include/carve/tree.hpp
+++ /dev/null
@@ -1,324 +0,0 @@
-
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/matrix.hpp>
-#include <carve/timing.hpp>
-#include <carve/rescale.hpp>
-
-namespace carve {
- namespace csg {
-
- class CSG_TreeNode {
- CSG_TreeNode(const CSG_TreeNode &);
- CSG_TreeNode &operator=(const CSG_TreeNode &);
-
- protected:
-
- public:
- CSG_TreeNode() {
- }
-
- virtual ~CSG_TreeNode() {
- }
-
- virtual carve::mesh::MeshSet<3> *eval(bool &is_temp, CSG &csg) =0;
-
- virtual carve::mesh::MeshSet<3> *eval(CSG &csg) {
- bool temp;
- carve::mesh::MeshSet<3> *r = eval(temp, csg);
- if (!temp) r = r->clone();
- return r;
- }
- };
-
-
-
- class CSG_TransformNode : public CSG_TreeNode {
- carve::math::Matrix transform;
- CSG_TreeNode *child;
-
- public:
- CSG_TransformNode(const carve::math::Matrix &_transform, CSG_TreeNode *_child) : transform(_transform), child(_child) {
- }
- virtual ~CSG_TransformNode() {
- delete child;
- }
-
- virtual carve::mesh::MeshSet<3> *eval(bool &is_temp, CSG &csg) {
- carve::mesh::MeshSet<3> *result = child->eval(is_temp, csg);
- if (!is_temp) {
- result = result->clone();
- is_temp = true;
- }
- result->transform(carve::math::matrix_transformation(transform));
- return result;
- }
- };
-
-
-
-
- class CSG_InvertNode : public CSG_TreeNode {
- std::vector<bool> selected_meshes;
- CSG_TreeNode *child;
-
- public:
- CSG_InvertNode(CSG_TreeNode *_child) : selected_meshes(), child(_child) {
- }
- CSG_InvertNode(int g_id, CSG_TreeNode *_child) : selected_meshes(), child(_child) {
- selected_meshes.resize(g_id + 1, false);
- selected_meshes[g_id] = true;
- }
- virtual ~CSG_InvertNode() {
- delete child;
- }
-
- template<typename T>
- CSG_InvertNode(T start, T end, CSG_TreeNode *_child) : selected_meshes(), child(_child) {
- while (start != end) {
- int g_id = (int)(*start);
- if (selected_meshes.size() < g_id + 1) selected_meshes.resize(g_id + 1, false);
- selected_meshes[g_id] = true;
- ++start;
- }
- }
-
- virtual carve::mesh::MeshSet<3> *eval(bool &is_temp, CSG &csg) {
- bool c_temp;
- carve::mesh::MeshSet<3> *c = child->eval(c_temp, csg);
- if (!c_temp) c = c->clone();
- if (!selected_meshes.size()) {
- c->invert();
- } else {
- for (size_t i = 0; i < c->meshes.size() && i < selected_meshes.size(); ++i) {
- if (selected_meshes[i]) {
- c->meshes[i]->invert();
- }
- }
- }
- is_temp = true;
- return c;
- }
- };
-
-
-
-
- class CSG_SelectNode : public CSG_TreeNode {
- std::vector<bool> selected_meshes;
- CSG_TreeNode *child;
-
- public:
- CSG_SelectNode(int m_id, CSG_TreeNode *_child) : selected_meshes(), child(_child) {
- selected_meshes.resize(m_id + 1, false);
- selected_meshes[m_id] = true;
- }
-
- template<typename T>
- CSG_SelectNode(T start, T end, CSG_TreeNode *_child) : selected_meshes(), child(_child) {
- while (start != end) {
- int m_id = (int)(*start);
- if ((int)selected_meshes.size() < m_id + 1) selected_meshes.resize(m_id + 1, false);
- selected_meshes[m_id] = true;
- ++start;
- }
- }
-
- virtual ~CSG_SelectNode() {
- delete child;
- }
-
- virtual carve::mesh::MeshSet<3> *eval(bool &is_temp, CSG &csg) {
- bool c_temp;
- carve::mesh::MeshSet<3> *c = child->eval(c_temp, csg);
- if (!c_temp) c = c->clone();
- size_t i = 0;
- size_t j = 0;
- for (size_t i = 0; i < c->meshes.size(); ++i) {
- if (i >= selected_meshes.size() || !selected_meshes[i]) {
- delete c->meshes[i];
- c->meshes[i] = NULL;
- } else {
- c->meshes[j++] = c->meshes[i];
- }
- }
- c->meshes.erase(c->meshes.begin() + j, c->meshes.end());
- c->collectVertices();
- is_temp = true;
- return c;
- }
- };
-
-
-
-
- class CSG_PolyNode : public CSG_TreeNode {
- carve::mesh::MeshSet<3> *poly;
- bool del;
-
- public:
- CSG_PolyNode(carve::mesh::MeshSet<3> *_poly, bool _del) : poly(_poly), del(_del) {
- }
- virtual ~CSG_PolyNode() {
- static carve::TimingName FUNC_NAME("delete polyhedron");
- carve::TimingBlock block(FUNC_NAME);
-
- if (del) {
- delete poly;
- }
- }
-
- virtual carve::mesh::MeshSet<3> *eval(bool &is_temp, CSG &csg) {
- is_temp = false;
- return poly;
- }
- };
-
-
-
- class CSG_OPNode : public CSG_TreeNode {
- CSG_TreeNode *left, *right;
- CSG::OP op;
- bool rescale;
- CSG::CLASSIFY_TYPE classify_type;
-
- public:
- CSG_OPNode(CSG_TreeNode *_left,
- CSG_TreeNode *_right,
- CSG::OP _op,
- bool _rescale,
- CSG::CLASSIFY_TYPE _classify_type = CSG::CLASSIFY_NORMAL) : left(_left), right(_right), op(_op), rescale(_rescale), classify_type(_classify_type) {
- }
-
- virtual ~CSG_OPNode() {
- delete left;
- delete right;
- }
-
- void minmax(double &min_x, double &min_y, double &min_z,
- double &max_x, double &max_y, double &max_z,
- const std::vector<carve::geom3d::Vector> &points) {
- for (unsigned i = 1; i < points.size(); ++i) {
- min_x = std::min(min_x, points[i].x);
- max_x = std::max(max_x, points[i].x);
- min_y = std::min(min_y, points[i].y);
- max_y = std::max(max_y, points[i].y);
- min_z = std::min(min_z, points[i].z);
- max_z = std::max(max_z, points[i].z);
- }
- }
-
- virtual carve::mesh::MeshSet<3> *evalScaled(bool &is_temp, CSG &csg) {
- carve::mesh::MeshSet<3> *l, *r;
- bool l_temp, r_temp;
-
- l = left->eval(l_temp, csg);
- r = right->eval(r_temp, csg);
-
- if (!l_temp) { l = l->clone(); }
- if (!r_temp) { r = r->clone(); }
-
- carve::geom3d::Vector min, max;
- carve::geom3d::Vector min_l, max_l;
- carve::geom3d::Vector min_r, max_r;
-
- carve::geom::bounds<3>(l->vertex_storage.begin(),
- l->vertex_storage.end(),
- carve::mesh::Face<3>::vector_mapping(),
- min_l,
- max_l);
- carve::geom::bounds<3>(r->vertex_storage.begin(),
- r->vertex_storage.end(),
- carve::mesh::Face<3>::vector_mapping(),
- min_r,
- max_r);
-
- carve::geom::assign_op(min, min_l, min_r, carve::util::min_functor());
- carve::geom::assign_op(max, max_l, max_r, carve::util::max_functor());
-
- carve::rescale::rescale scaler(min.x, min.y, min.z, max.x, max.y, max.z);
-
- carve::rescale::fwd fwd_r(scaler);
- carve::rescale::rev rev_r(scaler);
-
- l->transform(fwd_r);
- r->transform(fwd_r);
-
- carve::mesh::MeshSet<3> *result = NULL;
- {
- static carve::TimingName FUNC_NAME("csg.compute()");
- carve::TimingBlock block(FUNC_NAME);
- result = csg.compute(l, r, op, NULL, classify_type);
- }
-
- {
- static carve::TimingName FUNC_NAME("delete polyhedron");
- carve::TimingBlock block(FUNC_NAME);
-
- delete l;
- delete r;
- }
-
- result->transform(rev_r);
-
- is_temp = true;
- return result;
- }
-
- virtual carve::mesh::MeshSet<3> *evalUnscaled(bool &is_temp, CSG &csg) {
- carve::mesh::MeshSet<3> *l, *r;
- bool l_temp, r_temp;
-
- l = left->eval(l_temp, csg);
- r = right->eval(r_temp, csg);
-
- carve::mesh::MeshSet<3> *result = NULL;
- {
- static carve::TimingName FUNC_NAME("csg.compute()");
- carve::TimingBlock block(FUNC_NAME);
- result = csg.compute(l, r, op, NULL, classify_type);
- }
-
- {
- static carve::TimingName FUNC_NAME("delete polyhedron");
- carve::TimingBlock block(FUNC_NAME);
-
- if (l_temp) delete l;
- if (r_temp) delete r;
- }
-
- is_temp = true;
- return result;
- }
-
-
- virtual carve::mesh::MeshSet<3> *eval(bool &is_temp, CSG &csg) {
- if (rescale) {
- return evalScaled(is_temp, csg);
- } else {
- return evalUnscaled(is_temp, csg);
- }
- }
- };
-
- }
-}
diff --git a/extern/carve/include/carve/triangle_intersection.hpp b/extern/carve/include/carve/triangle_intersection.hpp
deleted file mode 100644
index ff4ffd9da20..00000000000
--- a/extern/carve/include/carve/triangle_intersection.hpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/geom.hpp>
-
-namespace carve {
- namespace geom {
-
- enum TriangleIntType {
- TR_TYPE_NONE = 0,
- TR_TYPE_TOUCH = 1,
- TR_TYPE_INT = 2
- };
-
- enum TriangleInt {
- TR_INT_NONE = 0, // no intersection.
- TR_INT_INT = 1, // intersection.
- TR_INT_VERT = 2, // intersection due to shared vertex.
- TR_INT_EDGE = 3, // intersection due to shared edge.
- TR_INT_TRI = 4 // intersection due to identical triangle.
- };
-
- TriangleInt triangle_intersection(const vector<2> tri_a[3], const vector<2> tri_b[3]);
- TriangleInt triangle_intersection(const vector<3> tri_a[3], const vector<3> tri_b[3]);
-
- bool triangle_intersection_simple(const vector<2> tri_a[3], const vector<2> tri_b[3]);
- bool triangle_intersection_simple(const vector<3> tri_a[3], const vector<3> tri_b[3]);
-
- TriangleIntType triangle_intersection_exact(const vector<2> tri_a[3], const vector<2> tri_b[3]);
- TriangleIntType triangle_intersection_exact(const vector<3> tri_a[3], const vector<3> tri_b[3]);
-
- TriangleIntType triangle_linesegment_intersection_exact(const vector<2> tri_a[3], const vector<2> line_b[2]);
- TriangleIntType triangle_point_intersection_exact(const vector<2> tri_a[3], const vector<2> &pt_b);
- }
-}
diff --git a/extern/carve/include/carve/triangulator.hpp b/extern/carve/include/carve/triangulator.hpp
deleted file mode 100644
index 63e68c8c5f8..00000000000
--- a/extern/carve/include/carve/triangulator.hpp
+++ /dev/null
@@ -1,175 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <list>
-#include <vector>
-#include <algorithm>
-
-#include <carve/carve.hpp>
-
-#include <carve/geom2d.hpp>
-
-namespace carve {
- namespace triangulate {
-
- /**
- * \brief Merge a set of holes into a polygon. (templated)
- *
- * Take a polygon loop and a collection of hole loops, and patch
- * the hole loops into the polygon loop, returning a vector of
- * vertices from the polygon and holes, which describes a new
- * polygon boundary with no holes. The new polygon boundary is
- * constructed via the addition of edges * joining the polygon
- * loop to the holes.
- *
- * This may be applied to arbitrary vertex data (generally
- * carve::geom3d::Vertex pointers), but a projection function must
- * be supplied to convert vertices to coordinates in 2-space, in
- * which the work is performed.
- *
- * @tparam project_t A functor which converts vertices to a 2d
- * projection.
- * @tparam vert_t The vertex type.
- * @param project The projection functor.
- * @param f_loop The polygon loop into which holes are to be
- * incorporated.
- * @param h_loops The set of hole loops to be incorporated.
- *
- * @return A vector of vertex pointers.
- */
- template<typename project_t, typename vert_t>
- static std::vector<vert_t>
- incorporateHolesIntoPolygon(const project_t &project,
- const std::vector<vert_t> &f_loop,
- const std::vector<std::vector<vert_t> > &h_loops);
-
- void
- incorporateHolesIntoPolygon(const std::vector<std::vector<carve::geom2d::P2> > &poly,
- std::vector<std::pair<size_t, size_t> > &result,
- size_t poly_loop,
- const std::vector<size_t> &hole_loops);
-
- /**
- * \brief Merge a set of holes into a polygon. (2d)
- *
- * Take a polygon loop and a collection of hole loops, and patch
- * the hole loops into the polygon loop, returning a vector of
- * containing the vertices from the polygon and holes which
- * describes a new polygon boundary with no holes, through the
- * addition of edges joining the polygon loop to the holes.
- *
- * @param poly A vector containing the face loop (the first
- * element of poly) and the hole loops (second and
- * subsequent elements of poly).
- *
- * @return A vector of pairs of <loop_number, index> that
- * reference poly and define the result polygon loop.
- */
- std::vector<std::pair<size_t, size_t> > incorporateHolesIntoPolygon(const std::vector<std::vector<carve::geom2d::P2> > &poly);
-
- std::vector<std::vector<std::pair<size_t, size_t> > > mergePolygonsAndHoles(const std::vector<std::vector<carve::geom2d::P2> > &poly);
-
-
- struct tri_idx {
- union {
- unsigned v[3];
- struct { unsigned a, b, c; };
- };
-
- tri_idx() : a(0), b(0), c(0) {
- }
- tri_idx(unsigned _a, unsigned _b, unsigned _c) : a(_a), b(_b), c(_c) {
- }
- };
-
- /**
- * \brief Triangulate a 2-dimensional polygon.
- *
- * Given a 2-dimensional polygon described as a vector of 2-d
- * points, with no holes and no self-crossings, produce a
- * triangulation using an ear-clipping algorithm.
- *
- * @param [in] poly A vector containing the input polygon.
- * @param [out] result A vector of triangles, represented as
- * indicies into poly.
- */
-
-
- void triangulate(const std::vector<carve::geom2d::P2> &poly, std::vector<tri_idx> &result);
-
- /**
- * \brief Triangulate a polygon (templated).
- *
- * @tparam project_t A functor which converts vertices to a 2d
- * projection.
- * @tparam vert_t The vertex type.
- * @param [in] project The projection functor.
- * @param [in] poly A vector containing the input polygon,
- * represented as vert_t pointers.
- * @param [out] result A vector of triangles, represented as
- * indicies into poly.
- */
- template<typename project_t, typename vert_t>
- void triangulate(const project_t &project,
- const std::vector<vert_t> &poly,
- std::vector<tri_idx> &result);
-
- /**
- * \brief Improve a candidate triangulation of poly by minimising
- * the length of internal edges. (templated)
- *
- * @tparam project_t A functor which converts vertices to a 2d
- * projection.
- * @tparam vert_t The vertex type.
- * @param [in] project The projection functor.
- * @param [in] poly A vector containing the input polygon,
- * represented as vert_t pointers.
- * @param [inout] result A vector of triangles, represented as
- * indicies into poly. On input, this vector
- * must contain a candidate triangulation of
- * poly. Calling improve() modifies the
- * contents of the vector, returning an
- * improved triangulation.
- */
- template<typename project_t, typename vert_t>
- void improve(const project_t &project,
- const std::vector<vert_t> &poly,
- std::vector<tri_idx> &result);
-
- /**
- * \brief Improve a candidate triangulation of poly by minimising
- * the length of internal edges.
- *
- * @param [in] poly A vector containing the input polygon.
-
- * @param [inout] result A vector of triangles, represented as
- * indicies into poly. On input, this vector
- * must contain a candidate triangulation of
- * poly. Calling improve() modifies the
- * contents of the vector, returning an
- * improved triangulation.
- */
- static inline void improve(const std::vector<carve::geom2d::P2> &poly, std::vector<tri_idx> &result) {
- improve(carve::geom2d::p2_adapt_ident(), poly, result);
- }
-
- }
-}
-
-#include <carve/triangulator_impl.hpp>
diff --git a/extern/carve/include/carve/triangulator_impl.hpp b/extern/carve/include/carve/triangulator_impl.hpp
deleted file mode 100644
index 5358268d81a..00000000000
--- a/extern/carve/include/carve/triangulator_impl.hpp
+++ /dev/null
@@ -1,851 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/geom2d.hpp>
-
-#if defined(CARVE_DEBUG)
-# include <iostream>
-#endif
-
-namespace carve {
- namespace triangulate {
- namespace detail {
-
-
-
- static inline bool axisOrdering(const carve::geom2d::P2 &a,
- const carve::geom2d::P2 &b,
- int axis) {
- return a.v[axis] < b.v[axis] || (a.v[axis] == b.v[axis] && a.v[1-axis] < b.v[1-axis]);
- }
-
-
-
- /**
- * \class order_h_loops
- * \brief Provides an ordering of hole loops based upon a single
- * projected axis.
- *
- * @tparam project_t A functor which converts vertices to a 2d
- * projection.
- * @tparam hole_t A collection of vertices.
- */
- template<typename project_t, typename vert_t>
- class order_h_loops {
- const project_t &project;
- int axis;
- public:
-
- /**
- *
- * @param _project The projection functor.
- * @param _axis The axis of the 2d projection upon which hole
- * loops are ordered.
- */
- order_h_loops(const project_t &_project, int _axis) : project(_project), axis(_axis) { }
-
- bool operator()(const vert_t &a,
- const vert_t &b) const {
- return axisOrdering(project(a), project(b), axis);
- }
-
- bool operator()(
- const std::pair<const typename std::vector<vert_t> *, typename std::vector<vert_t>::const_iterator> &a,
- const std::pair<const typename std::vector<vert_t> *, typename std::vector<vert_t>::const_iterator> &b) {
- return axisOrdering(project(*(a.second)), project(*(b.second)), axis);
- }
- };
-
-
-
- /**
- * \class heap_ordering
- * \brief Provides an ordering of vertex indicies in a polygon
- * loop according to proximity to a vertex.
- *
- * @tparam project_t A functor which converts vertices to a 2d
- * projection.
- * @tparam vert_t A vertex type.
- */
- template<typename project_t, typename vert_t>
- class heap_ordering {
- const project_t &project;
- const std::vector<vert_t> &loop;
- const carve::geom2d::P2 p;
- int axis;
-
- public:
- /**
- *
- * @param _project A functor which converts vertices to a 2d
- * projection.
- * @param _loop The polygon loop which indices address.
- * @param _vert The vertex from which distance is measured.
- *
- */
- heap_ordering(const project_t &_project,
- const std::vector<vert_t> &_loop,
- vert_t _vert,
- int _axis) :
- project(_project),
- loop(_loop),
- p(_project(_vert)),
- axis(_axis) {
- }
-
- bool operator()(size_t a, size_t b) const {
- carve::geom2d::P2 pa = project(loop[a]);
- carve::geom2d::P2 pb = project(loop[b]);
- double da = carve::geom::distance2(p, pa);
- double db = carve::geom::distance2(p, pb);
- if (da > db) return true;
- if (da < db) return false;
- return axisOrdering(pa, pb, axis);
- }
- };
-
-
-
- /**
- * \brief Given a polygon loop and a hole loop, and attachment
- * points, insert the hole loop vertices into the polygon loop.
- *
- * @param[in,out] f_loop The polygon loop to incorporate the
- * hole into.
- * @param f_loop_attach[in] The index of the vertex of the
- * polygon loop that the hole is to be
- * attached to.
- * @param hole_attach[in] A pair consisting of a pointer to a
- * hole container and an iterator into
- * that container reflecting the point of
- * attachment of the hole.
- */
- template<typename vert_t>
- void patchHoleIntoPolygon(std::vector<vert_t> &f_loop,
- unsigned f_loop_attach,
- const std::pair<const std::vector<vert_t> *,
- typename std::vector<vert_t>::const_iterator> &hole_attach) {
- // join the vertex curr of the polygon loop to the hole at
- // h_loop_connect
- f_loop.insert(f_loop.begin() + f_loop_attach + 1, hole_attach.first->size() + 2, NULL);
- typename std::vector<vert_t>::iterator f = f_loop.begin() + f_loop_attach;
-
- typename std::vector<vert_t>::const_iterator h = hole_attach.second;
-
- while (h != hole_attach.first->end()) {
- *++f = *h++;
- }
-
- h = hole_attach.first->begin();
- typename std::vector<vert_t>::const_iterator he = hole_attach.second; ++he;
- while (h != he) {
- *++f = *h++;
- }
-
- *++f = f_loop[f_loop_attach];
- }
-
-
-
- struct vertex_info;
-
-
-
- /**
- * \brief Determine whether c is to the left of a->b.
- */
- static inline bool isLeft(const vertex_info *a,
- const vertex_info *b,
- const vertex_info *c);
-
-
-
- /**
- * \brief Determine whether d is contained in the triangle abc.
- */
- static inline bool pointInTriangle(const vertex_info *a,
- const vertex_info *b,
- const vertex_info *c,
- const vertex_info *d);
-
-
-
- /**
- * \class vertex_info
- * \brief Maintains a linked list of untriangulated vertices
- * during a triangulation operation.
- */
-
- struct vertex_info {
- vertex_info *prev;
- vertex_info *next;
- carve::geom2d::P2 p;
- size_t idx;
- double score;
- bool convex;
- bool failed;
-
- vertex_info(const carve::geom2d::P2 &_p, size_t _idx) :
- prev(NULL), next(NULL),
- p(_p), idx(_idx),
- score(0.0), convex(false) {
- }
-
- static double triScore(const vertex_info *p, const vertex_info *v, const vertex_info *n);
-
- double calcScore() const;
-
- void recompute() {
- score = calcScore();
- convex = isLeft(prev, this, next);
- failed = false;
- }
-
- bool isCandidate() const {
- return convex && !failed;
- }
-
- void remove() {
- next->prev = prev;
- prev->next = next;
- }
-
- bool isClipable() const;
- };
-
-
-
- static inline bool isLeft(const vertex_info *a,
- const vertex_info *b,
- const vertex_info *c) {
- if (a->idx < b->idx && b->idx < c->idx) {
- return carve::geom2d::orient2d(a->p, b->p, c->p) > 0.0;
- } else if (a->idx < c->idx && c->idx < b->idx) {
- return carve::geom2d::orient2d(a->p, c->p, b->p) < 0.0;
- } else if (b->idx < a->idx && a->idx < c->idx) {
- return carve::geom2d::orient2d(b->p, a->p, c->p) < 0.0;
- } else if (b->idx < c->idx && c->idx < a->idx) {
- return carve::geom2d::orient2d(b->p, c->p, a->p) > 0.0;
- } else if (c->idx < a->idx && a->idx < b->idx) {
- return carve::geom2d::orient2d(c->p, a->p, b->p) > 0.0;
- } else {
- return carve::geom2d::orient2d(c->p, b->p, a->p) < 0.0;
- }
- }
-
-
-
- static inline bool pointInTriangle(const vertex_info *a,
- const vertex_info *b,
- const vertex_info *c,
- const vertex_info *d) {
- return !isLeft(a, c, d) && !isLeft(b, a, d) && !isLeft(c, b, d);
- }
-
-
-
- size_t removeDegeneracies(vertex_info *&begin, std::vector<carve::triangulate::tri_idx> &result);
-
- bool splitAndResume(vertex_info *begin, std::vector<carve::triangulate::tri_idx> &result);
-
- bool doTriangulate(vertex_info *begin, std::vector<carve::triangulate::tri_idx> &result);
-
-
-
- typedef std::pair<unsigned, unsigned> vert_edge_t;
-
-
-
- struct hash_vert_edge_t {
- size_t operator()(const vert_edge_t &e) const {
- size_t r = (size_t)e.first;
- size_t s = (size_t)e.second;
- return r ^ ((s >> 16) | (s << 16));
- }
- };
-
-
-
- static inline vert_edge_t ordered_vert_edge_t(unsigned a, unsigned b) {
- return (a < b) ? vert_edge_t(a, b) : vert_edge_t(b, a);
- }
-
-
-
- struct tri_pair_t {
- carve::triangulate::tri_idx *a, *b;
- double score;
- size_t idx;
-
- tri_pair_t() : a(NULL), b(NULL), score(0.0) {
- }
-
- static inline unsigned N(unsigned i) { return (i+1)%3; }
- static inline unsigned P(unsigned i) { return (i+2)%3; }
-
- void findSharedEdge(unsigned &ai, unsigned &bi) const {
- if (a->v[1] == b->v[0]) { if (a->v[0] == b->v[1]) { ai = 0; bi = 0; } else { ai = 1; bi = 2; } return; }
- if (a->v[1] == b->v[1]) { if (a->v[0] == b->v[2]) { ai = 0; bi = 1; } else { ai = 1; bi = 0; } return; }
- if (a->v[1] == b->v[2]) { if (a->v[0] == b->v[0]) { ai = 0; bi = 2; } else { ai = 1; bi = 1; } return; }
- if (a->v[2] == b->v[0]) { ai = 2; bi = 2; return; }
- if (a->v[2] == b->v[1]) { ai = 2; bi = 0; return; }
- if (a->v[2] == b->v[2]) { ai = 2; bi = 1; return; }
- CARVE_FAIL("should not be reached");
- }
-
- void flip(vert_edge_t &old_edge,
- vert_edge_t &new_edge,
- vert_edge_t perim[4]);
-
- template<typename project_t, typename vert_t, typename distance_calc_t>
- double calc(const project_t &project,
- const std::vector<vert_t> &poly,
- distance_calc_t dist) {
- unsigned ai, bi;
- unsigned cross_ai, cross_bi;
- unsigned ea, eb;
-
- findSharedEdge(ai, bi);
-
-#if defined(CARVE_DEBUG)
- if (carve::geom2d::signedArea(project(poly[a->v[0]]), project(poly[a->v[1]]), project(poly[a->v[2]])) > 0.0 ||
- carve::geom2d::signedArea(project(poly[b->v[0]]), project(poly[b->v[1]]), project(poly[b->v[2]])) > 0.0) {
- std::cerr << "warning: triangle pair " << this << " contains triangles with incorrect orientation" << std::endl;
- }
-#endif
-
- cross_ai = P(ai);
- cross_bi = P(bi);
-
- ea = a->v[cross_ai];
- eb = b->v[cross_bi];
-
- double side_1 = carve::geom2d::orient2d(project(poly[ea]), project(poly[eb]), project(poly[a->v[ai]]));
- double side_2 = carve::geom2d::orient2d(project(poly[ea]), project(poly[eb]), project(poly[a->v[N(ai)]]));
-
- bool can_flip = (side_1 < 0.0 && side_2 > 0.0) || (side_1 > 0.0 && side_2 < 0.0);
-
- if (!can_flip) {
- score = -1;
- } else {
- score =
- dist(poly[a->v[ai]], poly[b->v[bi]]) -
- dist(poly[a->v[cross_ai]], poly[b->v[cross_bi]]);
- }
- return score;
- }
-
- template<typename project_t, typename vert_t, typename distance_calc_t>
- double edgeLen(const project_t &project,
- const std::vector<vert_t> &poly,
- distance_calc_t dist) const {
- unsigned ai, bi;
- findSharedEdge(ai, bi);
- return dist(poly[a->v[ai]], poly[b->v[bi]]);
- }
- };
-
-
-
- struct max_score {
- bool operator()(const tri_pair_t *a, const tri_pair_t *b) const { return a->score < b->score; }
- };
-
-
-
- struct tri_pairs_t {
- typedef std::unordered_map<vert_edge_t, tri_pair_t *, hash_vert_edge_t> storage_t;
- storage_t storage;
-
- tri_pairs_t() : storage() {
- };
-
- ~tri_pairs_t() {
- for (storage_t::iterator i = storage.begin(); i != storage.end(); ++i) {
- if ((*i).second) delete (*i).second;
- }
- }
-
- void insert(unsigned a, unsigned b, carve::triangulate::tri_idx *t);
-
- template<typename project_t, typename vert_t, typename distance_calc_t>
- void updateEdge(tri_pair_t *tp,
- const project_t &project,
- const std::vector<vert_t> &poly,
- distance_calc_t dist,
- std::vector<tri_pair_t *> &edges,
- size_t &n) {
- double old_score = tp->score;
- double new_score = tp->calc(project, poly, dist);
-#if defined(CARVE_DEBUG)
- std::cerr << "tp:" << tp << " old_score: " << old_score << " new_score: " << new_score << std::endl;
-#endif
- if (new_score > 0.0 && old_score <= 0.0) {
- tp->idx = n;
- edges[n++] = tp;
- } else if (new_score <= 0.0 && old_score > 0.0) {
- std::swap(edges[tp->idx], edges[--n]);
- edges[tp->idx]->idx = tp->idx;
- }
- }
-
- tri_pair_t *get(vert_edge_t &e) {
- storage_t::iterator i;
- i = storage.find(e);
- if (i == storage.end()) return NULL;
- return (*i).second;
- }
-
- template<typename project_t, typename vert_t, typename distance_calc_t>
- void flip(const project_t &project,
- const std::vector<vert_t> &poly,
- distance_calc_t dist,
- std::vector<tri_pair_t *> &edges,
- size_t &n) {
- vert_edge_t old_e, new_e;
- vert_edge_t perim[4];
-
-#if defined(CARVE_DEBUG)
- std::cerr << "improvable edges: " << n << std::endl;
-#endif
-
- tri_pair_t *tp = *std::max_element(edges.begin(), edges.begin() + n, max_score());
-
-#if defined(CARVE_DEBUG)
- std::cerr << "improving tri-pair: " << tp << " with score: " << tp->score << std::endl;
-#endif
-
- tp->flip(old_e, new_e, perim);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "old_e: " << old_e.first << "," << old_e.second << " -> new_e: " << new_e.first << "," << new_e.second << std::endl;
-#endif
-
- CARVE_ASSERT(storage.find(old_e) != storage.end());
- storage.erase(old_e);
- storage[new_e] = tp;
-
- std::swap(edges[tp->idx], edges[--n]);
- edges[tp->idx]->idx = tp->idx;
-
- tri_pair_t *tp2;
-
- tp2 = get(perim[0]);
- if (tp2 != NULL) {
- updateEdge(tp2, project, poly, dist, edges, n);
- }
-
- tp2 = get(perim[1]);
- if (tp2 != NULL) {
- CARVE_ASSERT(tp2->a == tp->b || tp2->b == tp->b);
- if (tp2->a == tp->b) { tp2->a = tp->a; } else { tp2->b = tp->a; }
- updateEdge(tp2, project, poly, dist, edges, n);
- }
-
- tp2 = get(perim[2]);
- if (tp2 != NULL) {
- updateEdge(tp2, project, poly, dist, edges, n);
- }
-
- tp2 = get(perim[3]);
- if (tp2 != NULL) {
- CARVE_ASSERT(tp2->a == tp->a || tp2->b == tp->a);
- if (tp2->a == tp->a) { tp2->a = tp->b; } else { tp2->b = tp->b; }
- updateEdge(tp2, project, poly, dist, edges, n);
- }
- }
-
- template<typename project_t, typename vert_t, typename distance_calc_t>
- size_t getInternalEdges(const project_t &project,
- const std::vector<vert_t> &poly,
- distance_calc_t dist,
- std::vector<tri_pair_t *> &edges) {
- size_t count = 0;
-
- for (storage_t::iterator i = storage.begin(); i != storage.end();) {
- tri_pair_t *tp = (*i).second;
- if (tp->a && tp->b) {
- tp->calc(project, poly, dist);
- count++;
-#if defined(CARVE_DEBUG)
- std::cerr << "internal edge: " << (*i).first.first << "," << (*i).first.second << " -> " << tp << " " << tp->score << std::endl;
-#endif
- ++i;
- } else {
- delete (*i).second;
- storage.erase(i++);
- }
- }
-
- edges.resize(count);
-
- size_t fwd = 0;
- size_t rev = count;
- for (storage_t::iterator i = storage.begin(); i != storage.end(); ++i) {
- tri_pair_t *tp = (*i).second;
- if (tp && tp->a && tp->b) {
- if (tp->score > 0.0) {
- edges[fwd++] = tp;
- } else {
- edges[--rev] = tp;
- }
- }
- }
-
- CARVE_ASSERT(fwd == rev);
-
- return fwd;
- }
- };
-
-
-
- template<typename project_t, typename vert_t>
- static bool
- testCandidateAttachment(const project_t &project,
- std::vector<vert_t> &current_f_loop,
- size_t curr,
- carve::geom2d::P2 hole_min) {
- const size_t SZ = current_f_loop.size();
-
- size_t prev, next;
-
- if (curr == 0) {
- prev = SZ - 1; next = 1;
- } else if (curr == SZ - 1) {
- prev = curr - 1; next = 0;
- } else {
- prev = curr - 1; next = curr + 1;
- }
-
- if (!carve::geom2d::internalToAngle(project(current_f_loop[next]),
- project(current_f_loop[curr]),
- project(current_f_loop[prev]),
- hole_min)) {
- return false;
- }
-
- if (hole_min == project(current_f_loop[curr])) {
- return true;
- }
-
- carve::geom2d::LineSegment2 test(hole_min, project(current_f_loop[curr]));
-
- size_t v1 = current_f_loop.size() - 1;
- size_t v2 = 0;
- double v1_side = carve::geom2d::orient2d(test.v1, test.v2, project(current_f_loop[v1]));
- double v2_side = 0;
-
- while (v2 != current_f_loop.size()) {
- v2_side = carve::geom2d::orient2d(test.v1, test.v2, project(current_f_loop[v2]));
-
- if (v1_side != v2_side) {
- // XXX: need to test vertices, not indices, because they may
- // be duplicated.
- if (project(current_f_loop[v1]) != project(current_f_loop[curr]) &&
- project(current_f_loop[v2]) != project(current_f_loop[curr])) {
- carve::geom2d::LineSegment2 test2(project(current_f_loop[v1]), project(current_f_loop[v2]));
- if (carve::geom2d::lineSegmentIntersection_simple(test, test2)) {
- // intersection; failed.
- return false;
- }
- }
- }
-
- v1 = v2;
- v1_side = v2_side;
- ++v2;
- }
- return true;
- }
-
-
-
- }
-
-
-
- template<typename project_t, typename vert_t>
- static std::vector<vert_t>
- incorporateHolesIntoPolygon(const project_t &project,
- const std::vector<vert_t> &f_loop,
- const std::vector<std::vector<vert_t> > &h_loops) {
- typedef std::vector<vert_t> hole_t;
- typedef typename std::vector<vert_t>::const_iterator vert_iter;
- typedef typename std::vector<std::vector<vert_t> >::const_iterator hole_iter;
-
- size_t N = f_loop.size();
-
- // work out how much space to reserve for the patched in holes.
- for (hole_iter i = h_loops.begin(); i != h_loops.end(); ++i) {
- N += 2 + (*i).size();
- }
-
- // this is the vector that we will build the result in.
- std::vector<vert_t> current_f_loop;
- current_f_loop.reserve(N);
-
- std::vector<size_t> f_loop_heap;
- f_loop_heap.reserve(N);
-
- for (unsigned i = 0; i < f_loop.size(); ++i) {
- current_f_loop.push_back(f_loop[i]);
- }
-
- std::vector<std::pair<const std::vector<vert_t> *, vert_iter> > h_loop_min_vertex;
-
- h_loop_min_vertex.reserve(h_loops.size());
-
- // find the major axis for the holes - this is the axis that we
- // will sort on for finding vertices on the polygon to join
- // holes up to.
- //
- // it might also be nice to also look for whether it is better
- // to sort ascending or descending.
- //
- // another trick that could be used is to modify the projection
- // by 90 degree rotations or flipping about an axis. just as
- // long as we keep the carve::geom3d::Vector pointers for the
- // real data in sync, everything should be ok. then we wouldn't
- // need to accomodate axes or sort order in the main loop.
-
- // find the bounding box of all the holes.
- bool first = true;
- double min_x, min_y, max_x, max_y;
- for (hole_iter i = h_loops.begin(); i != h_loops.end(); ++i) {
- const hole_t &hole(*i);
- for (vert_iter j = hole.begin(); j != hole.end(); ++j) {
- carve::geom2d::P2 curr = project(*j);
- if (first) {
- min_x = max_x = curr.x;
- min_y = max_y = curr.y;
- first = false;
- } else {
- min_x = std::min(min_x, curr.x);
- min_y = std::min(min_y, curr.y);
- max_x = std::max(max_x, curr.x);
- max_y = std::max(max_y, curr.y);
- }
- }
- }
-
- // choose the axis for which the bbox is largest.
- int axis = (max_x - min_x) > (max_y - min_y) ? 0 : 1;
-
- // for each hole, find the minimum vertex in the chosen axis.
- for (hole_iter i = h_loops.begin(); i != h_loops.end(); ++i) {
- const hole_t &hole = *i;
- vert_iter best_i = std::min_element(hole.begin(), hole.end(), detail::order_h_loops<project_t, vert_t>(project, axis));
- h_loop_min_vertex.push_back(std::make_pair(&hole, best_i));
- }
-
- // sort the holes by the minimum vertex.
- std::sort(h_loop_min_vertex.begin(), h_loop_min_vertex.end(), detail::order_h_loops<project_t, vert_t>(project, axis));
-
- // now, for each hole, find a vertex in the current polygon loop that it can be joined to.
- for (unsigned i = 0; i < h_loop_min_vertex.size(); ++i) {
- const size_t N_f_loop = current_f_loop.size();
-
- // the index of the vertex in the hole to connect.
- vert_iter h_loop_connect = h_loop_min_vertex[i].second;
-
- carve::geom2d::P2 hole_min = project(*h_loop_connect);
-
- f_loop_heap.clear();
- // we order polygon loop vertices that may be able to be connected
- // to the hole vertex by their distance to the hole vertex
- detail::heap_ordering<project_t, vert_t> _heap_ordering(project, current_f_loop, *h_loop_connect, axis);
-
- for (size_t j = 0; j < N_f_loop; ++j) {
- // it is guaranteed that there exists a polygon vertex with
- // coord < the min hole coord chosen, which can be joined to
- // the min hole coord without crossing the polygon
- // boundary. also, because we merge holes in ascending
- // order, it is also true that this join can never cross
- // another hole (and that doesn't need to be tested for).
- if (project(current_f_loop[j]).v[axis] <= hole_min.v[axis]) {
- f_loop_heap.push_back(j);
- std::push_heap(f_loop_heap.begin(), f_loop_heap.end(), _heap_ordering);
- }
- }
-
- // we are going to test each potential (according to the
- // previous test) polygon vertex as a candidate join. we order
- // by closeness to the hole vertex, so that the join we make
- // is as small as possible. to test, we need to check the
- // joining line segment does not cross any other line segment
- // in the current polygon loop (excluding those that have the
- // vertex that we are attempting to join with as an endpoint).
- size_t attachment_point = current_f_loop.size();
-
- while (f_loop_heap.size()) {
- std::pop_heap(f_loop_heap.begin(), f_loop_heap.end(), _heap_ordering);
- size_t curr = f_loop_heap.back();
- f_loop_heap.pop_back();
- // test the candidate join from current_f_loop[curr] to hole_min
-
- if (!detail::testCandidateAttachment(project, current_f_loop, curr, hole_min)) {
- continue;
- }
-
- attachment_point = curr;
- break;
- }
-
- if (attachment_point == current_f_loop.size()) {
- CARVE_FAIL("didn't manage to link up hole!");
- }
-
- detail::patchHoleIntoPolygon(current_f_loop, attachment_point, h_loop_min_vertex[i]);
- }
-
- return current_f_loop;
- }
-
-
-
- template<typename project_t, typename vert_t>
- void triangulate(const project_t &project,
- const std::vector<vert_t> &poly,
- std::vector<tri_idx> &result) {
- std::vector<detail::vertex_info *> vinfo;
- const size_t N = poly.size();
-
- result.clear();
- if (N < 3) {
- return;
- }
-
- result.reserve(poly.size() - 2);
-
- if (N == 3) {
- result.push_back(tri_idx(0, 1, 2));
- return;
- }
-
- vinfo.resize(N);
-
- vinfo[0] = new detail::vertex_info(project(poly[0]), 0);
- for (size_t i = 1; i < N-1; ++i) {
- vinfo[i] = new detail::vertex_info(project(poly[i]), i);
- vinfo[i]->prev = vinfo[i-1];
- vinfo[i-1]->next = vinfo[i];
- }
- vinfo[N-1] = new detail::vertex_info(project(poly[N-1]), N-1);
- vinfo[N-1]->prev = vinfo[N-2];
- vinfo[N-1]->next = vinfo[0];
- vinfo[0]->prev = vinfo[N-1];
- vinfo[N-2]->next = vinfo[N-1];
-
- for (size_t i = 0; i < N; ++i) {
- vinfo[i]->recompute();
- }
-
- detail::vertex_info *begin = vinfo[0];
-
- removeDegeneracies(begin, result);
- doTriangulate(begin, result);
- }
-
-
-
- template<typename project_t, typename vert_t, typename distance_calc_t>
- void improve(const project_t &project,
- const std::vector<vert_t> &poly,
- distance_calc_t dist,
- std::vector<tri_idx> &result) {
- detail::tri_pairs_t tri_pairs;
-
-#if defined(CARVE_DEBUG)
- bool warn = false;
- for (size_t i = 0; i < result.size(); ++i) {
- tri_idx &t = result[i];
- if (carve::geom2d::signedArea(project(poly[t.a]), project(poly[t.b]), project(poly[t.c])) > 0) {
- warn = true;
- }
- }
- if (warn) {
- std::cerr << "carve::triangulate::improve(): Some triangles are incorrectly oriented. Results may be incorrect." << std::endl;
- }
-#endif
-
- for (size_t i = 0; i < result.size(); ++i) {
- tri_idx &t = result[i];
- tri_pairs.insert(t.a, t.b, &t);
- tri_pairs.insert(t.b, t.c, &t);
- tri_pairs.insert(t.c, t.a, &t);
- }
-
- std::vector<detail::tri_pair_t *> edges;
- size_t n = tri_pairs.getInternalEdges(project, poly, dist, edges);
- for (size_t i = 0; i < n; ++i) {
- edges[i]->idx = i;
- }
-
- // procedure:
- // while a tri pair with a positive score exists:
- // p = pair with highest positive score
- // flip p, rewriting its two referenced triangles.
- // negate p's score
- // for each q in the up-to-four adjoining tri pairs:
- // update q's tri ptr, if changed, and its score.
-
-#if defined(CARVE_DEBUG)
- double initial_score = 0;
- for (size_t i = 0; i < edges.size(); ++i) {
- initial_score += edges[i]->edgeLen(project, poly, dist);
- }
- std::cerr << "initial score: " << initial_score << std::endl;
-#endif
-
- while (n) {
- tri_pairs.flip(project, poly, dist, edges, n);
- }
-
-#if defined(CARVE_DEBUG)
- double final_score = 0;
- for (size_t i = 0; i < edges.size(); ++i) {
- final_score += edges[i]->edgeLen(project, poly, dist);
- }
- std::cerr << "final score: " << final_score << std::endl;
-#endif
-
-#if defined(CARVE_DEBUG)
- if (!warn) {
- for (size_t i = 0; i < result.size(); ++i) {
- tri_idx &t = result[i];
- CARVE_ASSERT (carve::geom2d::signedArea(project(poly[t.a]), project(poly[t.b]), project(poly[t.c])) <= 0.0);
- }
- }
-#endif
- }
-
-
-
- template<typename project_t, typename vert_t>
- void improve(const project_t &project,
- const std::vector<vert_t> &poly,
- std::vector<tri_idx> &result) {
- improve(project, poly, carve::geom::distance_functor(), result);
- }
-
-
-
- }
-}
diff --git a/extern/carve/include/carve/util.hpp b/extern/carve/include/carve/util.hpp
deleted file mode 100644
index 8d7f6b933ce..00000000000
--- a/extern/carve/include/carve/util.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-namespace carve {
- namespace util {
- struct min_functor {
- template<typename T>
- const T &operator()(const T &a, const T &b) const { return std::min(a, b); }
- };
- struct max_functor {
- template<typename T>
- const T &operator()(const T &a, const T &b) const { return std::max(a, b); }
- };
- }
-}
diff --git a/extern/carve/include/carve/vcpp_config.h b/extern/carve/include/carve/vcpp_config.h
deleted file mode 100644
index 5ebd4006159..00000000000
--- a/extern/carve/include/carve/vcpp_config.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* include/carve/config.h. Generated from config.h.in by configure. */
-#pragma once
-
-#include <math.h>
-
-/* Define if using boost collections. Preferred, because the visual C++ unordered collections are slow and memory hungry. */
-#define HAVE_BOOST_UNORDERED_COLLECTIONS
-
-#if defined(_MSC_VER)
-# pragma warning(disable:4201)
-#endif
-
-#include <math.h>
-
-static inline double round(double value) {
- return (value >= 0) ? floor(value + 0.5) : ceil(value - 0.5);
-}
diff --git a/extern/carve/include/carve/vector.hpp b/extern/carve/include/carve/vector.hpp
deleted file mode 100644
index b7e81e92c88..00000000000
--- a/extern/carve/include/carve/vector.hpp
+++ /dev/null
@@ -1,163 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/math_constants.hpp>
-#include <carve/geom.hpp>
-#include <carve/geom3d.hpp>
-
-#include <sstream>
-#include <algorithm>
-
-#include <math.h>
-
-namespace carve {
- namespace geom3d {
-
- struct hash_vector_ptr {
- size_t operator()(const Vector * const &v) const {
- return (size_t)v;
- }
- size_t operator()(const std::pair<const Vector *, const Vector *> &v) const {
- size_t r = (size_t)v.first;
- size_t s = (size_t)v.second;
- return r ^ ((s >> 16) | (s << 16));
- }
- };
-
-
-
- struct vec_adapt_ident {
- const Vector &operator()(const Vector &v) const { return v; }
- Vector &operator()(Vector &v) const { return v; }
- };
-
-
-
- struct vec_adapt_ptr {
- const Vector &operator()(const Vector * const &v) const { return *v; }
- Vector &operator()(Vector *&v) const { return *v; }
- };
-
-
-
- struct vec_adapt_pair_first {
- template<typename pair_t> const Vector &operator()(const pair_t &v) const { return v.first; }
- template<typename pair_t> Vector &operator()(pair_t &v) const { return v.first; }
- };
-
-
-
- struct vec_adapt_pair_second {
- template<typename pair_t> const Vector &operator()(const pair_t &v) const { return v.second; }
- template<typename pair_t> Vector &operator()(pair_t &v) const { return v.second; }
- };
-
-
-
- template<typename adapt_t>
- struct vec_cmp_lt_x {
- adapt_t adapt;
- vec_cmp_lt_x(adapt_t _adapt = adapt_t()) : adapt(_adapt) {}
- template<typename input_t> bool operator()(const input_t &a, const input_t &b) const { return adapt(a).x < adapt(b).x; }
- };
- template<typename adapt_t> vec_cmp_lt_x<adapt_t> vec_lt_x(adapt_t &adapt) { return vec_cmp_lt_x<adapt_t>(adapt); }
-
-
-
- template<typename adapt_t>
- struct vec_cmp_lt_y {
- adapt_t adapt;
- vec_cmp_lt_y(adapt_t _adapt = adapt_t()) : adapt(_adapt) {}
- template<typename input_t> bool operator()(const input_t &a, const input_t &b) const { return adapt(a).y < adapt(b).y; }
- };
- template<typename adapt_t> vec_cmp_lt_y<adapt_t> vec_lt_y(adapt_t &adapt) { return vec_cmp_lt_y<adapt_t>(adapt); }
-
-
-
- template<typename adapt_t>
- struct vec_cmp_lt_z {
- adapt_t adapt;
- vec_cmp_lt_z(adapt_t _adapt = adapt_t()) : adapt(_adapt) {}
- template<typename input_t> bool operator()(const input_t &a, const input_t &b) const { return adapt(a).z < adapt(b).z; }
- };
- template<typename adapt_t> vec_cmp_lt_z<adapt_t> vec_lt_z(adapt_t &adapt) { return vec_cmp_lt_z<adapt_t>(adapt); }
-
-
-
- template<typename adapt_t>
- struct vec_cmp_gt_x {
- adapt_t adapt;
- vec_cmp_gt_x(adapt_t _adapt = adapt_t()) : adapt(_adapt) {}
- template<typename input_t> bool operator()(const input_t &a, const input_t &b) const { return adapt(a).x > adapt(b).x; }
- };
- template<typename adapt_t> vec_cmp_gt_x<adapt_t> vec_gt_x(adapt_t &adapt) { return vec_cmp_gt_x<adapt_t>(adapt); }
-
-
-
- template<typename adapt_t>
- struct vec_cmp_gt_y {
- adapt_t adapt;
- vec_cmp_gt_y(adapt_t _adapt = adapt_t()) : adapt(_adapt) {}
- template<typename input_t> bool operator()(const input_t &a, const input_t &b) const { return adapt(a).y > adapt(b).y; }
- };
- template<typename adapt_t> vec_cmp_gt_y<adapt_t> vec_gt_y(adapt_t &adapt) { return vec_cmp_gt_y<adapt_t>(adapt); }
-
-
-
- template<typename adapt_t>
- struct vec_cmp_gt_z {
- adapt_t adapt;
- vec_cmp_gt_z(adapt_t _adapt = adapt_t()) : adapt(_adapt) {}
- template<typename input_t> bool operator()(const input_t &a, const input_t &b) const { return adapt(a).z > adapt(b).z; }
- };
- template<typename adapt_t> vec_cmp_gt_z<adapt_t> vec_gt_z(adapt_t &adapt) { return vec_cmp_gt_z<adapt_t>(adapt); }
-
-
-
- template<typename iter_t, typename adapt_t>
- void sortInDirectionOfRay(const Vector &ray_dir, iter_t begin, iter_t end, adapt_t adapt) {
- switch (carve::geom::largestAxis(ray_dir)) {
- case 0:
- if (ray_dir.x > 0) {
- std::sort(begin, end, vec_lt_x(adapt));
- } else {
- std::sort(begin, end, vec_gt_x(adapt));
- }
- break;
- case 1:
- if (ray_dir.y > 0) {
- std::sort(begin, end, vec_lt_y(adapt));
- } else {
- std::sort(begin, end, vec_gt_y(adapt));
- }
- break;
- case 2:
- if (ray_dir.z > 0) {
- std::sort(begin, end, vec_lt_z(adapt));
- } else {
- std::sort(begin, end, vec_gt_z(adapt));
- }
- break;
- }
- }
-
- }
-}
diff --git a/extern/carve/include/carve/vertex_decl.hpp b/extern/carve/include/carve/vertex_decl.hpp
deleted file mode 100644
index 4719b72c0ee..00000000000
--- a/extern/carve/include/carve/vertex_decl.hpp
+++ /dev/null
@@ -1,111 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/geom2d.hpp>
-#include <carve/vector.hpp>
-#include <carve/matrix.hpp>
-#include <carve/geom3d.hpp>
-#include <carve/aabb.hpp>
-#include <carve/tag.hpp>
-
-#include <vector>
-#include <list>
-#include <map>
-
-namespace carve {
- namespace poly {
-
-
-
- struct Object;
-
-
-
- template<unsigned ndim>
- class Vertex : public tagable {
- public:
- typedef carve::geom::vector<ndim> vector_t;
- typedef Object obj_t;
-
- vector_t v;
- obj_t *owner;
-
- Vertex() : tagable(), v() {
- }
-
- ~Vertex() {
- }
-
- Vertex(const vector_t &_v) : tagable(), v(_v) {
- }
- };
-
-
-
- struct hash_vertex_ptr {
- template<unsigned ndim>
- size_t operator()(const Vertex<ndim> * const &v) const {
- return (size_t)v;
- }
-
- template<unsigned ndim>
- size_t operator()(const std::pair<const Vertex<ndim> *, const Vertex<ndim> *> &v) const {
- size_t r = (size_t)v.first;
- size_t s = (size_t)v.second;
- return r ^ ((s >> 16) | (s << 16));
- }
-
- };
-
-
-
- template<unsigned ndim>
- double distance(const Vertex<ndim> *v1, const Vertex<ndim> *v2) {
- return distance(v1->v, v2->v);
- }
-
- template<unsigned ndim>
- double distance(const Vertex<ndim> &v1, const Vertex<ndim> &v2) {
- return distance(v1.v, v2.v);
- }
-
- struct vec_adapt_vertex_ref {
- template<unsigned ndim>
- const typename Vertex<ndim>::vector_t &operator()(const Vertex<ndim> &v) const { return v.v; }
-
- template<unsigned ndim>
- typename Vertex<ndim>::vector_t &operator()(Vertex<ndim> &v) const { return v.v; }
- };
-
-
-
- struct vec_adapt_vertex_ptr {
- template<unsigned ndim>
- const typename Vertex<ndim>::vector_t &operator()(const Vertex<ndim> *v) const { return v->v; }
-
- template<unsigned ndim>
- typename Vertex<ndim>::vector_t &operator()(Vertex<ndim> *v) const { return v->v; }
- };
-
-
-
- }
-}
diff --git a/extern/carve/include/carve/vertex_impl.hpp b/extern/carve/include/carve/vertex_impl.hpp
deleted file mode 100644
index 9ff13782c08..00000000000
--- a/extern/carve/include/carve/vertex_impl.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-namespace carve {
- namespace poly {
-
- }
-}
diff --git a/extern/carve/include/carve/win32.h b/extern/carve/include/carve/win32.h
deleted file mode 100755
index 78a101e6f98..00000000000
--- a/extern/carve/include/carve/win32.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2006 Tobias Sargeant (toby@permuted.net)
-// All rights reserved.
-#pragma once
-
-#pragma warning (disable : 4996)
-#pragma warning (disable : 4786)
-
-#include <string.h>
-#include <stdlib.h>
-
-inline int strcasecmp(const char *a, const char *b) {
- return _stricmp(a,b);
-}
-
-inline void srandom(unsigned long input) {
- srand(input);
-}
-
-inline long random() {
- return rand();
-}
-
-#if defined(_MSC_VER)
-# include <carve/cbrt.h>
-
-#if _MSC_VER < 1300
-// intptr_t is an integer type that is big enough to hold a pointer
-// It is not defined in VC6 so include a definition here for the older compiler
-typedef long intptr_t;
-typedef unsigned long uintptr_t;
-#endif
-
-# if _MSC_VER < 1600
-// stdint.h is not available before VS2010
-#if defined(_WIN32)
-/* The __intXX are built-in types of the visual complier! So we don't
- need to include anything else here.
- This typedefs should be in sync with types from MEM_sys_types.h */
-
-typedef signed __int8 int8_t;
-typedef signed __int16 int16_t;
-typedef signed __int32 int32_t;
-
-typedef unsigned __int8 uint8_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int32 uint32_t;
-#endif
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-# else
-# include <stdint.h>
-# endif
-#endif
-
-#if defined(_MSC_VER)
-# include <BaseTsd.h>
-typedef SSIZE_T ssize_t;
-#endif
diff --git a/extern/carve/lib/carve.cpp b/extern/carve/lib/carve.cpp
deleted file mode 100644
index becaa1d9f90..00000000000
--- a/extern/carve/lib/carve.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/carve.hpp>
-
-#define DEF_EPSILON 1.4901161193847656e-08
-
-namespace carve {
- double EPSILON = DEF_EPSILON;
- double EPSILON2 = DEF_EPSILON * DEF_EPSILON;
-}
diff --git a/extern/carve/lib/convex_hull.cpp b/extern/carve/lib/convex_hull.cpp
deleted file mode 100644
index e923746f532..00000000000
--- a/extern/carve/lib/convex_hull.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/csg.hpp>
-#include <carve/convex_hull.hpp>
-
-#include <algorithm>
-
-namespace {
-
- bool grahamScan(const std::vector<carve::geom2d::P2> &points,
- int vpp, int vp,
- const std::vector<int> &ordered,
- int start,
- std::vector<int> &result, int _i = 0) {
- carve::geom2d::P2 v1 = points[vp] - points[vpp];
- if (start == (int)ordered.size()) return true;
-
- for (int i = start; i < (int)ordered.size(); ++i) {
- int v = ordered[i];
- carve::geom2d::P2 v2 = points[v] - points[vp];
-
- double cp = v1.x * v2.y - v2.x * v1.y;
- if (cp < 0) return false;
-
- int j = i + 1;
- while (j < (int)ordered.size() && points[ordered[j]] == points[v]) j++;
-
- result.push_back(v);
- if (grahamScan(points, vp, v, ordered, j, result, _i + 1)) return true;
- result.pop_back();
- }
-
- return false;
- }
-
-}
-
-namespace carve {
- namespace geom {
-
- std::vector<int> convexHull(const std::vector<carve::geom2d::P2> &points) {
- double max_x = points[0].x;
- unsigned max_v = 0;
-
- for (unsigned i = 1; i < points.size(); ++i) {
- if (points[i].x > max_x) {
- max_x = points[i].x;
- max_v = i;
- }
- }
-
- std::vector<std::pair<double, double> > angle_dist;
- std::vector<int> ordered;
- angle_dist.reserve(points.size());
- ordered.reserve(points.size() - 1);
- for (unsigned i = 0; i < points.size(); ++i) {
- if (i == max_v) continue;
- angle_dist[i] = std::make_pair(carve::math::ANG(carve::geom2d::atan2(points[i] - points[max_v])), distance2(points[i], points[max_v]));
- ordered.push_back(i);
- }
-
- std::sort(ordered.begin(),
- ordered.end(),
- make_index_sort(angle_dist.begin()));
-
- std::vector<int> result;
- result.push_back(max_v);
- result.push_back(ordered[0]);
-
- if (!grahamScan(points, max_v, ordered[0], ordered, 1, result)) {
- result.clear();
- throw carve::exception("convex hull failed!");
- }
-
- return result;
- }
-
- }
-}
-
-
diff --git a/extern/carve/lib/csg.cpp b/extern/carve/lib/csg.cpp
deleted file mode 100644
index 7e790def024..00000000000
--- a/extern/carve/lib/csg.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/csg.hpp>
-#include "csg_detail.hpp"
-
-
-const char *carve::csg::ENUM(carve::csg::FaceClass f) {
- if (f == FACE_ON_ORIENT_OUT) return "FACE_ON_ORIENT_OUT";
- if (f == FACE_OUT) return "FACE_OUT";
- if (f == FACE_IN) return "FACE_IN";
- if (f == FACE_ON_ORIENT_IN) return "FACE_ON_ORIENT_IN";
- return "???";
-}
-
-
-
-const char *carve::csg::ENUM(carve::PointClass p) {
- if (p == POINT_UNK) return "POINT_UNK";
- if (p == POINT_OUT) return "POINT_OUT";
- if (p == POINT_ON) return "POINT_ON";
- if (p == POINT_IN) return "POINT_IN";
- if (p == POINT_VERTEX) return "POINT_VERTEX";
- if (p == POINT_EDGE) return "POINT_EDGE";
- return "???";
-}
-
-
-
-void carve::csg::detail::LoopEdges::addFaceLoop(FaceLoop *fl) {
- carve::mesh::MeshSet<3>::vertex_t *v1, *v2;
- v1 = fl->vertices[fl->vertices.size() - 1];
- for (unsigned j = 0; j < fl->vertices.size(); ++j) {
- v2 = fl->vertices[j];
- (*this)[std::make_pair(v1, v2)].push_back(fl);
- v1 = v2;
- }
-}
-
-
-
-void carve::csg::detail::LoopEdges::sortFaceLoopLists() {
- for (super::iterator i = begin(), e = end(); i != e; ++i) {
- (*i).second.sort();
- }
-}
-
-
-
-void carve::csg::detail::LoopEdges::removeFaceLoop(FaceLoop *fl) {
- carve::mesh::MeshSet<3>::vertex_t *v1, *v2;
- v1 = fl->vertices[fl->vertices.size() - 1];
- for (unsigned j = 0; j < fl->vertices.size(); ++j) {
- v2 = fl->vertices[j];
- iterator l(find(std::make_pair(v1, v2)));
- if (l != end()) {
- (*l).second.remove(fl);
- if (!(*l).second.size()) {
- erase(l);
- }
- }
- v1 = v2;
- }
-}
-
-
-
-carve::csg::FaceClass carve::csg::FaceLoopGroup::classificationAgainst(const carve::mesh::MeshSet<3>::mesh_t *mesh) const {
- for (std::list<ClassificationInfo>::const_iterator i = classification.begin(); i != classification.end(); ++i) {
- if ((*i).intersected_mesh == mesh) {
- return (*i).classification;
- }
- }
- return FACE_UNCLASSIFIED;
-}
diff --git a/extern/carve/lib/csg_collector.cpp b/extern/carve/lib/csg_collector.cpp
deleted file mode 100644
index 3986a918a5e..00000000000
--- a/extern/carve/lib/csg_collector.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/csg.hpp>
-#include <iostream>
-#include "csg_collector.hpp"
-#include "intersect_debug.hpp"
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
-void writePLY(const std::string &out_file, const carve::mesh::MeshSet<3> *poly, bool ascii);
-#endif
-
-
-namespace carve {
- namespace csg {
- namespace {
-
- class BaseCollector : public CSG::Collector {
- BaseCollector();
- BaseCollector(const BaseCollector &);
- BaseCollector &operator=(const BaseCollector &);
-
- protected:
- struct face_data_t {
- carve::mesh::MeshSet<3>::face_t *face;
- const carve::mesh::MeshSet<3>::face_t *orig_face;
- bool flipped;
- face_data_t(carve::mesh::MeshSet<3>::face_t *_face,
- const carve::mesh::MeshSet<3>::face_t *_orig_face,
- bool _flipped) : face(_face), orig_face(_orig_face), flipped(_flipped) {
- };
- };
-
- std::list<face_data_t> faces;
-
- const carve::mesh::MeshSet<3> *src_a;
- const carve::mesh::MeshSet<3> *src_b;
-
- BaseCollector(const carve::mesh::MeshSet<3> *_src_a,
- const carve::mesh::MeshSet<3> *_src_b) : CSG::Collector(), src_a(_src_a), src_b(_src_b) {
- }
-
- virtual ~BaseCollector() {
- }
-
- void FWD(const carve::mesh::MeshSet<3>::face_t *orig_face,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &vertices,
- carve::geom3d::Vector /* normal */,
- bool /* poly_a */,
- FaceClass face_class,
- CSG::Hooks &hooks) {
- std::vector<carve::mesh::MeshSet<3>::face_t *> new_faces;
- new_faces.reserve(1);
- new_faces.push_back(orig_face->create(vertices.begin(), vertices.end(), false));
- hooks.processOutputFace(new_faces, orig_face, false);
- for (size_t i = 0; i < new_faces.size(); ++i) {
- faces.push_back(face_data_t(new_faces[i], orig_face, false));
- }
-
-#if defined(CARVE_DEBUG) && defined(DEBUG_PRINT_RESULT_FACES)
- std::cerr << "+" << ENUM(face_class) << " ";
- for (unsigned i = 0; i < vertices.size(); ++i) std::cerr << " " << vertices[i] << ":" << *vertices[i];
- std::cerr << std::endl;
-#endif
- }
-
- void REV(const carve::mesh::MeshSet<3>::face_t *orig_face,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &vertices,
- carve::geom3d::Vector /* normal */,
- bool /* poly_a */,
- FaceClass face_class,
- CSG::Hooks &hooks) {
- // normal = -normal;
- std::vector<carve::mesh::MeshSet<3>::face_t *> new_faces;
- new_faces.reserve(1);
- new_faces.push_back(orig_face->create(vertices.begin(), vertices.end(), true));
- hooks.processOutputFace(new_faces, orig_face, true);
- for (size_t i = 0; i < new_faces.size(); ++i) {
- faces.push_back(face_data_t(new_faces[i], orig_face, true));
- }
-
-#if defined(CARVE_DEBUG) && defined(DEBUG_PRINT_RESULT_FACES)
- std::cerr << "-" << ENUM(face_class) << " ";
- for (unsigned i = 0; i < vertices.size(); ++i) std::cerr << " " << vertices[i] << ":" << *vertices[i];
- std::cerr << std::endl;
-#endif
- }
-
- virtual void collect(const carve::mesh::MeshSet<3>::face_t *orig_face,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &vertices,
- carve::geom3d::Vector normal,
- bool poly_a,
- FaceClass face_class,
- CSG::Hooks &hooks) =0;
-
- virtual void collect(FaceLoopGroup *grp, CSG::Hooks &hooks) {
- std::list<ClassificationInfo> &cinfo = (grp->classification);
-
- if (cinfo.size() == 0) {
- std::cerr << "WARNING! group " << grp << " has no classification info!" << std::endl;
- return;
- }
-
- FaceClass fc = FACE_UNCLASSIFIED;
-
- unsigned fc_closed_bits = 0;
- unsigned fc_open_bits = 0;
- unsigned fc_bits = 0;
-
- for (std::list<ClassificationInfo>::const_iterator i = grp->classification.begin(), e = grp->classification.end(); i != e; ++i) {
-
- if ((*i).intersected_mesh == NULL) {
- // classifier only returns global info
- fc_closed_bits = class_to_class_bit((*i).classification);
- break;
- }
-
- if ((*i).classification == FACE_UNCLASSIFIED) continue;
- if ((*i).intersectedMeshIsClosed()) {
- fc_closed_bits |= class_to_class_bit((*i).classification);
- } else {
- fc_open_bits |= class_to_class_bit((*i).classification);
- }
- }
-
- if (fc_closed_bits) {
- fc_bits = fc_closed_bits;
- } else {
- fc_bits = fc_open_bits;
- }
-
- fc = class_bit_to_class(fc_bits);
-
- // handle the complex cases where a group is classified differently with respect to two or more closed manifolds.
- if (fc == FACE_UNCLASSIFIED) {
- unsigned inout_bits = fc_bits & FACE_NOT_ON_BIT;
- unsigned on_bits = fc_bits & FACE_ON_BIT;
-
- // both in and out. indicates an invalid manifold embedding.
- if (inout_bits == (FACE_IN_BIT | FACE_OUT_BIT)) goto out;
-
- // on, both orientations. could be caused by two manifolds touching at a face.
- if (on_bits == (FACE_ON_ORIENT_IN_BIT | FACE_ON_ORIENT_OUT_BIT)) goto out;
-
- // in or out, but also on (with orientation). the on classification takes precedence.
- fc = class_bit_to_class(on_bits);
- }
-
- out:
-
- if (fc == FACE_UNCLASSIFIED) {
- std::cerr << "group " << grp << " is unclassified!" << std::endl;
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- static int uc_count = 0;
-
- std::vector<carve::mesh::MeshSet<3>::face_t *> faces;
-
- for (FaceLoop *f = grp->face_loops.head; f; f = f->next) {
- carve::mesh::MeshSet<3>::face_t *temp = f->orig_face->create(f->vertices.begin(), f->vertices.end(), false);
- faces.push_back(temp);
- }
-
- carve::mesh::MeshSet<3> *p = new carve::mesh::MeshSet<3>(faces);
-
- std::ostringstream filename;
- filename << "classifier_fail_" << ++uc_count << ".ply";
- std::string out(filename.str().c_str());
- ::writePLY(out, p, false);
-
- delete p;
-#endif
-
- return;
- }
-
- bool is_poly_a = grp->src == src_a;
-
- for (FaceLoop *f = grp->face_loops.head; f; f = f->next) {
- collect(f->orig_face, f->vertices, f->orig_face->plane.N, is_poly_a, fc, hooks);
- }
- }
-
- virtual carve::mesh::MeshSet<3> *done(CSG::Hooks &hooks) {
- std::vector<carve::mesh::MeshSet<3>::face_t *> f;
- f.reserve(faces.size());
- for (std::list<face_data_t>::iterator i = faces.begin(); i != faces.end(); ++i) {
- f.push_back((*i).face);
- }
-
- carve::mesh::MeshSet<3> *p = new carve::mesh::MeshSet<3>(f);
-
- if (hooks.hasHook(carve::csg::CSG::Hooks::RESULT_FACE_HOOK)) {
- for (std::list<face_data_t>::iterator i = faces.begin(); i != faces.end(); ++i) {
- hooks.resultFace((*i).face, (*i).orig_face, (*i).flipped);
- }
- }
-
- return p;
- }
- };
-
-
-
- class AllCollector : public BaseCollector {
- public:
- AllCollector(const carve::mesh::MeshSet<3> *_src_a,
- const carve::mesh::MeshSet<3> *_src_b) : BaseCollector(_src_a, _src_b) {
- }
- virtual ~AllCollector() {
- }
- virtual void collect(FaceLoopGroup *grp, CSG::Hooks &hooks) {
- for (FaceLoop *f = grp->face_loops.head; f; f = f->next) {
- FWD(f->orig_face, f->vertices, f->orig_face->plane.N, f->orig_face->mesh->meshset == src_a, FACE_OUT, hooks);
- }
- }
- virtual void collect(const carve::mesh::MeshSet<3>::face_t *orig_face,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &vertices,
- carve::geom3d::Vector normal,
- bool poly_a,
- FaceClass face_class,
- CSG::Hooks &hooks) {
- FWD(orig_face, vertices, normal, poly_a, face_class, hooks);
- }
- };
-
-
-
- class UnionCollector : public BaseCollector {
- public:
- UnionCollector(const carve::mesh::MeshSet<3> *_src_a,
- const carve::mesh::MeshSet<3> *_src_b) : BaseCollector(_src_a, _src_b) {
- }
- virtual ~UnionCollector() {
- }
- virtual void collect(const carve::mesh::MeshSet<3>::face_t *orig_face,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &vertices,
- carve::geom3d::Vector normal,
- bool poly_a,
- FaceClass face_class,
- CSG::Hooks &hooks) {
- if (face_class == FACE_OUT || (poly_a && face_class == FACE_ON_ORIENT_OUT)) {
- FWD(orig_face, vertices, normal, poly_a, face_class, hooks);
- }
- }
- };
-
-
-
- class IntersectionCollector : public BaseCollector {
- public:
- IntersectionCollector(const carve::mesh::MeshSet<3> *_src_a,
- const carve::mesh::MeshSet<3> *_src_b) : BaseCollector(_src_a, _src_b) {
- }
- virtual ~IntersectionCollector() {
- }
- virtual void collect(const carve::mesh::MeshSet<3>::face_t *orig_face,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &vertices,
- carve::geom3d::Vector normal,
- bool poly_a,
- FaceClass face_class,
- CSG::Hooks &hooks) {
- if (face_class == FACE_IN || (poly_a && face_class == FACE_ON_ORIENT_OUT)) {
- FWD(orig_face, vertices, normal, poly_a, face_class, hooks);
- }
- }
- };
-
-
-
- class SymmetricDifferenceCollector : public BaseCollector {
- public:
- SymmetricDifferenceCollector(const carve::mesh::MeshSet<3> *_src_a,
- const carve::mesh::MeshSet<3> *_src_b) : BaseCollector(_src_a, _src_b) {
- }
- virtual ~SymmetricDifferenceCollector() {
- }
- virtual void collect(const carve::mesh::MeshSet<3>::face_t *orig_face,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &vertices,
- carve::geom3d::Vector normal,
- bool poly_a,
- FaceClass face_class,
- CSG::Hooks &hooks) {
- if (face_class == FACE_OUT) {
- FWD(orig_face, vertices, normal, poly_a, face_class, hooks);
- } else if (face_class == FACE_IN) {
- REV(orig_face, vertices, normal, poly_a, face_class, hooks);
- }
- }
- };
-
-
-
- class AMinusBCollector : public BaseCollector {
- public:
- AMinusBCollector(const carve::mesh::MeshSet<3> *_src_a,
- const carve::mesh::MeshSet<3> *_src_b) : BaseCollector(_src_a, _src_b) {
- }
- virtual ~AMinusBCollector() {
- }
- virtual void collect(const carve::mesh::MeshSet<3>::face_t *orig_face,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &vertices,
- carve::geom3d::Vector normal,
- bool poly_a,
- FaceClass face_class,
- CSG::Hooks &hooks) {
- if ((face_class == FACE_OUT || face_class == FACE_ON_ORIENT_IN) && poly_a) {
- FWD(orig_face, vertices, normal, poly_a, face_class, hooks);
- } else if (face_class == FACE_IN && !poly_a) {
- REV(orig_face, vertices, normal, poly_a, face_class, hooks);
- }
- }
- };
-
-
-
- class BMinusACollector : public BaseCollector {
- public:
- BMinusACollector(const carve::mesh::MeshSet<3> *_src_a,
- const carve::mesh::MeshSet<3> *_src_b) : BaseCollector(_src_a, _src_b) {
- }
- virtual ~BMinusACollector() {
- }
- virtual void collect(const carve::mesh::MeshSet<3>::face_t *orig_face,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &vertices,
- carve::geom3d::Vector normal,
- bool poly_a,
- FaceClass face_class,
- CSG::Hooks &hooks) {
- if ((face_class == FACE_OUT || face_class == FACE_ON_ORIENT_IN) && !poly_a) {
- FWD(orig_face, vertices, normal, poly_a, face_class, hooks);
- } else if (face_class == FACE_IN && poly_a) {
- REV(orig_face, vertices, normal, poly_a, face_class, hooks);
- }
- }
- };
-
- }
-
- CSG::Collector *makeCollector(CSG::OP op,
- const carve::mesh::MeshSet<3> *poly_a,
- const carve::mesh::MeshSet<3> *poly_b) {
- switch (op) {
- case CSG::UNION: return new UnionCollector(poly_a, poly_b);
- case CSG::INTERSECTION: return new IntersectionCollector(poly_a, poly_b);
- case CSG::A_MINUS_B: return new AMinusBCollector(poly_a, poly_b);
- case CSG::B_MINUS_A: return new BMinusACollector(poly_a, poly_b);
- case CSG::SYMMETRIC_DIFFERENCE: return new SymmetricDifferenceCollector(poly_a, poly_b);
- case CSG::ALL: return new AllCollector(poly_a, poly_b);
- }
- return NULL;
- }
- }
-}
diff --git a/extern/carve/lib/csg_collector.hpp b/extern/carve/lib/csg_collector.hpp
deleted file mode 100644
index 452f19a06a8..00000000000
--- a/extern/carve/lib/csg_collector.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-namespace carve {
- namespace csg {
- CSG::Collector *makeCollector(CSG::OP op,
- const carve::mesh::MeshSet<3> *poly_a,
- const carve::mesh::MeshSet<3> *poly_b);
- }
-}
diff --git a/extern/carve/lib/csg_data.hpp b/extern/carve/lib/csg_data.hpp
deleted file mode 100644
index c0c18d3122b..00000000000
--- a/extern/carve/lib/csg_data.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/csg.hpp>
-
-#include "csg_detail.hpp"
-
-struct carve::csg::detail::Data {
-// * @param[out] vmap A mapping from vertex pointer to intersection point.
-// * @param[out] emap A mapping from edge pointer to intersection points.
-// * @param[out] fmap A mapping from face pointer to intersection points.
-// * @param[out] fmap_rev A mapping from intersection points to face pointers.
- // map from intersected vertex to intersection point.
- VVMap vmap;
-
- // map from intersected edge to intersection points.
- EIntMap emap;
-
- // map from intersected face to intersection points.
- FVSMap fmap;
-
- // map from intersection point to intersected faces.
- VFSMap fmap_rev;
-
- // created by divideEdges().
- // holds, for each edge, an ordered vector of inserted vertices.
- EVVMap divided_edges;
-
- // created by faceSplitEdges.
- FV2SMap face_split_edges;
-
- // mapping from vertex to edge for potentially intersected
- // faces. Saves building the vertex to edge map for all faces of
- // both meshes.
- VEVecMap vert_to_edges;
-};
diff --git a/extern/carve/lib/csg_detail.hpp b/extern/carve/lib/csg_detail.hpp
deleted file mode 100644
index a985a5c6ada..00000000000
--- a/extern/carve/lib/csg_detail.hpp
+++ /dev/null
@@ -1,73 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include <carve/carve.hpp>
-
-#include <carve/polyhedron_base.hpp>
-
-namespace carve {
- namespace csg {
- namespace detail {
- typedef std::map<carve::mesh::MeshSet<3>::vertex_t *,
- std::set<std::pair<carve::mesh::MeshSet<3>::face_t *, double> > > EdgeIntInfo;
-
- typedef std::unordered_set<carve::mesh::MeshSet<3>::vertex_t *> VSet;
- typedef std::unordered_set<carve::mesh::MeshSet<3>::face_t *> FSet;
-
- typedef std::set<carve::mesh::MeshSet<3>::vertex_t *> VSetSmall;
- typedef std::set<csg::V2> V2SetSmall;
- typedef std::set<carve::mesh::MeshSet<3>::face_t *> FSetSmall;
-
- typedef std::unordered_map<carve::mesh::MeshSet<3>::vertex_t *, VSetSmall> VVSMap;
- typedef std::unordered_map<carve::mesh::MeshSet<3>::edge_t *, EdgeIntInfo> EIntMap;
- typedef std::unordered_map<carve::mesh::MeshSet<3>::face_t *, VSetSmall> FVSMap;
-
- typedef std::unordered_map<carve::mesh::MeshSet<3>::vertex_t *, FSetSmall> VFSMap;
- typedef std::unordered_map<carve::mesh::MeshSet<3>::face_t *, V2SetSmall> FV2SMap;
-
- typedef std::unordered_map<
- carve::mesh::MeshSet<3>::edge_t *,
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> > EVVMap;
-
- typedef std::unordered_map<carve::mesh::MeshSet<3>::vertex_t *,
- std::vector<carve::mesh::MeshSet<3>::edge_t *> > VEVecMap;
-
-
- class LoopEdges : public std::unordered_map<V2, std::list<FaceLoop *> > {
- typedef std::unordered_map<V2, std::list<FaceLoop *> > super;
-
- public:
- void addFaceLoop(FaceLoop *fl);
- void sortFaceLoopLists();
- void removeFaceLoop(FaceLoop *fl);
- };
-
- }
- }
-}
-
-
-
-static inline std::ostream &operator<<(std::ostream &o, const carve::csg::detail::FSet &s) {
- const char *sep="";
- for (carve::csg::detail::FSet::const_iterator i = s.begin(); i != s.end(); ++i) {
- o << sep << *i; sep=",";
- }
- return o;
-}
diff --git a/extern/carve/lib/face.cpp b/extern/carve/lib/face.cpp
deleted file mode 100644
index cb56478626f..00000000000
--- a/extern/carve/lib/face.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/poly.hpp>
-
-namespace {
-
- double CALC_X(const carve::geom::plane<3> &p, double y, double z) { return -(p.d + p.N.y * y + p.N.z * z) / p.N.x; }
- double CALC_Y(const carve::geom::plane<3> &p, double x, double z) { return -(p.d + p.N.x * x + p.N.z * z) / p.N.y; }
- double CALC_Z(const carve::geom::plane<3> &p, double x, double y) { return -(p.d + p.N.x * x + p.N.y * y) / p.N.z; }
-
-} // namespace
-
-namespace carve {
- namespace poly {
-
- namespace {
-
- carve::geom2d::P2 _project_1(const carve::geom3d::Vector &v) {
- return carve::geom::VECTOR(v.z, v.y);
- }
-
- carve::geom2d::P2 _project_2(const carve::geom3d::Vector &v) {
- return carve::geom::VECTOR(v.x, v.z);
- }
-
- carve::geom2d::P2 _project_3(const carve::geom3d::Vector &v) {
- return carve::geom::VECTOR(v.y, v.x);
- }
-
- carve::geom2d::P2 _project_4(const carve::geom3d::Vector &v) {
- return carve::geom::VECTOR(v.y, v.z);
- }
-
- carve::geom2d::P2 _project_5(const carve::geom3d::Vector &v) {
- return carve::geom::VECTOR(v.z, v.x);
- }
-
- carve::geom2d::P2 _project_6(const carve::geom3d::Vector &v) {
- return carve::geom::VECTOR(v.x, v.y);
- }
-
-
- carve::geom3d::Vector _unproject_1(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
- return carve::geom::VECTOR(CALC_X(plane_eqn, p.y, p.x), p.y, p.x);
- }
-
- carve::geom3d::Vector _unproject_2(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
- return carve::geom::VECTOR(p.x, CALC_Y(plane_eqn, p.x, p.y), p.y);
- }
-
- carve::geom3d::Vector _unproject_3(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
- return carve::geom::VECTOR(p.y, p.x, CALC_Z(plane_eqn, p.y, p.x));
- }
-
- carve::geom3d::Vector _unproject_4(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
- return carve::geom::VECTOR(CALC_X(plane_eqn, p.x, p.y), p.x, p.y);
- }
-
- carve::geom3d::Vector _unproject_5(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
- return carve::geom::VECTOR(p.y, CALC_Y(plane_eqn, p.y, p.x), p.x);
- }
-
- carve::geom3d::Vector _unproject_6(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
- return carve::geom::VECTOR(p.x, p.y, CALC_Z(plane_eqn, p.x, p.y));
- }
-
- } // namespace
-
- static carve::geom2d::P2 (*project_tab[2][3])(const carve::geom3d::Vector &) = {
- { &_project_1, &_project_2, &_project_3 },
- { &_project_4, &_project_5, &_project_6 }
- };
-
- static carve::geom3d::Vector (*unproject_tab[2][3])(const carve::geom2d::P2 &, const carve::geom3d::Plane &) = {
- { &_unproject_1, &_unproject_2, &_unproject_3 },
- { &_unproject_4, &_unproject_5, &_unproject_6 }
- };
-
- // only implemented for 3d.
- template<unsigned ndim>
- typename Face<ndim>::project_t Face<ndim>::getProjector(bool positive_facing, int axis) {
- return NULL;
- }
-
- template<>
- Face<3>::project_t Face<3>::getProjector(bool positive_facing, int axis) {
- return project_tab[positive_facing ? 1 : 0][axis];
- }
-
- template<unsigned ndim>
- typename Face<ndim>::unproject_t Face<ndim>::getUnprojector(bool positive_facing, int axis) {
- return NULL;
- }
-
- template<>
- Face<3>::unproject_t Face<3>::getUnprojector(bool positive_facing, int axis) {
- return unproject_tab[positive_facing ? 1 : 0][axis];
- }
-
-
-
- template<unsigned ndim>
- Face<ndim>::Face(const std::vector<const vertex_t *> &_vertices,
- bool delay_recalc) : tagable() {
- vertices = _vertices;
- edges.resize(nVertices(), NULL);
- if (!delay_recalc && !recalc()) { }
- }
-
- template<unsigned ndim>
- Face<ndim>::Face(const vertex_t *a,
- const vertex_t *b,
- const vertex_t *c,
- bool delay_recalc) : tagable() {
- vertices.reserve(3);
- vertices.push_back(a);
- vertices.push_back(b);
- vertices.push_back(c);
- edges.resize(3, NULL);
- if (!delay_recalc && !recalc()) { }
- }
-
- template<unsigned ndim>
- Face<ndim>::Face(const vertex_t *a,
- const vertex_t *b,
- const vertex_t *c,
- const vertex_t *d,
- bool delay_recalc) : tagable() {
- vertices.reserve(4);
- vertices.push_back(a);
- vertices.push_back(b);
- vertices.push_back(c);
- vertices.push_back(d);
- edges.resize(4, NULL);
- if (!delay_recalc && !recalc()) { }
- }
-
- template<unsigned ndim>
- void Face<ndim>::invert() {
- size_t n_verts = vertices.size();
- std::reverse(vertices.begin(), vertices.end());
-
- if (project != NULL) {
- plane_eqn.negate();
-
- int da = carve::geom::largestAxis(plane_eqn.N);
-
- project = getProjector(plane_eqn.N.v[da] > 0, da);
- unproject = getUnprojector(plane_eqn.N.v[da] > 0, da);
- }
-
- std::reverse(edges.begin(), edges.end() - 1);
- for (size_t i = 0; i < n_verts; i++) {
- const vertex_t *v1 = vertices[i];
- const vertex_t *v2 = vertices[(i+1) % n_verts];
- CARVE_ASSERT((edges[i]->v1 == v1 && edges[i]->v2 == v2) || (edges[i]->v1 == v2 && edges[i]->v2 == v1));
- }
- }
-
- template<unsigned ndim>
- bool Face<ndim>::recalc() {
- aabb.fit(vertices.begin(), vertices.end(), vec_adapt_vertex_ptr());
-
- if (!carve::geom3d::fitPlane(vertices.begin(), vertices.end(), vec_adapt_vertex_ptr(), plane_eqn)) {
- return false;
- }
-
- int da = carve::geom::largestAxis(plane_eqn.N);
- project = getProjector(false, da);
-
- double A = carve::geom2d::signedArea(vertices, projector());
- if ((A < 0.0) ^ (plane_eqn.N.v[da] < 0.0)) {
- plane_eqn.negate();
- }
-
- project = getProjector(plane_eqn.N.v[da] > 0, da);
- unproject = getUnprojector(plane_eqn.N.v[da] > 0, da);
-
- return true;
- }
-
- template<unsigned ndim>
- Face<ndim> *Face<ndim>::init(const Face *base, const std::vector<const vertex_t *> &_vertices, bool flipped) {
- return init(base, _vertices.begin(), _vertices.end(), flipped);
- }
-
- template<unsigned ndim>
- bool Face<ndim>::containsPoint(const vector_t &p) const {
- if (!carve::math::ZERO(carve::geom::distance(plane_eqn, p))) return false;
- // return pointInPolySimple(vertices, projector(), (this->*project)(p));
- return carve::geom2d::pointInPoly(vertices, projector(), face::project(this, p)).iclass != POINT_OUT;
- }
-
- template<unsigned ndim>
- bool Face<ndim>::containsPointInProjection(const vector_t &p) const {
- return carve::geom2d::pointInPoly(vertices, projector(), face::project(this, p)).iclass != POINT_OUT;
- }
-
- template<unsigned ndim>
- bool Face<ndim>::simpleLineSegmentIntersection(const carve::geom::linesegment<ndim> &line,
- vector_t &intersection) const {
- if (!line.OK()) return false;
-
- carve::geom3d::Vector p;
- IntersectionClass intersects = carve::geom3d::lineSegmentPlaneIntersection(plane_eqn,
- line,
- p);
- if (intersects == INTERSECT_NONE || intersects == INTERSECT_BAD) {
- return false;
- }
-
- carve::geom2d::P2 proj_p(face::project(this, p));
- if (carve::geom2d::pointInPolySimple(vertices, projector(), proj_p)) {
- intersection = p;
- return true;
- }
- return false;
- }
-
- // XXX: should try to return a pre-existing vertex in the case of a
- // line-vertex intersection. as it stands, this code isn't used,
- // so... meh.
- template<unsigned ndim>
- IntersectionClass Face<ndim>::lineSegmentIntersection(const carve::geom::linesegment<ndim> &line,
- vector_t &intersection) const {
- if (!line.OK()) return INTERSECT_NONE;
-
-
- carve::geom3d::Vector p;
- IntersectionClass intersects = carve::geom3d::lineSegmentPlaneIntersection(plane_eqn,
- line,
- p);
- if (intersects == INTERSECT_NONE || intersects == INTERSECT_BAD) {
- return intersects;
- }
-
- carve::geom2d::P2 proj_p(face::project(this, p));
-
- carve::geom2d::PolyInclusionInfo pi = carve::geom2d::pointInPoly(vertices, projector(), proj_p);
- switch (pi.iclass) {
- case POINT_VERTEX:
- intersection = p;
- return INTERSECT_VERTEX;
-
- case POINT_EDGE:
- intersection = p;
- return INTERSECT_EDGE;
-
- case POINT_IN:
- intersection = p;
- return INTERSECT_FACE;
-
- case POINT_OUT:
- return INTERSECT_NONE;
-
- default:
- break;
- }
- return INTERSECT_NONE;
- }
-
-
- }
-}
-
-// explicit instantiations.
-template class carve::poly::Face<3>;
diff --git a/extern/carve/lib/geom2d.cpp b/extern/carve/lib/geom2d.cpp
deleted file mode 100644
index 0e8f3a9377c..00000000000
--- a/extern/carve/lib/geom2d.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/geom2d.hpp>
-#include <carve/math.hpp>
-#include <carve/aabb.hpp>
-
-#include <algorithm>
-#include <iostream>
-
-namespace carve {
- namespace geom2d {
-
- bool lineSegmentIntersection_simple(const P2 &l1v1, const P2 &l1v2,
- const P2 &l2v1, const P2 &l2v2) {
- geom::aabb<2> l1_aabb, l2_aabb;
- l1_aabb.fit(l1v1, l1v2);
- l2_aabb.fit(l2v1, l2v2);
-
- if (l1_aabb.maxAxisSeparation(l2_aabb) > 0.0) {
- return false;
- }
-
- double l1v1_side = orient2d(l2v1, l2v2, l1v1);
- double l1v2_side = orient2d(l2v1, l2v2, l1v2);
-
- double l2v1_side = orient2d(l1v1, l1v2, l2v1);
- double l2v2_side = orient2d(l1v1, l1v2, l2v2);
-
- if (l1v1_side * l1v2_side > 0.0 || l2v1_side * l2v2_side > 0.0) {
- return false;
- }
-
- return true;
- }
-
- bool lineSegmentIntersection_simple(const LineSegment2 &l1,
- const LineSegment2 &l2) {
- return lineSegmentIntersection_simple(l1.v1, l1.v2, l2.v1, l2.v2);
- }
-
- LineIntersectionInfo lineSegmentIntersection(const P2 &l1v1, const P2 &l1v2,
- const P2 &l2v1, const P2 &l2v2) {
- geom::aabb<2> l1_aabb, l2_aabb;
- l1_aabb.fit(l1v1, l1v2);
- l2_aabb.fit(l2v1, l2v2);
-
- if (l1_aabb.maxAxisSeparation(l2_aabb) > EPSILON) {
- return LineIntersectionInfo(NO_INTERSECTION);
- }
-
- if (carve::geom::equal(l1v1, l1v2) || carve::geom::equal(l2v1, l2v2)) {
- throw carve::exception("zero length line in intersection test");
- }
-
- double dx13 = l1v1.x - l2v1.x;
- double dy13 = l1v1.y - l2v1.y;
- double dx43 = l2v2.x - l2v1.x;
- double dy43 = l2v2.y - l2v1.y;
- double dx21 = l1v2.x - l1v1.x;
- double dy21 = l1v2.y - l1v1.y;
- double ua_n = dx43 * dy13 - dy43 * dx13;
- double ub_n = dx21 * dy13 - dy21 * dx13;
- double u_d = dy43 * dx21 - dx43 * dy21;
-
- if (carve::math::ZERO(u_d)) {
- if (carve::math::ZERO(ua_n)) {
- if (carve::geom::equal(l1v2, l2v1)) {
- return LineIntersectionInfo(INTERSECTION_PP, l1v2, 1, 2);
- }
- if (carve::geom::equal(l1v1, l2v2)) {
- return LineIntersectionInfo(INTERSECTION_PP, l1v1, 0, 4);
- }
- if (l1v2.x > l2v1.x && l1v1.x < l2v2.x) {
- return LineIntersectionInfo(COLINEAR);
- }
- }
- return LineIntersectionInfo(NO_INTERSECTION);
- }
-
- double ua = ua_n / u_d;
- double ub = ub_n / u_d;
-
- if (-EPSILON <= ua && ua <= 1.0 + EPSILON && -EPSILON <= ub && ub <= 1.0 + EPSILON) {
- double x = l1v1.x + ua * (l1v2.x - l1v1.x);
- double y = l1v1.y + ua * (l1v2.y - l1v1.y);
-
- P2 p = carve::geom::VECTOR(x, y);
-
- double d1 = distance2(p, l1v1);
- double d2 = distance2(p, l1v2);
- double d3 = distance2(p, l2v1);
- double d4 = distance2(p, l2v2);
-
- int n = -1;
-
- if (std::min(d1, d2) < EPSILON2) {
- if (d1 < d2) {
- p = l1v1; n = 0;
- } else {
- p = l1v2; n = 1;
- }
- if (std::min(d3, d4) < EPSILON2) {
- if (d3 < d4) {
- return LineIntersectionInfo(INTERSECTION_PP, p, n, 2);
- } else {
- return LineIntersectionInfo(INTERSECTION_PP, p, n, 3);
- }
- } else {
- return LineIntersectionInfo(INTERSECTION_PL, p, n, -1);
- }
- } else if (std::min(d3, d4) < EPSILON2) {
- if (d3 < d4) {
- return LineIntersectionInfo(INTERSECTION_LP, l2v1, -1, 2);
- } else {
- return LineIntersectionInfo(INTERSECTION_LP, l2v2, -1, 3);
- }
- } else {
- return LineIntersectionInfo(INTERSECTION_LL, p, -1, -1);
- }
- }
- return LineIntersectionInfo(NO_INTERSECTION);
- }
-
- LineIntersectionInfo lineSegmentIntersection(const LineSegment2 &l1,
- const LineSegment2 &l2) {
- return lineSegmentIntersection(l1.v1, l1.v2, l2.v1, l2.v2);
- }
-
- double signedArea(const P2Vector &points) {
- return signedArea(points, p2_adapt_ident());
- }
-
- bool pointInPolySimple(const P2Vector &points, const P2 &p) {
- return pointInPolySimple(points, p2_adapt_ident(), p);
- }
-
- PolyInclusionInfo pointInPoly(const P2Vector &points, const P2 &p) {
- return pointInPoly(points, p2_adapt_ident(), p);
- }
-
-#if 0
- static int lineSegmentPolyIntersections(const P2Vector &points,
- LineSegment2 line,
- std::vector<PolyIntersectionInfo> &out) {
- int count = 0;
-
- if (line.v2 < line.v1) { line.flip(); }
- out.clear();
-
- for (P2Vector::size_type i = 0, l = points.size(); i < l; i++) {
- P2Vector::size_type j = (i + 1) % l;
- LineIntersectionInfo e =
- lineSegmentIntersection(LineSegment2(points[i], points[j]), line);
-
- switch (e.iclass) {
- case INTERSECTION_PL: {
- out.push_back(PolyIntersectionInfo(INTERSECT_EDGE, e.ipoint, i));
- count++;
- break;
- }
- case INTERSECTION_PP: {
- out.push_back(PolyIntersectionInfo(INTERSECT_VERTEX, e.ipoint, i + (size_t)e.p2 - 2));
- count++;
- break;
- }
- case INTERSECTION_LP: {
- out.push_back(PolyIntersectionInfo(INTERSECT_VERTEX, e.ipoint, i + (size_t)e.p2 - 2));
- count++;
- break;
- }
- case INTERSECTION_LL: {
- out.push_back(PolyIntersectionInfo(INTERSECT_EDGE, e.ipoint, i));
- count++;
- break;
- }
- case COLINEAR: {
- size_t n1 = i;
- size_t n2 = j;
-
- P2 q1 = points[i], q2 = points[j];
-
- if (q2 < q1) { std::swap(q1, q2); std::swap(n1, n2); }
-
- if (equal(q1, line.v1)) {
- out.push_back(PolyIntersectionInfo(INTERSECT_VERTEX, q1, n1));
- } else if (q1.x < line.v1.x) {
- out.push_back(PolyIntersectionInfo(INTERSECT_EDGE, line.v1, i));
- } else {
- out.push_back(PolyIntersectionInfo(INTERSECT_VERTEX, q1, n1));
- }
- if (equal(q2, line.v2)) {
- out.push_back(PolyIntersectionInfo(INTERSECT_VERTEX, q2, n2));
- } else if (line.v2.x < q2.x) {
- out.push_back(PolyIntersectionInfo(INTERSECT_EDGE, line.v2, i));
- } else {
- out.push_back(PolyIntersectionInfo(INTERSECT_VERTEX, q2, n2));
- }
-
- count += 2;
-
- break;
- }
- default:
- break;
- }
- }
- return count;
- }
-#endif
-
- struct FwdSort {
- bool operator()(const PolyIntersectionInfo &a,
- const PolyIntersectionInfo &b) const {
- return a.ipoint < b.ipoint;
- }
- };
-
- struct RevSort {
- bool operator()(const PolyIntersectionInfo &a,
- const PolyIntersectionInfo &b) const {
- return a.ipoint < b.ipoint;
- }
- };
-
-#if 0
- static int sortedLineSegmentPolyIntersections(const P2Vector &points,
- LineSegment2 line,
- std::vector<PolyIntersectionInfo> &out) {
-
- bool swapped = line.v2 < line.v1;
-
- int count = lineSegmentPolyIntersections(points, line, out);
- if (swapped) {
- std::sort(out.begin(), out.end(), RevSort());
- } else {
- std::sort(out.begin(), out.end(), FwdSort());
- }
- return count;
- }
-#endif
-
- bool pickContainedPoint(const std::vector<P2> &poly, P2 &result) {
- return pickContainedPoint(poly, p2_adapt_ident(), result);
- }
-
- }
-}
diff --git a/extern/carve/lib/geom3d.cpp b/extern/carve/lib/geom3d.cpp
deleted file mode 100644
index 94085034f10..00000000000
--- a/extern/carve/lib/geom3d.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/math.hpp>
-#include <carve/geom3d.hpp>
-
-#include <algorithm>
-
-namespace carve {
- namespace geom3d {
-
- namespace {
-#if 0
- int is_same(const std::vector<const Vector *> &a,
- const std::vector<const Vector *> &b) {
- if (a.size() != b.size()) return false;
-
- const size_t S = a.size();
- size_t i, j, p;
-
- for (p = 0; p < S; ++p) {
- if (a[0] == b[p]) break;
- }
- if (p == S) return 0;
-
- for (i = 1, j = p + 1; j < S; ++i, ++j) if (a[i] != b[j]) goto not_fwd;
- for ( j = 0; i < S; ++i, ++j) if (a[i] != b[j]) goto not_fwd;
- return +1;
-
-not_fwd:
- for (i = 1, j = p - 1; j != (size_t)-1; ++i, --j) if (a[i] != b[j]) goto not_rev;
- for ( j = S - 1; i < S; ++i, --j) if (a[i] != b[j]) goto not_rev;
- return -1;
-
-not_rev:
- return 0;
- }
-#endif
- }
-
- bool planeIntersection(const Plane &a, const Plane &b, Ray &r) {
- Vector N = cross(a.N, b.N);
- if (N.isZero()) {
- return false;
- }
- N.normalize();
-
- double dot_aa = dot(a.N, a.N);
- double dot_bb = dot(b.N, b.N);
- double dot_ab = dot(a.N, b.N);
-
- double determinant = dot_aa * dot_bb - dot_ab * dot_ab;
-
- double c1 = ( a.d * dot_bb - b.d * dot_ab) / determinant;
- double c2 = ( b.d * dot_aa - a.d * dot_ab) / determinant;
-
- r.D = N;
- r.v = c1 * a.N + c2 * b.N;
-
- return true;
- }
-
- IntersectionClass rayPlaneIntersection(const Plane &p,
- const Vector &v1,
- const Vector &v2,
- Vector &v,
- double &t) {
- Vector Rd = v2 - v1;
- double Vd = dot(p.N, Rd);
- double V0 = dot(p.N, v1) + p.d;
-
- if (carve::math::ZERO(Vd)) {
- if (carve::math::ZERO(V0)) {
- return INTERSECT_BAD;
- } else {
- return INTERSECT_NONE;
- }
- }
-
- t = -V0 / Vd;
- v = v1 + t * Rd;
- return INTERSECT_PLANE;
- }
-
- IntersectionClass lineSegmentPlaneIntersection(const Plane &p,
- const LineSegment &line,
- Vector &v) {
- double t;
- IntersectionClass r = rayPlaneIntersection(p, line.v1, line.v2, v, t);
-
- if (r <= 0) return r;
-
- if ((t < 0.0 && !equal(v, line.v1)) || (t > 1.0 && !equal(v, line.v2)))
- return INTERSECT_NONE;
-
- return INTERSECT_PLANE;
- }
-
- RayIntersectionClass rayRayIntersection(const Ray &r1,
- const Ray &r2,
- Vector &v1,
- Vector &v2,
- double &mu1,
- double &mu2) {
- if (!r1.OK() || !r2.OK()) return RR_DEGENERATE;
-
- Vector v_13 = r1.v - r2.v;
-
- double d1343 = dot(v_13, r2.D);
- double d4321 = dot(r2.D, r1.D);
- double d1321 = dot(v_13, r1.D);
- double d4343 = dot(r2.D, r2.D);
- double d2121 = dot(r1.D, r1.D);
-
- double numer = d1343 * d4321 - d1321 * d4343;
- double denom = d2121 * d4343 - d4321 * d4321;
-
- // dc - eb
- // -------
- // ab - cc
-
- // dc/eb - 1
- // ---------
- // a/e - cc/eb
-
- // dc/b - e
- // --------
- // a - cc/b
-
- // d/b - e/c
- // ---------
- // a/c - c/b
-
- if (fabs(denom) * double(1<<10) <= fabs(numer)) {
- return RR_PARALLEL;
- }
-
- mu1 = numer / denom;
- mu2 = (d1343 + d4321 * mu1) / d4343;
-
- v1 = r1.v + mu1 * r1.D;
- v2 = r2.v + mu2 * r2.D;
-
- return (equal(v1, v2)) ? RR_INTERSECTION : RR_NO_INTERSECTION;
- }
-
- }
-}
diff --git a/extern/carve/lib/intersect.cpp b/extern/carve/lib/intersect.cpp
deleted file mode 100644
index d780e08d224..00000000000
--- a/extern/carve/lib/intersect.cpp
+++ /dev/null
@@ -1,1735 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/csg.hpp>
-#include <carve/pointset.hpp>
-#include <carve/polyline.hpp>
-
-#include <list>
-#include <set>
-#include <iostream>
-
-#include <algorithm>
-
-#include "csg_detail.hpp"
-#include "csg_data.hpp"
-
-#include "intersect_debug.hpp"
-#include "intersect_common.hpp"
-#include "intersect_classify_common.hpp"
-
-#include "csg_collector.hpp"
-
-#include <carve/timing.hpp>
-#include <carve/colour.hpp>
-
-#include <memory>
-
-
-
-carve::csg::VertexPool::VertexPool() {
-}
-
-carve::csg::VertexPool::~VertexPool() {
-}
-
-void carve::csg::VertexPool::reset() {
- pool.clear();
-}
-
-carve::csg::VertexPool::vertex_t *carve::csg::VertexPool::get(const vertex_t::vector_t &v) {
- if (!pool.size() || pool.back().size() == blocksize) {
- pool.push_back(std::vector<vertex_t>());
- pool.back().reserve(blocksize);
- }
- pool.back().push_back(vertex_t(v));
- return &pool.back().back();
-}
-
-bool carve::csg::VertexPool::inPool(vertex_t *v) const {
- for (pool_t::const_iterator i = pool.begin(); i != pool.end(); ++i) {
- if (v >= &(i->front()) && v <= &(i->back())) return true;
- }
- return false;
-}
-
-
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
-void writePLY(const std::string &out_file, const carve::point::PointSet *points, bool ascii);
-void writePLY(const std::string &out_file, const carve::line::PolylineSet *lines, bool ascii);
-void writePLY(const std::string &out_file, const carve::mesh::MeshSet<3> *poly, bool ascii);
-
-static carve::mesh::MeshSet<3> *faceLoopsToPolyhedron(const carve::csg::FaceLoopList &fl) {
- std::vector<carve::mesh::MeshSet<3>::face_t *> faces;
- faces.reserve(fl.size());
- for (carve::csg::FaceLoop *f = fl.head; f; f = f->next) {
- faces.push_back(f->orig_face->create(f->vertices.begin(), f->vertices.end(), false));
- }
- carve::mesh::MeshSet<3> *poly = new carve::mesh::MeshSet<3>(faces);
-
- return poly;
-}
-#endif
-
-namespace {
- /**
- * \brief Sort a range [\a beg, \a end) of vertices in order of increasing dot product of vertex - \a base on \dir.
- *
- * @tparam[in] T a forward iterator type.
- * @param[in] dir The direction in which to sort vertices.
- * @param[in] base
- * @param[in] beg The start of the vertex range to sort.
- * @param[in] end The end of the vertex range to sort.
- * @param[out] out The sorted vertex result.
- * @param[in] size_hint A hint regarding the size of the output
- * vector (to avoid needing to be able to calculate \a
- * end - \a beg).
- */
- template<typename iter_t>
- void orderVertices(iter_t beg, const iter_t end,
- const carve::mesh::MeshSet<3>::vertex_t::vector_t &dir,
- const carve::mesh::MeshSet<3>::vertex_t::vector_t &base,
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &out) {
- typedef std::vector<std::pair<double, carve::mesh::MeshSet<3>::vertex_t *> > DVVector;
- std::vector<std::pair<double, carve::mesh::MeshSet<3>::vertex_t *> > ordered_vertices;
-
- ordered_vertices.reserve(std::distance(beg, end));
-
- for (; beg != end; ++beg) {
- carve::mesh::MeshSet<3>::vertex_t *v = *beg;
- ordered_vertices.push_back(std::make_pair(carve::geom::dot(v->v - base, dir), v));
- }
-
- std::sort(ordered_vertices.begin(), ordered_vertices.end());
-
- out.clear();
- out.reserve(ordered_vertices.size());
- for (DVVector::const_iterator
- i = ordered_vertices.begin(), e = ordered_vertices.end();
- i != e;
- ++i) {
- out.push_back((*i).second);
- }
- }
-
- template<typename iter_t>
- void orderEdgeIntersectionVertices(iter_t beg, const iter_t end,
- const carve::mesh::MeshSet<3>::vertex_t::vector_t &dir,
- const carve::mesh::MeshSet<3>::vertex_t::vector_t &base,
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &out) {
- typedef std::vector<std::pair<std::pair<double, double>, carve::mesh::MeshSet<3>::vertex_t *> > DVVector;
- DVVector ordered_vertices;
-
- ordered_vertices.reserve(std::distance(beg, end));
-
- for (; beg != end; ++beg) {
- carve::mesh::MeshSet<3>::vertex_t *v = (*beg).first;
- double ovec = 0.0;
- for (carve::csg::detail::EdgeIntInfo::mapped_type::const_iterator j = (*beg).second.begin(); j != (*beg).second.end(); ++j) {
- ovec += (*j).second;
- }
- ordered_vertices.push_back(std::make_pair(std::make_pair(carve::geom::dot(v->v - base, dir), -ovec), v));
- }
-
- std::sort(ordered_vertices.begin(), ordered_vertices.end());
-
- out.clear();
- out.reserve(ordered_vertices.size());
- for (DVVector::const_iterator
- i = ordered_vertices.begin(), e = ordered_vertices.end();
- i != e;
- ++i) {
- out.push_back((*i).second);
- }
- }
-
-
-
- /**
- *
- *
- * @param dir
- * @param base
- * @param beg
- * @param end
- */
- template<typename iter_t>
- void selectOrderingProjection(iter_t beg, const iter_t end,
- carve::mesh::MeshSet<3>::vertex_t::vector_t &dir,
- carve::mesh::MeshSet<3>::vertex_t::vector_t &base) {
- double dx, dy, dz;
- carve::mesh::MeshSet<3>::vertex_t *min_x, *min_y, *min_z, *max_x, *max_y, *max_z;
- if (beg == end) return;
- min_x = max_x = min_y = max_y = min_z = max_z = *beg++;
- for (; beg != end; ++beg) {
- if (min_x->v.x > (*beg)->v.x) min_x = *beg;
- if (min_y->v.y > (*beg)->v.y) min_y = *beg;
- if (min_z->v.z > (*beg)->v.z) min_z = *beg;
- if (max_x->v.x < (*beg)->v.x) max_x = *beg;
- if (max_y->v.y < (*beg)->v.y) max_y = *beg;
- if (max_z->v.z < (*beg)->v.z) max_z = *beg;
- }
-
- dx = max_x->v.x - min_x->v.x;
- dy = max_y->v.y - min_y->v.y;
- dz = max_z->v.z - min_z->v.z;
-
- if (dx > dy) {
- if (dx > dz) {
- dir = max_x->v - min_x->v; base = min_x->v;
- } else {
- dir = max_z->v - min_z->v; base = min_z->v;
- }
- } else {
- if (dy > dz) {
- dir = max_y->v - min_y->v; base = min_y->v;
- } else {
- dir = max_z->v - min_z->v; base = min_z->v;
- }
- }
- }
-}
-
-namespace {
- struct dump_data {
- carve::mesh::MeshSet<3>::vertex_t *i_pt;
- carve::csg::IObj i_src;
- carve::csg::IObj i_tgt;
- dump_data(carve::mesh::MeshSet<3>::vertex_t *_i_pt,
- carve::csg::IObj _i_src,
- carve::csg::IObj _i_tgt) : i_pt(_i_pt), i_src(_i_src), i_tgt(_i_tgt) {
- }
- };
-
-
-
- struct dump_sort {
- bool operator()(const dump_data &a, const dump_data &b) const {
- if (a.i_pt->v.x < b.i_pt->v.x) return true;
- if (a.i_pt->v.x > b.i_pt->v.x) return false;
- if (a.i_pt->v.y < b.i_pt->v.y) return true;
- if (a.i_pt->v.y > b.i_pt->v.y) return false;
- if (a.i_pt->v.z < b.i_pt->v.z) return true;
- if (a.i_pt->v.z > b.i_pt->v.z) return false;
- return false;
- }
- };
-
-
-
-#if 0
- void dump_intersections(std::ostream &out, carve::csg::Intersections &csg_intersections) {
- std::vector<dump_data> temp;
-
- for (carve::csg::Intersections::const_iterator
- i = csg_intersections.begin(),
- ie = csg_intersections.end();
- i != ie;
- ++i) {
- const carve::csg::IObj &i_src = ((*i).first);
-
- for (carve::csg::Intersections::mapped_type::const_iterator
- j = (*i).second.begin(),
- je = (*i).second.end();
- j != je;
- ++j) {
- const carve::csg::IObj &i_tgt = ((*j).first);
- carve::mesh::MeshSet<3>::vertex_t *i_pt = ((*j).second);
- temp.push_back(dump_data(i_pt, i_src, i_tgt));
- }
- }
-
- std::sort(temp.begin(), temp.end(), dump_sort());
-
- for (size_t i = 0; i < temp.size(); ++i) {
- const carve::csg::IObj &i_src = temp[i].i_src;
- const carve::csg::IObj &i_tgt = temp[i].i_tgt;
- out
- << "INTERSECTION: " << temp[i].i_pt << " (" << temp[i].i_pt->v << ") "
- << "is " << i_src << ".." << i_tgt << std::endl;
- }
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- std::vector<carve::geom3d::Vector> vertices;
-
- for (carve::csg::Intersections::const_iterator
- i = csg_intersections.begin(),
- ie = csg_intersections.end();
- i != ie;
- ++i) {
- for (carve::csg::Intersections::mapped_type::const_iterator
- j = (*i).second.begin(),
- je = (*i).second.end();
- j != je;
- ++j) {
- carve::mesh::MeshSet<3>::vertex_t *i_pt = ((*j).second);
- vertices.push_back(i_pt->v);
- }
- }
-#endif
-
- carve::point::PointSet points(vertices);
-
- std::string outf("/tmp/intersection-points.ply");
- ::writePLY(outf, &points, true);
- }
-#endif
-
-
-
- /**
- * \brief Populate a collection with the faces adjoining an edge.
- *
- * @tparam face_set_t A collection type.
- * @param e The edge for which to collect adjoining faces.
- * @param faces
- */
- template<typename face_set_t>
- inline void facesForVertex(carve::mesh::MeshSet<3>::vertex_t *v,
- const carve::csg::detail::VEVecMap &ve,
- face_set_t &faces) {
- carve::csg::detail::VEVecMap::const_iterator vi = ve.find(v);
- if (vi != ve.end()) {
- for (carve::csg::detail::VEVecMap::data_type::const_iterator i = (*vi).second.begin(); i != (*vi).second.end(); ++i) {
- faces.insert((*i)->face);
- }
- }
- }
-
- /**
- * \brief Populate a collection with the faces adjoining an edge.
- *
- * @tparam face_set_t A collection type.
- * @param e The edge for which to collect adjoining faces.
- * @param faces
- */
- template<typename face_set_t>
- inline void facesForEdge(carve::mesh::MeshSet<3>::edge_t *e,
- face_set_t &faces) {
- faces.insert(e->face);
- }
-
- /**
- * \brief Populate a collection with the faces adjoining a face.
- *
- * @tparam face_set_t A collection type.
- * @param f The face for which to collect adjoining faces.
- * @param faces
- */
- template<typename face_set_t>
- inline void facesForFace(carve::mesh::MeshSet<3>::face_t *f,
- face_set_t &faces) {
- faces.insert(f);
- }
-
- /**
- * \brief Populate a collection with the faces adjoining an intersection object.
- *
- * @tparam face_set_t A collection type holding const carve::poly::Polyhedron::face_t *.
- * @param obj The intersection object for which to collect adjoining faces.
- * @param faces
- */
- template<typename face_set_t>
- void facesForObject(const carve::csg::IObj &obj,
- const carve::csg::detail::VEVecMap &ve,
- face_set_t &faces) {
- switch (obj.obtype) {
- case carve::csg::IObj::OBTYPE_VERTEX:
- facesForVertex(obj.vertex, ve, faces);
- break;
-
- case carve::csg::IObj::OBTYPE_EDGE:
- facesForEdge(obj.edge, faces);
- break;
-
- case carve::csg::IObj::OBTYPE_FACE:
- facesForFace(obj.face, faces);
- break;
-
- default:
- break;
- }
- }
-
-
-
-}
-
-
-
-bool carve::csg::CSG::Hooks::hasHook(unsigned hook_num) {
- return hooks[hook_num].size() > 0;
-}
-
-void carve::csg::CSG::Hooks::intersectionVertex(const meshset_t::vertex_t *vertex,
- const IObjPairSet &intersections) {
- for (std::list<Hook *>::iterator j = hooks[INTERSECTION_VERTEX_HOOK].begin();
- j != hooks[INTERSECTION_VERTEX_HOOK].end();
- ++j) {
- (*j)->intersectionVertex(vertex, intersections);
- }
-}
-
-void carve::csg::CSG::Hooks::processOutputFace(std::vector<meshset_t::face_t *> &faces,
- const meshset_t::face_t *orig_face,
- bool flipped) {
- for (std::list<Hook *>::iterator j = hooks[PROCESS_OUTPUT_FACE_HOOK].begin();
- j != hooks[PROCESS_OUTPUT_FACE_HOOK].end();
- ++j) {
- (*j)->processOutputFace(faces, orig_face, flipped);
- }
-}
-
-void carve::csg::CSG::Hooks::resultFace(const meshset_t::face_t *new_face,
- const meshset_t::face_t *orig_face,
- bool flipped) {
- for (std::list<Hook *>::iterator j = hooks[RESULT_FACE_HOOK].begin();
- j != hooks[RESULT_FACE_HOOK].end();
- ++j) {
- (*j)->resultFace(new_face, orig_face, flipped);
- }
-}
-
-void carve::csg::CSG::Hooks::edgeDivision(const meshset_t::edge_t *orig_edge,
- size_t orig_edge_idx,
- const meshset_t::vertex_t *v1,
- const meshset_t::vertex_t *v2) {
- for (std::list<Hook *>::iterator j = hooks[EDGE_DIVISION_HOOK].begin();
- j != hooks[EDGE_DIVISION_HOOK].end();
- ++j) {
- (*j)->edgeDivision(orig_edge, orig_edge_idx, v1, v2);
- }
-}
-
-void carve::csg::CSG::Hooks::registerHook(Hook *hook, unsigned hook_bits) {
- for (unsigned i = 0; i < HOOK_MAX; ++i) {
- if (hook_bits & (1U << i)) {
- hooks[i].push_back(hook);
- }
- }
-}
-
-void carve::csg::CSG::Hooks::unregisterHook(Hook *hook) {
- for (unsigned i = 0; i < HOOK_MAX; ++i) {
- hooks[i].erase(std::remove(hooks[i].begin(), hooks[i].end(), hook), hooks[i].end());
- }
-}
-
-void carve::csg::CSG::Hooks::reset() {
- std::set<Hook *> to_delete;
- for (unsigned i = 0; i < HOOK_MAX; ++i) {
- for (std::list<Hook *>::iterator j = hooks[i].begin(); j != hooks[i].end(); ++j) {
- to_delete.insert(*j);
- }
- hooks[i].clear();
- }
- for (std::set<Hook *>::iterator i = to_delete.begin(); i != to_delete.end(); ++i) {
- delete *i;
- }
-}
-
-carve::csg::CSG::Hooks::Hooks() : hooks() {
- hooks.resize(HOOK_MAX);
-}
-
-carve::csg::CSG::Hooks::~Hooks() {
- reset();
-}
-
-
-
-void carve::csg::CSG::makeVertexIntersections() {
- static carve::TimingName FUNC_NAME("CSG::makeVertexIntersections()");
- carve::TimingBlock block(FUNC_NAME);
- vertex_intersections.clear();
- for (Intersections::const_iterator
- i = intersections.begin(),
- ie = intersections.end();
- i != ie;
- ++i) {
- const IObj &i_src = ((*i).first);
-
- for (Intersections::mapped_type::const_iterator
- j = (*i).second.begin(),
- je = (*i).second.end();
- j != je;
- ++j) {
- const IObj &i_tgt = ((*j).first);
- meshset_t::vertex_t *i_pt = ((*j).second);
-
- vertex_intersections[i_pt].insert(std::make_pair(i_src, i_tgt));
- }
- }
-}
-
-
-
-#if 0
-static carve::mesh::MeshSet<3>::vertex_t *chooseWeldPoint(
- const carve::csg::detail::VSet &equivalent,
- carve::csg::VertexPool &vertex_pool) {
- // XXX: choose a better weld point.
- if (!equivalent.size()) return NULL;
-
- for (carve::csg::detail::VSet::const_iterator
- i = equivalent.begin(), e = equivalent.end();
- i != e;
- ++i) {
- if (!vertex_pool.inPool((*i))) return (*i);
- }
- return *equivalent.begin();
-}
-
-
-
-static const carve::mesh::MeshSet<3>::vertex_t *weld(
- const carve::csg::detail::VSet &equivalent,
- carve::csg::VertexIntersections &vertex_intersections,
- carve::csg::VertexPool &vertex_pool) {
- carve::mesh::MeshSet<3>::vertex_t *weld_point = chooseWeldPoint(equivalent, vertex_pool);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "weld: " << equivalent.size() << " vertices ( ";
- for (carve::csg::detail::VSet::const_iterator
- i = equivalent.begin(), e = equivalent.end();
- i != e;
- ++i) {
- const carve::mesh::MeshSet<3>::vertex_t *v = (*i);
- std::cerr << " " << v;
- }
- std::cerr << ") to " << weld_point << std::endl;
-#endif
-
- if (!weld_point) return NULL;
-
- carve::csg::VertexIntersections::mapped_type &weld_tgt = (vertex_intersections[weld_point]);
-
- for (carve::csg::detail::VSet::const_iterator
- i = equivalent.begin(), e = equivalent.end();
- i != e;
- ++i) {
- carve::mesh::MeshSet<3>::vertex_t *v = (*i);
-
- if (v != weld_point) {
- carve::csg::VertexIntersections::iterator j = vertex_intersections.find(v);
-
- if (j != vertex_intersections.end()) {
- weld_tgt.insert((*j).second.begin(), (*j).second.end());
- vertex_intersections.erase(j);
- }
- }
- }
- return weld_point;
-}
-#endif
-
-
-void carve::csg::CSG::groupIntersections() {
-#if 0 // old code, to be removed.
- static carve::TimingName GROUP_INTERSECTONS("groupIntersections()");
-
- carve::TimingBlock block(GROUP_INTERSECTONS);
-
- std::vector<meshset_t::vertex_t *> vertices;
- detail::VVSMap graph;
-#if defined(CARVE_DEBUG)
- std::cerr << "groupIntersections()" << ": vertex_intersections.size()==" << vertex_intersections.size() << std::endl;
-#endif
-
- vertices.reserve(vertex_intersections.size());
- for (carve::csg::VertexIntersections::const_iterator
- i = vertex_intersections.begin(),
- e = vertex_intersections.end();
- i != e;
- ++i)
- {
- vertices.push_back((*i).first);
- }
- carve::geom3d::AABB aabb;
- aabb.fit(vertices.begin(), vertices.end(), carve::poly::vec_adapt_vertex_ptr());
- Octree vertex_intersections_octree;
- vertex_intersections_octree.setBounds(aabb);
-
- vertex_intersections_octree.addVertices(vertices);
-
- std::vector<meshset_t::vertex_t *> out;
- for (size_t i = 0, l = vertices.size(); i != l; ++i) {
- // let's find all the vertices near this one.
- out.clear();
- vertex_intersections_octree.findVerticesNearAllowDupes(vertices[i]->v, out);
-
- for (size_t j = 0; j < out.size(); ++j) {
- if (vertices[i] != out[j] && carve::geom::equal(vertices[i]->v, out[j]->v)) {
-#if defined(CARVE_DEBUG)
- std::cerr << "EQ: " << vertices[i] << "," << out[j] << " " << vertices[i]->v << "," << out[j]->v << std::endl;
-#endif
- graph[vertices[i]].insert(out[j]);
- graph[out[j]].insert(vertices[i]);
- }
- }
- }
-
- detail::VSet visited, open;
- while (graph.size()) {
- visited.clear();
- open.clear();
- detail::VVSMap::iterator i = graph.begin();
- open.insert((*i).first);
- while (open.size()) {
- detail::VSet::iterator t = open.begin();
- const meshset_t::vertex_t *o = (*t);
- open.erase(t);
- i = graph.find(o);
- CARVE_ASSERT(i != graph.end());
- visited.insert(o);
- for (detail::VVSMap::mapped_type::const_iterator
- j = (*i).second.begin(),
- je = (*i).second.end();
- j != je;
- ++j) {
- if (visited.count((*j)) == 0) {
- open.insert((*j));
- }
- }
- graph.erase(i);
- }
- weld(visited, vertex_intersections, vertex_pool);
- }
-#endif
-}
-
-
-static void recordEdgeIntersectionInfo(carve::mesh::MeshSet<3>::vertex_t *intersection,
- carve::mesh::MeshSet<3>::edge_t *edge,
- const carve::csg::detail::VFSMap::mapped_type &intersected_faces,
- carve::csg::detail::Data &data) {
- carve::mesh::MeshSet<3>::vertex_t::vector_t edge_dir = edge->v2()->v - edge->v1()->v;
- carve::csg::detail::EdgeIntInfo::mapped_type &eint_info = data.emap[edge][intersection];
-
- for (carve::csg::detail::VFSMap::mapped_type::const_iterator i = intersected_faces.begin(); i != intersected_faces.end(); ++i) {
- carve::mesh::MeshSet<3>::vertex_t::vector_t normal = (*i)->plane.N;
- eint_info.insert(std::make_pair((*i), carve::geom::dot(edge_dir, normal)));
- }
-}
-
-
-void carve::csg::CSG::intersectingFacePairs(detail::Data &data) {
- static carve::TimingName FUNC_NAME("CSG::intersectingFacePairs()");
- carve::TimingBlock block(FUNC_NAME);
-
- // iterate over all intersection points.
- for (VertexIntersections::const_iterator i = vertex_intersections.begin(), ie = vertex_intersections.end(); i != ie; ++i) {
- meshset_t::vertex_t *i_pt = ((*i).first);
- detail::VFSMap::mapped_type &face_set = (data.fmap_rev[i_pt]);
- detail::VFSMap::mapped_type src_face_set;
- detail::VFSMap::mapped_type tgt_face_set;
- // for all pairs of intersecting objects at this point
- for (VertexIntersections::data_type::const_iterator j = (*i).second.begin(), je = (*i).second.end(); j != je; ++j) {
- const IObj &i_src = ((*j).first);
- const IObj &i_tgt = ((*j).second);
-
- src_face_set.clear();
- tgt_face_set.clear();
- // work out the faces involved.
- facesForObject(i_src, data.vert_to_edges, src_face_set);
- facesForObject(i_tgt, data.vert_to_edges, tgt_face_set);
- // this updates fmap_rev.
- std::copy(src_face_set.begin(), src_face_set.end(), set_inserter(face_set));
- std::copy(tgt_face_set.begin(), tgt_face_set.end(), set_inserter(face_set));
-
- // record the intersection with respect to any involved vertex.
- if (i_src.obtype == IObj::OBTYPE_VERTEX) data.vmap[i_src.vertex] = i_pt;
- if (i_tgt.obtype == IObj::OBTYPE_VERTEX) data.vmap[i_tgt.vertex] = i_pt;
-
- // record the intersection with respect to any involved edge.
- if (i_src.obtype == IObj::OBTYPE_EDGE) recordEdgeIntersectionInfo(i_pt, i_src.edge, tgt_face_set, data);
- if (i_tgt.obtype == IObj::OBTYPE_EDGE) recordEdgeIntersectionInfo(i_pt, i_tgt.edge, src_face_set, data);
- }
-
- // record the intersection with respect to each face.
- for (carve::csg::detail::VFSMap::mapped_type::const_iterator k = face_set.begin(), ke = face_set.end(); k != ke; ++k) {
- meshset_t::face_t *f = (*k);
- data.fmap[f].insert(i_pt);
- }
- }
-}
-
-
-
-void carve::csg::CSG::_generateVertexVertexIntersections(meshset_t::vertex_t *va,
- meshset_t::edge_t *eb) {
- if (intersections.intersects(va, eb->v1())) {
- return;
- }
-
- double d_v1 = carve::geom::distance2(va->v, eb->v1()->v);
-
- if (d_v1 < carve::EPSILON2) {
- intersections.record(va, eb->v1(), va);
- }
-}
-
-
-
-void carve::csg::CSG::generateVertexVertexIntersections(meshset_t::face_t *a,
- const std::vector<meshset_t::face_t *> &b) {
- meshset_t::edge_t *ea, *eb;
-
- ea = a->edge;
- do {
- for (size_t i = 0; i < b.size(); ++i) {
- meshset_t::face_t *t = b[i];
- eb = t->edge;
- do {
- _generateVertexVertexIntersections(ea->v1(), eb);
- eb = eb->next;
- } while (eb != t->edge);
- }
- ea = ea->next;
- } while (ea != a->edge);
-}
-
-
-
-void carve::csg::CSG::_generateVertexEdgeIntersections(meshset_t::vertex_t *va,
- meshset_t::edge_t *eb) {
- if (intersections.intersects(va, eb)) {
- return;
- }
-
- carve::geom::aabb<3> eb_aabb;
- eb_aabb.fit(eb->v1()->v, eb->v2()->v);
- if (eb_aabb.maxAxisSeparation(va->v) > carve::EPSILON) {
- return;
- }
-
- double a = cross(eb->v2()->v - eb->v1()->v, va->v - eb->v1()->v).length2();
- double b = (eb->v2()->v - eb->v1()->v).length2();
-
- if (a < b * carve::EPSILON2) {
- // vertex-edge intersection
- intersections.record(eb, va, va);
- if (eb->rev) intersections.record(eb->rev, va, va);
- }
-}
-
-
-
-void carve::csg::CSG::generateVertexEdgeIntersections(meshset_t::face_t *a,
- const std::vector<meshset_t::face_t *> &b) {
- meshset_t::edge_t *ea, *eb;
-
- ea = a->edge;
- do {
- for (size_t i = 0; i < b.size(); ++i) {
- meshset_t::face_t *t = b[i];
- eb = t->edge;
- do {
- _generateVertexEdgeIntersections(ea->v1(), eb);
- eb = eb->next;
- } while (eb != t->edge);
- }
- ea = ea->next;
- } while (ea != a->edge);
-}
-
-
-
-void carve::csg::CSG::_generateEdgeEdgeIntersections(meshset_t::edge_t *ea,
- meshset_t::edge_t *eb) {
- if (intersections.intersects(ea, eb)) {
- return;
- }
-
- meshset_t::vertex_t *v1 = ea->v1(), *v2 = ea->v2();
- meshset_t::vertex_t *v3 = eb->v1(), *v4 = eb->v2();
-
- carve::geom::aabb<3> ea_aabb, eb_aabb;
- ea_aabb.fit(v1->v, v2->v);
- eb_aabb.fit(v3->v, v4->v);
- if (ea_aabb.maxAxisSeparation(eb_aabb) > EPSILON) return;
-
- meshset_t::vertex_t::vector_t p1, p2;
- double mu1, mu2;
-
- switch (carve::geom3d::rayRayIntersection(carve::geom3d::Ray(v2->v - v1->v, v1->v),
- carve::geom3d::Ray(v4->v - v3->v, v3->v),
- p1, p2, mu1, mu2)) {
- case carve::RR_INTERSECTION: {
- // edges intersect
- if (mu1 >= 0.0 && mu1 <= 1.0 && mu2 >= 0.0 && mu2 <= 1.0) {
- meshset_t::vertex_t *p = vertex_pool.get((p1 + p2) / 2.0);
- intersections.record(ea, eb, p);
- if (ea->rev) intersections.record(ea->rev, eb, p);
- if (eb->rev) intersections.record(ea, eb->rev, p);
- if (ea->rev && eb->rev) intersections.record(ea->rev, eb->rev, p);
- }
- break;
- }
- case carve::RR_PARALLEL: {
- // edges parallel. any intersection of this type should have
- // been handled by generateVertexEdgeIntersections().
- break;
- }
- case carve::RR_DEGENERATE: {
- throw carve::exception("degenerate edge");
- break;
- }
- case carve::RR_NO_INTERSECTION: {
- break;
- }
- }
-}
-
-
-
-void carve::csg::CSG::generateEdgeEdgeIntersections(meshset_t::face_t *a,
- const std::vector<meshset_t::face_t *> &b) {
- meshset_t::edge_t *ea, *eb;
-
- ea = a->edge;
- do {
- for (size_t i = 0; i < b.size(); ++i) {
- meshset_t::face_t *t = b[i];
- eb = t->edge;
- do {
- _generateEdgeEdgeIntersections(ea, eb);
- eb = eb->next;
- } while (eb != t->edge);
- }
- ea = ea->next;
- } while (ea != a->edge);
-}
-
-
-
-void carve::csg::CSG::_generateVertexFaceIntersections(meshset_t::face_t *fa,
- meshset_t::edge_t *eb) {
- if (intersections.intersects(eb->v1(), fa)) {
- return;
- }
-
- double d1 = carve::geom::distance(fa->plane, eb->v1()->v);
-
- if (fabs(d1) < carve::EPSILON &&
- fa->containsPoint(eb->v1()->v)) {
- intersections.record(eb->v1(), fa, eb->v1());
- }
-}
-
-
-
-void carve::csg::CSG::generateVertexFaceIntersections(meshset_t::face_t *a,
- const std::vector<meshset_t::face_t *> &b) {
- meshset_t::edge_t *eb;
-
- for (size_t i = 0; i < b.size(); ++i) {
- meshset_t::face_t *t = b[i];
- eb = t->edge;
- do {
- _generateVertexFaceIntersections(a, eb);
- eb = eb->next;
- } while (eb != t->edge);
- }
-}
-
-
-
-void carve::csg::CSG::_generateEdgeFaceIntersections(meshset_t::face_t *fa,
- meshset_t::edge_t *eb) {
- if (intersections.intersects(eb, fa)) {
- return;
- }
-
- meshset_t::vertex_t::vector_t _p;
- if (fa->simpleLineSegmentIntersection(carve::geom3d::LineSegment(eb->v1()->v, eb->v2()->v), _p)) {
- meshset_t::vertex_t *p = vertex_pool.get(_p);
- intersections.record(eb, fa, p);
- if (eb->rev) intersections.record(eb->rev, fa, p);
- }
-}
-
-
-
-void carve::csg::CSG::generateEdgeFaceIntersections(meshset_t::face_t *a,
- const std::vector<meshset_t::face_t *> &b) {
- meshset_t::edge_t *eb;
-
- for (size_t i = 0; i < b.size(); ++i) {
- meshset_t::face_t *t = b[i];
- eb = t->edge;
- do {
- _generateEdgeFaceIntersections(a, eb);
- eb = eb->next;
- } while (eb != t->edge);
- }
-}
-
-
-
-void carve::csg::CSG::generateIntersectionCandidates(meshset_t *a,
- const face_rtree_t *a_node,
- meshset_t *b,
- const face_rtree_t *b_node,
- face_pairs_t &face_pairs,
- bool descend_a) {
- if (!a_node->bbox.intersects(b_node->bbox)) {
- return;
- }
-
- if (a_node->child && (descend_a || !b_node->child)) {
- for (face_rtree_t *node = a_node->child; node; node = node->sibling) {
- generateIntersectionCandidates(a, node, b, b_node, face_pairs, false);
- }
- } else if (b_node->child) {
- for (face_rtree_t *node = b_node->child; node; node = node->sibling) {
- generateIntersectionCandidates(a, a_node, b, node, face_pairs, true);
- }
- } else {
- for (size_t i = 0; i < a_node->data.size(); ++i) {
- meshset_t::face_t *fa = a_node->data[i];
- carve::geom::aabb<3> aabb_a = fa->getAABB();
- if (aabb_a.maxAxisSeparation(b_node->bbox) > carve::EPSILON) continue;
-
- for (size_t j = 0; j < b_node->data.size(); ++j) {
- meshset_t::face_t *fb = b_node->data[j];
- carve::geom::aabb<3> aabb_b = fb->getAABB();
- if (aabb_b.maxAxisSeparation(aabb_a) > carve::EPSILON) continue;
-
- std::pair<double, double> a_ra = fa->rangeInDirection(fa->plane.N, fa->edge->vert->v);
- std::pair<double, double> b_ra = fb->rangeInDirection(fa->plane.N, fa->edge->vert->v);
- if (carve::rangeSeparation(a_ra, b_ra) > carve::EPSILON) continue;
-
- std::pair<double, double> a_rb = fa->rangeInDirection(fb->plane.N, fb->edge->vert->v);
- std::pair<double, double> b_rb = fb->rangeInDirection(fb->plane.N, fb->edge->vert->v);
- if (carve::rangeSeparation(a_rb, b_rb) > carve::EPSILON) continue;
-
- if (!facesAreCoplanar(fa, fb)) {
- face_pairs[fa].push_back(fb);
- face_pairs[fb].push_back(fa);
- }
- }
- }
- }
-}
-
-
-
-
-void carve::csg::CSG::generateIntersections(meshset_t *a,
- const face_rtree_t *a_rtree,
- meshset_t *b,
- const face_rtree_t *b_rtree,
- detail::Data &data) {
- face_pairs_t face_pairs;
- generateIntersectionCandidates(a, a_rtree, b, b_rtree, face_pairs);
-
- for (face_pairs_t::const_iterator i = face_pairs.begin(); i != face_pairs.end(); ++i) {
- meshset_t::face_t *f = (*i).first;
- meshset_t::edge_t *e = f->edge;
- do {
- data.vert_to_edges[e->v1()].push_back(e);
- e = e->next;
- } while (e != f->edge);
- }
-
- for (face_pairs_t::const_iterator i = face_pairs.begin(); i != face_pairs.end(); ++i) {
- generateVertexVertexIntersections((*i).first, (*i).second);
- }
-
- for (face_pairs_t::const_iterator i = face_pairs.begin(); i != face_pairs.end(); ++i) {
- generateVertexEdgeIntersections((*i).first, (*i).second);
- }
-
- for (face_pairs_t::const_iterator i = face_pairs.begin(); i != face_pairs.end(); ++i) {
- generateEdgeEdgeIntersections((*i).first, (*i).second);
- }
-
- for (face_pairs_t::const_iterator i = face_pairs.begin(); i != face_pairs.end(); ++i) {
- generateVertexFaceIntersections((*i).first, (*i).second);
- }
-
- for (face_pairs_t::const_iterator i = face_pairs.begin(); i != face_pairs.end(); ++i) {
- generateEdgeFaceIntersections((*i).first, (*i).second);
- }
-
-
-#if defined(CARVE_DEBUG)
- std::cerr << "makeVertexIntersections" << std::endl;
-#endif
- makeVertexIntersections();
-
-#if defined(CARVE_DEBUG)
- std::cerr << " intersections.size() " << intersections.size() << std::endl;
- map_histogram(std::cerr, intersections);
- std::cerr << " vertex_intersections.size() " << vertex_intersections.size() << std::endl;
- map_histogram(std::cerr, vertex_intersections);
-#endif
-
-#if defined(CARVE_DEBUG) && defined(DEBUG_DRAW_INTERSECTIONS)
- HOOK(drawIntersections(vertex_intersections););
-#endif
-
-#if defined(CARVE_DEBUG)
- std::cerr << " intersections.size() " << intersections.size() << std::endl;
- std::cerr << " vertex_intersections.size() " << vertex_intersections.size() << std::endl;
-#endif
-
- // notify about intersections.
- if (hooks.hasHook(Hooks::INTERSECTION_VERTEX_HOOK)) {
- for (VertexIntersections::const_iterator i = vertex_intersections.begin();
- i != vertex_intersections.end();
- ++i) {
- hooks.intersectionVertex((*i).first, (*i).second);
- }
- }
-
- // from here on, only vertex_intersections is used for intersection
- // information.
-
- // intersections still contains the vertex_to_face map. maybe that
- // should be moved out into another class.
- static_cast<Intersections::super>(intersections).clear();
-}
-
-
-
-carve::csg::CSG::CSG() {
-}
-
-
-
-/**
- * \brief For each intersected edge, decompose into a set of vertex pairs representing an ordered set of edge fragments.
- *
- * @tparam[in,out] data Internal intersection data. data.emap is used to produce data.divided_edges.
- */
-void carve::csg::CSG::divideIntersectedEdges(detail::Data &data) {
- static carve::TimingName FUNC_NAME("CSG::divideIntersectedEdges()");
- carve::TimingBlock block(FUNC_NAME);
-
- for (detail::EIntMap::const_iterator i = data.emap.begin(), ei = data.emap.end(); i != ei; ++i) {
- meshset_t::edge_t *edge = (*i).first;
- const detail::EIntMap::mapped_type &int_info = (*i).second;
- std::vector<meshset_t::vertex_t *> &verts = data.divided_edges[edge];
- orderEdgeIntersectionVertices(int_info.begin(), int_info.end(),
- edge->v2()->v - edge->v1()->v, edge->v1()->v,
- verts);
- }
-}
-
-
-
-carve::csg::CSG::~CSG() {
-}
-
-
-
-void carve::csg::CSG::makeFaceEdges(carve::csg::EdgeClassification &eclass,
- detail::Data &data) {
- detail::FSet face_b_set;
- for (detail::FVSMap::const_iterator
- i = data.fmap.begin(), ie = data.fmap.end();
- i != ie;
- ++i) {
- meshset_t::face_t *face_a = (*i).first;
- const detail::FVSMap::mapped_type &face_a_intersections = ((*i).second);
- face_b_set.clear();
-
- // work out the set of faces from the opposing polyhedron that intersect face_a.
- for (detail::FVSMap::mapped_type::const_iterator
- j = face_a_intersections.begin(), je = face_a_intersections.end();
- j != je;
- ++j) {
- for (detail::VFSMap::mapped_type::const_iterator
- k = data.fmap_rev[*j].begin(), ke = data.fmap_rev[*j].end();
- k != ke;
- ++k) {
- meshset_t::face_t *face_b = (*k);
- if (face_a != face_b && face_b->mesh->meshset != face_a->mesh->meshset) {
- face_b_set.insert(face_b);
- }
- }
- }
-
- // run through each intersecting face.
- for (detail::FSet::const_iterator
- j = face_b_set.begin(), je = face_b_set.end();
- j != je;
- ++j) {
- meshset_t::face_t *face_b = (*j);
- const detail::FVSMap::mapped_type &face_b_intersections = (data.fmap[face_b]);
-
- std::vector<meshset_t::vertex_t *> vertices;
- vertices.reserve(std::min(face_a_intersections.size(), face_b_intersections.size()));
-
- // record the points of intersection between face_a and face_b
- std::set_intersection(face_a_intersections.begin(),
- face_a_intersections.end(),
- face_b_intersections.begin(),
- face_b_intersections.end(),
- std::back_inserter(vertices));
-
-#if defined(CARVE_DEBUG)
- std::cerr << "face pair: "
- << face_a << ":" << face_b
- << " N(verts) " << vertices.size() << std::endl;
- for (std::vector<meshset_t::vertex_t *>::const_iterator i = vertices.begin(), e = vertices.end(); i != e; ++i) {
- std::cerr << (*i) << " " << (*i)->v << " ("
- << carve::geom::distance(face_a->plane, (*i)->v) << ","
- << carve::geom::distance(face_b->plane, (*i)->v) << ")"
- << std::endl;
- //CARVE_ASSERT(carve::geom3d::distance(face_a->plane_eqn, *(*i)) < EPSILON);
- //CARVE_ASSERT(carve::geom3d::distance(face_b->plane_eqn, *(*i)) < EPSILON);
- }
-#endif
-
- // if there are two points of intersection, then the added edge is simple to determine.
- if (vertices.size() == 2) {
- meshset_t::vertex_t *v1 = vertices[0];
- meshset_t::vertex_t *v2 = vertices[1];
- carve::geom3d::Vector c = (v1->v + v2->v) / 2;
-
- // determine whether the midpoint of the implied edge is contained in face_a and face_b
-
-#if defined(CARVE_DEBUG)
- std::cerr << "face_a->nVertices() = " << face_a->nVertices() << " face_a->containsPointInProjection(c) = " << face_a->containsPointInProjection(c) << std::endl;
- std::cerr << "face_b->nVertices() = " << face_b->nVertices() << " face_b->containsPointInProjection(c) = " << face_b->containsPointInProjection(c) << std::endl;
-#endif
-
- if (face_a->containsPointInProjection(c) && face_b->containsPointInProjection(c)) {
-#if defined(CARVE_DEBUG)
- std::cerr << "adding edge: " << v1 << "-" << v2 << std::endl;
-#if defined(DEBUG_DRAW_FACE_EDGES)
- HOOK(drawEdge(v1, v2, 1, 1, 1, 1, 1, 1, 1, 1, 2.0););
-#endif
-#endif
- // record the edge, with class information.
- if (v1 > v2) std::swap(v1, v2);
- eclass[ordered_edge(v1, v2)] = carve::csg::EC2(carve::csg::EDGE_ON, carve::csg::EDGE_ON);
- data.face_split_edges[face_a].insert(std::make_pair(v1, v2));
- data.face_split_edges[face_b].insert(std::make_pair(v1, v2));
- }
- continue;
- }
-
- // otherwise, it's more complex.
- carve::geom3d::Vector base, dir;
- std::vector<meshset_t::vertex_t *> ordered;
-
- // skip coplanar edges. this simplifies the resulting
- // mesh. eventually all coplanar face regions of two polyhedra
- // must reach a point where they are no longer coplanar (or the
- // polyhedra are identical).
- if (!facesAreCoplanar(face_a, face_b)) {
- // order the intersection vertices (they must lie along a
- // vector, as the faces aren't coplanar).
- selectOrderingProjection(vertices.begin(), vertices.end(), dir, base);
- orderVertices(vertices.begin(), vertices.end(), dir, base, ordered);
-
- // for each possible edge in the ordering, test the midpoint,
- // and record if it's contained in face_a and face_b.
- for (int k = 0, ke = (int)ordered.size() - 1; k < ke; ++k) {
- meshset_t::vertex_t *v1 = ordered[k];
- meshset_t::vertex_t *v2 = ordered[k + 1];
- carve::geom3d::Vector c = (v1->v + v2->v) / 2;
-
-#if defined(CARVE_DEBUG)
- std::cerr << "testing edge: " << v1 << "-" << v2 << " at " << c << std::endl;
- std::cerr << "a: " << face_a->containsPointInProjection(c) << " b: " << face_b->containsPointInProjection(c) << std::endl;
- std::cerr << "face_a->containsPointInProjection(c): " << face_a->containsPointInProjection(c) << std::endl;
- std::cerr << "face_b->containsPointInProjection(c): " << face_b->containsPointInProjection(c) << std::endl;
-#endif
-
- if (face_a->containsPointInProjection(c) && face_b->containsPointInProjection(c)) {
-#if defined(CARVE_DEBUG)
- std::cerr << "adding edge: " << v1 << "-" << v2 << std::endl;
-#if defined(DEBUG_DRAW_FACE_EDGES)
- HOOK(drawEdge(v1, v2, .5, .5, .5, 1, .5, .5, .5, 1, 2.0););
-#endif
-#endif
- // record the edge, with class information.
- if (v1 > v2) std::swap(v1, v2);
- eclass[ordered_edge(v1, v2)] = carve::csg::EC2(carve::csg::EDGE_ON, carve::csg::EDGE_ON);
- data.face_split_edges[face_a].insert(std::make_pair(v1, v2));
- data.face_split_edges[face_b].insert(std::make_pair(v1, v2));
- }
- }
- }
- }
- }
-
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- {
- V2Set edges;
- for (detail::FV2SMap::const_iterator i = data.face_split_edges.begin(); i != data.face_split_edges.end(); ++i) {
- edges.insert((*i).second.begin(), (*i).second.end());
- }
-
- detail::VSet vertices;
- for (V2Set::const_iterator i = edges.begin(); i != edges.end(); ++i) {
- vertices.insert((*i).first);
- vertices.insert((*i).second);
- }
-
- carve::line::PolylineSet intersection_graph;
- intersection_graph.vertices.resize(vertices.size());
- std::map<const meshset_t::vertex_t *, size_t> vmap;
-
- size_t j = 0;
- for (detail::VSet::const_iterator i = vertices.begin(); i != vertices.end(); ++i) {
- intersection_graph.vertices[j].v = (*i)->v;
- vmap[(*i)] = j++;
- }
-
- for (V2Set::const_iterator i = edges.begin(); i != edges.end(); ++i) {
- size_t line[2];
- line[0] = vmap[(*i).first];
- line[1] = vmap[(*i).second];
- intersection_graph.addPolyline(false, line, line + 2);
- }
-
- std::string out("/tmp/intersection-edges.ply");
- ::writePLY(out, &intersection_graph, true);
- }
-#endif
-}
-
-
-
-/**
- *
- *
- * @param fll
- */
-#if 0
-static void checkFaceLoopIntegrity(carve::csg::FaceLoopList &fll) {
- static carve::TimingName FUNC_NAME("CSG::checkFaceLoopIntegrity()");
- carve::TimingBlock block(FUNC_NAME);
-
- std::unordered_map<carve::csg::V2, int> counts;
- for (carve::csg::FaceLoop *fl = fll.head; fl; fl = fl->next) {
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &loop = (fl->vertices);
- carve::mesh::MeshSet<3>::vertex_t *v1, *v2;
- v1 = loop[loop.size() - 1];
- for (unsigned i = 0; i < loop.size(); ++i) {
- v2 = loop[i];
- if (v1 < v2) {
- counts[std::make_pair(v1, v2)]++;
- } else {
- counts[std::make_pair(v2, v1)]--;
- }
- v1 = v2;
- }
- }
- for (std::unordered_map<carve::csg::V2, int>::const_iterator
- x = counts.begin(), xe = counts.end(); x != xe; ++x) {
- if ((*x).second) {
- std::cerr << "FACE LOOP ERROR: " << (*x).first.first << "-" << (*x).first.second << " : " << (*x).second << std::endl;
- }
- }
-}
-#endif
-
-
-/**
- *
- *
- * @param a
- * @param b
- * @param vclass
- * @param eclass
- * @param a_face_loops
- * @param b_face_loops
- * @param a_edge_count
- * @param b_edge_count
- * @param hooks
- */
-void carve::csg::CSG::calc(meshset_t *a,
- const face_rtree_t *a_rtree,
- meshset_t *b,
- const face_rtree_t *b_rtree,
- carve::csg::VertexClassification &vclass,
- carve::csg::EdgeClassification &eclass,
- carve::csg::FaceLoopList &a_face_loops,
- carve::csg::FaceLoopList &b_face_loops,
- size_t &a_edge_count,
- size_t &b_edge_count) {
- detail::Data data;
-
-#if defined(CARVE_DEBUG)
- std::cerr << "init" << std::endl;
-#endif
- init();
-
- generateIntersections(a, a_rtree, b, b_rtree, data);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "intersectingFacePairs" << std::endl;
-#endif
- intersectingFacePairs(data);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "emap:" << std::endl;
- map_histogram(std::cerr, data.emap);
- std::cerr << "fmap:" << std::endl;
- map_histogram(std::cerr, data.fmap);
- std::cerr << "fmap_rev:" << std::endl;
- map_histogram(std::cerr, data.fmap_rev);
-#endif
-
- // std::cerr << "removeCoplanarFaces" << std::endl;
- // fp_intersections.removeCoplanarFaces();
-
-#if defined(CARVE_DEBUG) && defined(DEBUG_DRAW_OCTREE)
- HOOK(drawOctree(a->octree););
- HOOK(drawOctree(b->octree););
-#endif
-
-#if defined(CARVE_DEBUG)
- std::cerr << "divideIntersectedEdges" << std::endl;
-#endif
- divideIntersectedEdges(data);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "makeFaceEdges" << std::endl;
-#endif
- // makeFaceEdges(data.face_split_edges, eclass, data.fmap, data.fmap_rev);
- makeFaceEdges(eclass, data);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "generateFaceLoops" << std::endl;
-#endif
- a_edge_count = generateFaceLoops(a, data, a_face_loops);
- b_edge_count = generateFaceLoops(b, data, b_face_loops);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "generated " << a_edge_count << " edges for poly a" << std::endl;
- std::cerr << "generated " << b_edge_count << " edges for poly b" << std::endl;
-#endif
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- {
- std::auto_ptr<carve::mesh::MeshSet<3> > poly(faceLoopsToPolyhedron(a_face_loops));
- writePLY("/tmp/a_split.ply", poly.get(), false);
- }
- {
- std::auto_ptr<carve::mesh::MeshSet<3> > poly(faceLoopsToPolyhedron(b_face_loops));
- writePLY("/tmp/b_split.ply", poly.get(), false);
- }
-#endif
-
- // checkFaceLoopIntegrity(a_face_loops);
- // checkFaceLoopIntegrity(b_face_loops);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "classify" << std::endl;
-#endif
- // initialize some classification information.
- for (std::vector<meshset_t::vertex_t>::iterator
- i = a->vertex_storage.begin(), e = a->vertex_storage.end(); i != e; ++i) {
- vclass[map_vertex(data.vmap, &(*i))].cls[0] = POINT_ON;
- }
- for (std::vector<meshset_t::vertex_t>::iterator
- i = b->vertex_storage.begin(), e = b->vertex_storage.end(); i != e; ++i) {
- vclass[map_vertex(data.vmap, &(*i))].cls[1] = POINT_ON;
- }
- for (VertexIntersections::const_iterator
- i = vertex_intersections.begin(), e = vertex_intersections.end(); i != e; ++i) {
- vclass[(*i).first] = PC2(POINT_ON, POINT_ON);
- }
-
-#if defined(CARVE_DEBUG)
- std::cerr << data.divided_edges.size() << " edges are split" << std::endl;
- std::cerr << data.face_split_edges.size() << " faces are split" << std::endl;
-
- std::cerr << "poly a: " << a_face_loops.size() << " face loops" << std::endl;
- std::cerr << "poly b: " << b_face_loops.size() << " face loops" << std::endl;
-#endif
-
- // std::cerr << "OCTREE A:" << std::endl;
- // dump_octree_stats(a->octree.root, 0);
- // std::cerr << "OCTREE B:" << std::endl;
- // dump_octree_stats(b->octree.root, 0);
-}
-
-
-
-/**
- *
- *
- * @param shared_edges
- * @param result_list
- * @param shared_edge_ptr
- */
-static void returnSharedEdges(carve::csg::V2Set &shared_edges,
- std::list<carve::mesh::MeshSet<3> *> &result_list,
- carve::csg::V2Set *shared_edge_ptr) {
- // need to convert shared edges to point into result
- typedef std::map<carve::geom3d::Vector, carve::mesh::MeshSet<3>::vertex_t *> remap_type;
- remap_type remap;
- for (std::list<carve::mesh::MeshSet<3> *>::iterator list_it =
- result_list.begin(); list_it != result_list.end(); list_it++) {
- carve::mesh::MeshSet<3> *result = *list_it;
- if (result) {
- for (std::vector<carve::mesh::MeshSet<3>::vertex_t>::iterator it =
- result->vertex_storage.begin(); it != result->vertex_storage.end(); it++) {
- remap.insert(std::make_pair((*it).v, &(*it)));
- }
- }
- }
- for (carve::csg::V2Set::iterator it = shared_edges.begin();
- it != shared_edges.end(); it++) {
- remap_type::iterator first_it = remap.find(((*it).first)->v);
- remap_type::iterator second_it = remap.find(((*it).second)->v);
- CARVE_ASSERT(first_it != remap.end() && second_it != remap.end());
- shared_edge_ptr->insert(std::make_pair(first_it->second, second_it->second));
- }
-}
-
-
-
-/**
- *
- *
- * @param a
- * @param b
- * @param collector
- * @param hooks
- * @param shared_edges_ptr
- * @param classify_type
- *
- * @return
- */
-carve::mesh::MeshSet<3> *carve::csg::CSG::compute(meshset_t *a,
- meshset_t *b,
- carve::csg::CSG::Collector &collector,
- carve::csg::V2Set *shared_edges_ptr,
- CLASSIFY_TYPE classify_type) {
- static carve::TimingName FUNC_NAME("CSG::compute");
- carve::TimingBlock block(FUNC_NAME);
-
- VertexClassification vclass;
- EdgeClassification eclass;
-
- FLGroupList a_loops_grouped;
- FLGroupList b_loops_grouped;
-
- FaceLoopList a_face_loops;
- FaceLoopList b_face_loops;
-
- size_t a_edge_count;
- size_t b_edge_count;
-
- std::auto_ptr<face_rtree_t> a_rtree(face_rtree_t::construct_STR(a->faceBegin(), a->faceEnd(), 4, 4));
- std::auto_ptr<face_rtree_t> b_rtree(face_rtree_t::construct_STR(b->faceBegin(), b->faceEnd(), 4, 4));
-
- {
- static carve::TimingName FUNC_NAME("CSG::compute - calc()");
- carve::TimingBlock block(FUNC_NAME);
- calc(a, a_rtree.get(), b, b_rtree.get(), vclass, eclass,a_face_loops, b_face_loops, a_edge_count, b_edge_count);
- }
-
- detail::LoopEdges a_edge_map;
- detail::LoopEdges b_edge_map;
-
- {
- static carve::TimingName FUNC_NAME("CSG::compute - makeEdgeMap()");
- carve::TimingBlock block(FUNC_NAME);
- makeEdgeMap(a_face_loops, a_edge_count, a_edge_map);
- makeEdgeMap(b_face_loops, b_edge_count, b_edge_map);
-
- }
-
- {
- static carve::TimingName FUNC_NAME("CSG::compute - sortFaceLoopLists()");
- carve::TimingBlock block(FUNC_NAME);
- a_edge_map.sortFaceLoopLists();
- b_edge_map.sortFaceLoopLists();
- }
-
- V2Set shared_edges;
-
- {
- static carve::TimingName FUNC_NAME("CSG::compute - findSharedEdges()");
- carve::TimingBlock block(FUNC_NAME);
- findSharedEdges(a_edge_map, b_edge_map, shared_edges);
- }
-
- {
- static carve::TimingName FUNC_NAME("CSG::compute - groupFaceLoops()");
- carve::TimingBlock block(FUNC_NAME);
- groupFaceLoops(a, a_face_loops, a_edge_map, shared_edges, a_loops_grouped);
- groupFaceLoops(b, b_face_loops, b_edge_map, shared_edges, b_loops_grouped);
-#if defined(CARVE_DEBUG)
- std::cerr << "*** a_loops_grouped.size(): " << a_loops_grouped.size() << std::endl;
- std::cerr << "*** b_loops_grouped.size(): " << b_loops_grouped.size() << std::endl;
-#endif
- }
-
-#if defined(CARVE_DEBUG) && defined(DEBUG_DRAW_GROUPS)
- {
- float n = 1.0 / (a_loops_grouped.size() + b_loops_grouped.size() + 1);
- float H = 0.0, S = 1.0, V = 1.0;
- float r, g, b;
- for (FLGroupList::const_iterator i = a_loops_grouped.begin(); i != a_loops_grouped.end(); ++i) {
- carve::colour::HSV2RGB(H, S, V, r, g, b); H += n;
- drawFaceLoopList((*i).face_loops, r, g, b, 1.0, r * .5, g * .5, b * .5, 1.0, true);
- }
- for (FLGroupList::const_iterator i = b_loops_grouped.begin(); i != b_loops_grouped.end(); ++i) {
- carve::colour::HSV2RGB(H, S, V, r, g, b); H += n;
- drawFaceLoopList((*i).face_loops, r, g, b, 1.0, r * .5, g * .5, b * .5, 1.0, true);
- }
-
- for (FLGroupList::const_iterator i = a_loops_grouped.begin(); i != a_loops_grouped.end(); ++i) {
- drawFaceLoopListWireframe((*i).face_loops);
- }
- for (FLGroupList::const_iterator i = b_loops_grouped.begin(); i != b_loops_grouped.end(); ++i) {
- drawFaceLoopListWireframe((*i).face_loops);
- }
- }
-#endif
-
- switch (classify_type) {
- case CLASSIFY_EDGE:
- classifyFaceGroupsEdge(shared_edges,
- vclass,
- a,
- a_rtree.get(),
- a_loops_grouped,
- a_edge_map,
- b,
- b_rtree.get(),
- b_loops_grouped,
- b_edge_map,
- collector);
- break;
- case CLASSIFY_NORMAL:
- classifyFaceGroups(shared_edges,
- vclass,
- a,
- a_rtree.get(),
- a_loops_grouped,
- a_edge_map,
- b,
- b_rtree.get(),
- b_loops_grouped,
- b_edge_map,
- collector);
- break;
- }
-
- meshset_t *result = collector.done(hooks);
- if (result != NULL && shared_edges_ptr != NULL) {
- std::list<meshset_t *> result_list;
- result_list.push_back(result);
- returnSharedEdges(shared_edges, result_list, shared_edges_ptr);
- }
- return result;
-}
-
-
-
-/**
- *
- *
- * @param a
- * @param b
- * @param op
- * @param hooks
- * @param shared_edges
- * @param classify_type
- *
- * @return
- */
-carve::mesh::MeshSet<3> *carve::csg::CSG::compute(meshset_t *a,
- meshset_t *b,
- carve::csg::CSG::OP op,
- carve::csg::V2Set *shared_edges,
- CLASSIFY_TYPE classify_type) {
- Collector *coll = makeCollector(op, a, b);
- if (!coll) return NULL;
-
- meshset_t *result = compute(a, b, *coll, shared_edges, classify_type);
-
- delete coll;
-
- return result;
-}
-
-
-
-/**
- *
- *
- * @param closed
- * @param open
- * @param FaceClass
- * @param result
- * @param hooks
- * @param shared_edges_ptr
- *
- * @return
- */
-bool carve::csg::CSG::sliceAndClassify(meshset_t *closed,
- meshset_t *open,
- std::list<std::pair<FaceClass, meshset_t *> > &result,
- carve::csg::V2Set *shared_edges_ptr) {
- if (!closed->isClosed()) return false;
- carve::csg::VertexClassification vclass;
- carve::csg::EdgeClassification eclass;
-
- carve::csg::FLGroupList a_loops_grouped;
- carve::csg::FLGroupList b_loops_grouped;
-
- carve::csg::FaceLoopList a_face_loops;
- carve::csg::FaceLoopList b_face_loops;
-
- size_t a_edge_count;
- size_t b_edge_count;
-
- std::auto_ptr<face_rtree_t> closed_rtree(face_rtree_t::construct_STR(closed->faceBegin(), closed->faceEnd(), 4, 4));
- std::auto_ptr<face_rtree_t> open_rtree(face_rtree_t::construct_STR(open->faceBegin(), open->faceEnd(), 4, 4));
-
- calc(closed, closed_rtree.get(), open, open_rtree.get(), vclass, eclass,a_face_loops, b_face_loops, a_edge_count, b_edge_count);
-
- detail::LoopEdges a_edge_map;
- detail::LoopEdges b_edge_map;
-
- makeEdgeMap(a_face_loops, a_edge_count, a_edge_map);
- makeEdgeMap(b_face_loops, b_edge_count, b_edge_map);
-
- carve::csg::V2Set shared_edges;
-
- findSharedEdges(a_edge_map, b_edge_map, shared_edges);
-
- groupFaceLoops(closed, a_face_loops, a_edge_map, shared_edges, a_loops_grouped);
- groupFaceLoops(open, b_face_loops, b_edge_map, shared_edges, b_loops_grouped);
-
- halfClassifyFaceGroups(shared_edges,
- vclass,
- closed,
- closed_rtree.get(),
- a_loops_grouped,
- a_edge_map,
- open,
- open_rtree.get(),
- b_loops_grouped,
- b_edge_map,
- result);
-
- if (shared_edges_ptr != NULL) {
- std::list<meshset_t *> result_list;
- for (std::list<std::pair<FaceClass, meshset_t *> >::iterator it = result.begin(); it != result.end(); it++) {
- result_list.push_back(it->second);
- }
- returnSharedEdges(shared_edges, result_list, shared_edges_ptr);
- }
- return true;
-}
-
-
-
-/**
- *
- *
- * @param a
- * @param b
- * @param a_sliced
- * @param b_sliced
- * @param hooks
- * @param shared_edges_ptr
- */
-void carve::csg::CSG::slice(meshset_t *a,
- meshset_t *b,
- std::list<meshset_t *> &a_sliced,
- std::list<meshset_t *> &b_sliced,
- carve::csg::V2Set *shared_edges_ptr) {
- carve::csg::VertexClassification vclass;
- carve::csg::EdgeClassification eclass;
-
- carve::csg::FLGroupList a_loops_grouped;
- carve::csg::FLGroupList b_loops_grouped;
-
- carve::csg::FaceLoopList a_face_loops;
- carve::csg::FaceLoopList b_face_loops;
-
- size_t a_edge_count;
- size_t b_edge_count;
-
- std::auto_ptr<face_rtree_t> a_rtree(face_rtree_t::construct_STR(a->faceBegin(), a->faceEnd(), 4, 4));
- std::auto_ptr<face_rtree_t> b_rtree(face_rtree_t::construct_STR(b->faceBegin(), b->faceEnd(), 4, 4));
-
- calc(a, a_rtree.get(), b, b_rtree.get(), vclass, eclass,a_face_loops, b_face_loops, a_edge_count, b_edge_count);
-
- detail::LoopEdges a_edge_map;
- detail::LoopEdges b_edge_map;
-
- makeEdgeMap(a_face_loops, a_edge_count, a_edge_map);
- makeEdgeMap(b_face_loops, b_edge_count, b_edge_map);
-
- carve::csg::V2Set shared_edges;
-
- findSharedEdges(a_edge_map, b_edge_map, shared_edges);
-
- groupFaceLoops(a, a_face_loops, a_edge_map, shared_edges, a_loops_grouped);
- groupFaceLoops(b, b_face_loops, b_edge_map, shared_edges, b_loops_grouped);
-
- for (carve::csg::FLGroupList::iterator
- i = a_loops_grouped.begin(), e = a_loops_grouped.end();
- i != e; ++i) {
- Collector *all = makeCollector(ALL, a, b);
- all->collect(&*i, hooks);
- a_sliced.push_back(all->done(hooks));
-
- delete all;
- }
-
- for (carve::csg::FLGroupList::iterator
- i = b_loops_grouped.begin(), e = b_loops_grouped.end();
- i != e; ++i) {
- Collector *all = makeCollector(ALL, a, b);
- all->collect(&*i, hooks);
- b_sliced.push_back(all->done(hooks));
-
- delete all;
- }
- if (shared_edges_ptr != NULL) {
- std::list<meshset_t *> result_list;
- result_list.insert(result_list.end(), a_sliced.begin(), a_sliced.end());
- result_list.insert(result_list.end(), b_sliced.begin(), b_sliced.end());
- returnSharedEdges(shared_edges, result_list, shared_edges_ptr);
- }
-}
-
-
-
-/**
- *
- *
- */
-void carve::csg::CSG::init() {
- intersections.clear();
- vertex_intersections.clear();
- vertex_pool.reset();
-}
diff --git a/extern/carve/lib/intersect_classify_common.hpp b/extern/carve/lib/intersect_classify_common.hpp
deleted file mode 100644
index ab59f27b029..00000000000
--- a/extern/carve/lib/intersect_classify_common.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-#include "intersect_common.hpp"
-
-template<typename T>
-static int is_same(const std::vector<T> &a,
- const std::vector<T> &b) {
- if (a.size() != b.size()) return false;
-
- const size_t S = a.size();
- size_t i, j, p;
-
- for (p = 0; p < S; ++p) {
- if (a[0] == b[p]) break;
- }
- if (p == S) return 0;
-
- for (i = 1, j = p + 1; j < S; ++i, ++j) if (a[i] != b[j]) goto not_fwd;
- for ( j = 0; i < S; ++i, ++j) if (a[i] != b[j]) goto not_fwd;
- return +1;
-
-not_fwd:
- for (i = 1, j = p - 1; j != (size_t)-1; ++i, --j) if (a[i] != b[j]) goto not_rev;
- for ( j = S - 1; i < S; ++i, --j) if (a[i] != b[j]) goto not_rev;
- return -1;
-
-not_rev:
- return 0;
-}
diff --git a/extern/carve/lib/intersect_classify_common_impl.hpp b/extern/carve/lib/intersect_classify_common_impl.hpp
deleted file mode 100644
index 409b9476a88..00000000000
--- a/extern/carve/lib/intersect_classify_common_impl.hpp
+++ /dev/null
@@ -1,362 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-namespace carve {
- namespace csg {
- typedef std::unordered_map<
- carve::mesh::MeshSet<3>::vertex_t *,
- std::list<FLGroupList::iterator> > GroupLookup;
-
-
- inline bool isSameFwd(const V2Set &a, const V2Set &b) {
- if (a.size() != b.size()) return false;
- for (V2Set::const_iterator i = a.begin(), e = a.end(); i != e; ++i) {
- if (b.find((*i)) == b.end()) return false;
- }
- return true;
- }
-
- inline bool isSameRev(const V2Set &a, const V2Set &b) {
- if (a.size() != b.size()) return false;
- for (V2Set::const_iterator i = a.begin(), e = a.end(); i != e; ++i) {
- if (b.find(std::make_pair((*i).second, (*i).first)) == b.end()) return false;
- }
- return true;
- }
-
-
- static void performClassifySimpleOnFaceGroups(FLGroupList &a_groups,
- FLGroupList &b_groups,
- carve::mesh::MeshSet<3> *poly_a,
- carve::mesh::MeshSet<3> *poly_b,
- CSG::Collector &collector,
- CSG::Hooks &hooks) {
- // Simple ON faces groups are face groups that consist of a single
- // face, and which have copy in both inputs. These are trivially ON.
- // This has the side effect of short circuiting the case where the
- // two inputs share geometry.
- GroupLookup a_map, b_map;
-
- // First, hash FaceLoopGroups with one FaceLoop based upon their
- // minimum vertex pointer - this pointer must be shared between
- // FaceLoops that this test catches.
- for (FLGroupList::iterator i = a_groups.begin(); i != a_groups.end(); ++i) {
- if ((*i).face_loops.size() != 1) continue;
- FaceLoop *f = (*i).face_loops.head;
- carve::mesh::MeshSet<3>::vertex_t *v = *std::min_element(f->vertices.begin(), f->vertices.end());
- a_map[v].push_back(i);
- }
-
- for (FLGroupList::iterator i = b_groups.begin(); i != b_groups.end(); ++i) {
- if ((*i).face_loops.size() != 1) continue;
- FaceLoop *f = (*i).face_loops.head;
- carve::mesh::MeshSet<3>::vertex_t *v = *std::min_element(f->vertices.begin(), f->vertices.end());
- if (a_map.find(v) != a_map.end()) {
- b_map[v].push_back(i);
- }
- }
-
- // Then, iterate through the FaceLoops hashed in the first map, and
- // find candidate matches in the second map.
- for (GroupLookup::iterator j = b_map.begin(), je = b_map.end(); j != je; ++j) {
- carve::mesh::MeshSet<3>::vertex_t *v = (*j).first;
- GroupLookup::iterator i = a_map.find(v);
-
- for (std::list<FLGroupList::iterator>::iterator bi = (*j).second.begin(), be = (*j).second.end(); bi != be;) {
- FLGroupList::iterator b(*bi);
- FaceLoop *f_b = (*b).face_loops.head;
-
- // For each candidate match pair, see if their vertex pointers
- // are the same, allowing for rotation and inversion.
- for (std::list<FLGroupList::iterator>::iterator ai = (*i).second.begin(), ae = (*i).second.end(); ai != ae; ++ai) {
- FLGroupList::iterator a(*ai);
- FaceLoop *f_a = (*a).face_loops.head;
-
- int s = is_same(f_a->vertices, f_b->vertices);
- if (!s) continue;
-
- // if they are ordered in the same direction, then they are
- // oriented out, otherwise oriented in.
- FaceClass fc = s == +1 ? FACE_ON_ORIENT_OUT : FACE_ON_ORIENT_IN;
-
- (*a).classification.push_back(ClassificationInfo(NULL, fc));
- (*b).classification.push_back(ClassificationInfo(NULL, fc));
-
- collector.collect(&*a, hooks);
- collector.collect(&*b, hooks);
-
- a_groups.erase(a);
- b_groups.erase(b);
-
- (*i).second.erase(ai);
- bi = (*j).second.erase(bi);
-
- goto done;
- }
- ++bi;
- done:;
- }
- }
- }
-
- template <typename CLASSIFIER>
- static void performClassifyEasyFaceGroups(FLGroupList &group,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- VertexClassification &vclass,
- const CLASSIFIER &classifier,
- CSG::Collector &collector,
- CSG::Hooks &hooks) {
-
- for (FLGroupList::iterator i = group.begin(); i != group.end();) {
-#if defined(CARVE_DEBUG)
- std::cerr << "............group " << &(*i) << std::endl;
-#endif
- FaceLoopGroup &grp = (*i);
- FaceLoopList &curr = (grp.face_loops);
- FaceClass fc;
-
- for (FaceLoop *f = curr.head; f; f = f->next) {
- for (size_t j = 0; j < f->vertices.size(); ++j) {
- if (!classifier.pointOn(vclass, f, j)) {
- PointClass pc = carve::mesh::classifyPoint(poly_a, poly_a_rtree, f->vertices[j]->v);
- if (pc == POINT_IN || pc == POINT_OUT) {
- classifier.explain(f, j, pc);
- }
- if (pc == POINT_IN) { fc = FACE_IN; goto accept; }
- if (pc == POINT_OUT) { fc = FACE_OUT; goto accept; }
- }
- }
- }
- ++i;
- continue;
- accept: {
- grp.classification.push_back(ClassificationInfo(NULL, fc));
- collector.collect(&grp, hooks);
- i = group.erase(i);
- }
- }
- }
-
-
- template <typename CLASSIFIER>
- static void performClassifyHardFaceGroups(FLGroupList &group,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- const CLASSIFIER & /* classifier */,
- CSG::Collector &collector,
- CSG::Hooks &hooks) {
- for (FLGroupList::iterator
- i = group.begin(); i != group.end();) {
- int n_in = 0, n_out = 0, n_on = 0;
- FaceLoopGroup &grp = (*i);
- FaceLoopList &curr = (grp.face_loops);
- V2Set &perim = ((*i).perimeter);
- FaceClass fc =FACE_UNCLASSIFIED;
-
- for (FaceLoop *f = curr.head; f; f = f->next) {
- carve::mesh::MeshSet<3>::vertex_t *v1, *v2;
- v1 = f->vertices.back();
- for (size_t j = 0; j < f->vertices.size(); ++j) {
- v2 = f->vertices[j];
- if (v1 < v2 && perim.find(std::make_pair(v1, v2)) == perim.end()) {
- carve::geom3d::Vector c = (v1->v + v2->v) / 2.0;
-
- PointClass pc = carve::mesh::classifyPoint(poly_a, poly_a_rtree, c);
-
- switch (pc) {
- case POINT_IN: n_in++; break;
- case POINT_OUT: n_out++; break;
- case POINT_ON: n_on++; break;
- default: break; // does not happen.
- }
- }
- v1 = v2;
- }
- }
-
-#if defined(CARVE_DEBUG)
- std::cerr << ">>> n_in: " << n_in << " n_on: " << n_on << " n_out: " << n_out << std::endl;
-#endif
-
- if (!n_in && !n_out) {
- ++i;
- continue;
- }
-
- if (n_in) fc = FACE_IN;
- if (n_out) fc = FACE_OUT;
-
- grp.classification.push_back(ClassificationInfo(NULL, fc));
- collector.collect(&grp, hooks);
- i = group.erase(i);
- }
- }
-
- template <typename CLASSIFIER>
- void performFaceLoopWork(carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- FLGroupList &b_loops_grouped,
- const CLASSIFIER &classifier,
- CSG::Collector &collector,
- CSG::Hooks &hooks) {
- for (FLGroupList::iterator i = b_loops_grouped.begin(), e = b_loops_grouped.end(); i != e;) {
- FaceClass fc;
-
- if (classifier.faceLoopSanityChecker(*i)) {
- std::cerr << "UNEXPECTED face loop with size != 1." << std::endl;
- ++i;
- continue;
- }
- CARVE_ASSERT((*i).face_loops.size() == 1);
-
- FaceLoop *fla = (*i).face_loops.head;
-
- const carve::mesh::MeshSet<3>::face_t *f = (fla->orig_face);
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &loop = (fla->vertices);
- std::vector<carve::geom2d::P2> proj;
- proj.reserve(loop.size());
- for (unsigned j = 0; j < loop.size(); ++j) {
- proj.push_back(f->project(loop[j]->v));
- }
- carve::geom2d::P2 pv;
- if (!carve::geom2d::pickContainedPoint(proj, pv)) {
- CARVE_FAIL("Failed");
- }
- carve::geom3d::Vector v = f->unproject(pv, f->plane);
-
- const carve::mesh::MeshSet<3>::face_t *hit_face;
- PointClass pc = carve::mesh::classifyPoint(poly_a, poly_a_rtree, v, false, NULL, &hit_face);
- switch (pc) {
- case POINT_IN: fc = FACE_IN; break;
- case POINT_OUT: fc = FACE_OUT; break;
- case POINT_ON: {
- double d = carve::geom::distance(hit_face->plane, v);
-#if defined(CARVE_DEBUG)
- std::cerr << "d = " << d << std::endl;
-#endif
- fc = d < 0 ? FACE_IN : FACE_OUT;
- break;
- }
- default:
- CARVE_FAIL("unhandled switch case -- should not happen");
- }
-#if defined(CARVE_DEBUG)
- std::cerr << "CLASS: " << (fc == FACE_IN ? "FACE_IN" : "FACE_OUT" ) << std::endl;
-#endif
-
- (*i).classification.push_back(ClassificationInfo(NULL, fc));
- collector.collect(&*i, hooks);
- i = b_loops_grouped.erase(i);
- }
-
- }
-
- template <typename CLASSIFIER>
- void performClassifyFaceGroups(FLGroupList &a_loops_grouped,
- FLGroupList &b_loops_grouped,
- VertexClassification &vclass,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- carve::mesh::MeshSet<3> *poly_b,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_b_rtree,
- const CLASSIFIER &classifier,
- CSG::Collector &collector,
- CSG::Hooks &hooks) {
-
- classifier.classifySimple(a_loops_grouped, b_loops_grouped, vclass, poly_a, poly_b);
- classifier.classifyEasy(a_loops_grouped, b_loops_grouped, vclass, poly_a, poly_a_rtree, poly_b, poly_b_rtree);
- classifier.classifyHard(a_loops_grouped, b_loops_grouped, vclass, poly_a, poly_a_rtree, poly_b, poly_b_rtree);
-
- {
- GroupLookup a_map;
- FLGroupList::iterator i, j;
- FaceClass fc;
-
- for (i = a_loops_grouped.begin(); i != a_loops_grouped.end(); ++i) {
- V2Set::iterator it_end = (*i).perimeter.end();
- V2Set::iterator it_begin = (*i).perimeter.begin();
-
- if(it_begin != it_end) {
- a_map[std::min_element(it_begin, it_end)->first].push_back(i);
- }
- }
-
- for (i = b_loops_grouped.begin(); i != b_loops_grouped.end();) {
- GroupLookup::iterator a = a_map.end();
-
- V2Set::iterator it_end = (*i).perimeter.end();
- V2Set::iterator it_begin = (*i).perimeter.begin();
-
- if(it_begin != it_end) {
- a = a_map.find(std::min_element(it_begin, it_end)->first);
- }
-
- if (a == a_map.end()) { ++i; continue; }
-
- for (std::list<FLGroupList::iterator>::iterator ji = (*a).second.begin(), je = (*a).second.end(); ji != je; ++ji) {
- j = (*ji);
- if (isSameFwd((*i).perimeter, (*j).perimeter)) {
-#if defined(CARVE_DEBUG)
- std::cerr << "SAME FWD PAIR" << std::endl;
-#endif
- fc = FACE_ON_ORIENT_OUT;
- goto face_pair;
- } else if (isSameRev((*i).perimeter, (*j).perimeter)) {
-#if defined(CARVE_DEBUG)
- std::cerr << "SAME REV PAIR" << std::endl;
-#endif
- fc = FACE_ON_ORIENT_IN;
- goto face_pair;
- }
- }
- ++i;
- continue;
-
- face_pair: {
- V2Set::iterator it_end = (*j).perimeter.end();
- V2Set::iterator it_begin = (*j).perimeter.begin();
-
- if(it_begin != it_end) {
- a_map[std::min_element(it_begin, it_end)->first].remove(j);
- }
-
- (*i).classification.push_back(ClassificationInfo(NULL, fc));
- (*j).classification.push_back(ClassificationInfo(NULL, fc));
-
- collector.collect(&*i, hooks);
- collector.collect(&*j, hooks);
-
- j = a_loops_grouped.erase(j);
- i = b_loops_grouped.erase(i);
- }
- }
- }
-
- // XXX: this may leave some face groups that are IN or OUT, and
- // consist of a single face loop.
- classifier.postRemovalCheck(a_loops_grouped, b_loops_grouped);
-
- classifier.faceLoopWork(a_loops_grouped, b_loops_grouped, vclass, poly_a, poly_a_rtree, poly_b, poly_b_rtree);
-
- classifier.finish(a_loops_grouped, b_loops_grouped);
- }
-
- }
-}
diff --git a/extern/carve/lib/intersect_classify_edge.cpp b/extern/carve/lib/intersect_classify_edge.cpp
deleted file mode 100644
index 23cfa21b643..00000000000
--- a/extern/carve/lib/intersect_classify_edge.cpp
+++ /dev/null
@@ -1,823 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#if defined(HAVE_STDINT_H)
-#include <stdint.h>
-#endif
-
-#include <carve/csg.hpp>
-#include <carve/debug_hooks.hpp>
-#include <carve/colour.hpp>
-
-#include <list>
-#include <set>
-#include <iostream>
-
-#include <algorithm>
-
-#include "csg_detail.hpp"
-
-#include "intersect_common.hpp"
-#include "intersect_classify_common.hpp"
-
-#define ANGLE_EPSILON 1e-6
-
-namespace carve {
- namespace csg {
-
- namespace {
-
- inline bool single_bit_set(uint32_t v) {
- v &= v - 1;
- return v == 0;
- }
-
- struct EdgeSurface {
- FaceLoop *fwd;
- double fwd_ang;
- FaceLoop *rev;
- double rev_ang;
-
- EdgeSurface() : fwd(NULL), fwd_ang(0.0), rev(NULL), rev_ang(0.0) { }
- };
-
-
- typedef std::map<const carve::mesh::MeshSet<3>::mesh_t *, EdgeSurface> GrpEdgeSurfMap;
-
- typedef std::pair<FaceLoopGroup *, const carve::mesh::MeshSet<3>::mesh_t *> ClassificationKey;
-
- struct ClassificationData {
- uint32_t class_bits : 5;
- uint32_t class_decided : 1;
-
- int c[5];
-
- ClassificationData() {
- class_bits = FACE_ANY_BIT;
- class_decided = 0;
- memset(c, 0, sizeof(c));
- }
- };
-
- struct hash_classification {
- size_t operator()(const ClassificationKey &f) const {
- return (size_t)f.first ^ (size_t)f.second;
- }
- };
-
- typedef std::unordered_map<ClassificationKey, ClassificationData, hash_classification> Classification;
-
-
- struct hash_group_ptr {
- size_t operator()(const FaceLoopGroup * const &f) const {
- return (size_t)f;
- }
- };
-
-
- typedef std::pair<size_t, const carve::mesh::MeshSet<3>::vertex_t *> PerimKey;
-
- struct hash_perim_key {
- size_t operator()(const PerimKey &v) const {
- return (size_t)v.first ^ (size_t)v.second;
- }
- };
-
- typedef std::unordered_map<std::pair<size_t, const carve::mesh::MeshSet<3>::vertex_t *>,
- std::unordered_set<FaceLoopGroup *, hash_group_ptr>,
- hash_perim_key> PerimMap;
-
-
-
- struct hash_group_pair {
- size_t operator()(const std::pair<int, const FaceLoopGroup *> &v) const {
- return (size_t)v.first ^ (size_t)v.second;
- }
- };
-
- typedef std::unordered_map<const FaceLoopGroup *,
- std::unordered_set<std::pair<int, const FaceLoopGroup *>, hash_group_pair>,
- hash_group_ptr> CandidateOnMap;
-
-
-
- static inline void remove(carve::mesh::MeshSet<3>::vertex_t *a,
- carve::mesh::MeshSet<3>::vertex_t *b,
- carve::csg::detail::VVSMap &shared_edge_graph) {
- carve::csg::detail::VVSMap::iterator i = shared_edge_graph.find(a);
- CARVE_ASSERT(i != shared_edge_graph.end());
- size_t n = (*i).second.erase(b);
- CARVE_ASSERT(n == 1);
- if ((*i).second.size() == 0) shared_edge_graph.erase(i);
- }
-
-
-
- static inline void remove(V2 edge,
- carve::csg::detail::VVSMap &shared_edge_graph) {
- remove(edge.first, edge.second, shared_edge_graph);
- remove(edge.second, edge.first, shared_edge_graph);
- }
-
-
-
-#if 0
- static void walkGraphSegment(carve::csg::detail::VVSMap &shared_edge_graph,
- const carve::csg::detail::VSet &branch_points,
- V2 initial,
- const carve::csg::detail::LoopEdges & /* a_edge_map */,
- const carve::csg::detail::LoopEdges & /* b_edge_map */,
- std::list<V2> &out) {
- V2 curr;
- curr = initial;
- bool closed = false;
-
- out.clear();
- for (;;) {
- // walk forward.
- out.push_back(curr);
- remove(curr, shared_edge_graph);
-
- if (curr.second == initial.first) { closed = true; break; }
- if (branch_points.find(curr.second) != branch_points.end()) break;
- carve::csg::detail::VVSMap::const_iterator o = shared_edge_graph.find(curr.second);
- if (o == shared_edge_graph.end()) break;
- CARVE_ASSERT((*o).second.size() == 1);
- curr.first = curr.second;
- curr.second = *((*o).second.begin());
- // test here that the set of incident groups hasn't changed.
- }
-
- if (!closed) {
- // walk backward.
- curr = initial;
- for (;;) {
- if (branch_points.find(curr.first) != branch_points.end()) break;
- carve::csg::detail::VVSMap::const_iterator o = shared_edge_graph.find(curr.first);
- if (o == shared_edge_graph.end()) break;
- curr.second = curr.first;
- curr.first = *((*o).second.begin());
- // test here that the set of incident groups hasn't changed.
-
- out.push_front(curr);
- remove(curr, shared_edge_graph);
- }
- }
-
-#if defined(CARVE_DEBUG)
- std::cerr << "intersection segment: " << out.size() << " edges." << std::endl;
-#if defined(DEBUG_DRAW_INTERSECTION_LINE)
- {
- static float H = 0.0, S = 1.0, V = 1.0;
- float r, g, b;
-
- H = fmod((H + .37), 1.0);
- S = 0.5 + fmod((S - 0.37), 0.5);
- carve::colour::HSV2RGB(H, S, V, r, g, b);
-
- if (out.size() > 1) {
- drawEdges(out.begin(), ++out.begin(),
- 0.0, 0.0, 0.0, 1.0,
- r, g, b, 1.0,
- 3.0);
- drawEdges(++out.begin(), --out.end(),
- r, g, b, 1.0,
- r, g, b, 1.0,
- 3.0);
- drawEdges(--out.end(), out.end(),
- r, g, b, 1.0,
- 1.0, 1.0, 1.0, 1.0,
- 3.0);
- } else {
- drawEdges(out.begin(), out.end(),
- r, g, b, 1.0,
- r, g, b, 1.0,
- 3.0);
- }
- }
-#endif
-#endif
- }
-#endif
-
-
- static carve::geom3d::Vector perpendicular(const carve::geom3d::Vector &v) {
- if (fabs(v.x) < fabs(v.y)) {
- if (fabs(v.x) < fabs(v.z)) {
- return cross(v, carve::geom::VECTOR(1.0, 0.0, 0.0)).normalized();
- } else {
- return cross(v, carve::geom::VECTOR(0.0, 0.0, 1.0)).normalized();
- }
- } else {
- if (fabs(v.y) < fabs(v.z)) {
- return cross(v, carve::geom::VECTOR(0.0, 1.0, 0.0)).normalized();
- } else {
- return cross(v, carve::geom::VECTOR(1.0, 0.0, 1.0)).normalized();
- }
- }
- }
-
-
-
- static void classifyAB(const GrpEdgeSurfMap &a_edge_surfaces,
- const GrpEdgeSurfMap &b_edge_surfaces,
- Classification &classifications) {
- // two faces in the a surface
- for (GrpEdgeSurfMap::const_iterator ib = b_edge_surfaces.begin(), eb = b_edge_surfaces.end(); ib != eb; ++ib) {
-
- if ((*ib).second.fwd) {
- FaceLoopGroup *b_grp = ((*ib).second.fwd->group);
-
- for (GrpEdgeSurfMap::const_iterator ia = a_edge_surfaces.begin(), ea = a_edge_surfaces.end(); ia != ea; ++ia) {
-
- if ((*ia).second.fwd && (*ia).second.rev) {
- const carve::mesh::MeshSet<3>::mesh_t *a_gid = (*ia).first;
-
- ClassificationData &data = classifications[std::make_pair(b_grp, a_gid)];
- if (data.class_decided) continue;
-
- // an angle between (*ia).fwd_ang and (*ia).rev_ang is outside/above group a.
- FaceClass fc;
-
- if (fabs((*ib).second.fwd_ang - (*ia).second.fwd_ang) < ANGLE_EPSILON) {
- fc = FACE_ON_ORIENT_OUT;
- } else if (fabs((*ib).second.fwd_ang - (*ia).second.rev_ang) < ANGLE_EPSILON) {
- fc = FACE_ON_ORIENT_IN;
- } else {
- double a1 = (*ia).second.fwd_ang;
- double a2 = (*ia).second.rev_ang;
- if (a1 < a2) {
- if (a1 < (*ib).second.fwd_ang && (*ib).second.fwd_ang < a2) {
- fc = FACE_IN;
- } else {
- fc = FACE_OUT;
- }
- } else {
- if (a2 < (*ib).second.fwd_ang && (*ib).second.fwd_ang < a1) {
- fc = FACE_OUT;
- } else {
- fc = FACE_IN;
- }
- }
- }
- data.c[fc + 2]++;
- }
- }
- }
-
- if ((*ib).second.rev) {
- FaceLoopGroup *b_grp = ((*ib).second.rev->group);
-
- for (GrpEdgeSurfMap::const_iterator ia = a_edge_surfaces.begin(), ea = a_edge_surfaces.end(); ia != ea; ++ia) {
-
- if ((*ia).second.fwd && (*ia).second.rev) {
- const carve::mesh::MeshSet<3>::mesh_t *a_gid = (*ia).first;
-
- ClassificationData &data = (classifications[std::make_pair(b_grp, a_gid)]);
- if (data.class_decided) continue;
-
- // an angle between (*ia).fwd_ang and (*ia).rev_ang is outside/above group a.
- FaceClass fc;
-
- if (fabs((*ib).second.rev_ang - (*ia).second.fwd_ang) < ANGLE_EPSILON) {
- fc = FACE_ON_ORIENT_IN;
- } else if (fabs((*ib).second.rev_ang - (*ia).second.rev_ang) < ANGLE_EPSILON) {
- fc = FACE_ON_ORIENT_OUT;
- } else {
- double a1 = (*ia).second.fwd_ang;
- double a2 = (*ia).second.rev_ang;
- if (a1 < a2) {
- if (a1 < (*ib).second.rev_ang && (*ib).second.rev_ang < a2) {
- fc = FACE_IN;
- } else {
- fc = FACE_OUT;
- }
- } else {
- if (a2 < (*ib).second.rev_ang && (*ib).second.rev_ang < a1) {
- fc = FACE_OUT;
- } else {
- fc = FACE_IN;
- }
- }
- }
- data.c[fc + 2]++;
- }
- }
- }
- }
- }
-
-
- static bool processForwardEdgeSurfaces(GrpEdgeSurfMap &edge_surfaces,
- const std::list<FaceLoop *> &fwd,
- const carve::geom3d::Vector &edge_vector,
- const carve::geom3d::Vector &base_vector) {
- for (std::list<FaceLoop *>::const_iterator i = fwd.begin(), e = fwd.end(); i != e; ++i) {
- EdgeSurface &es = (edge_surfaces[(*i)->orig_face->mesh]);
- if (es.fwd != NULL) return false;
- es.fwd = (*i);
- es.fwd_ang = carve::geom3d::antiClockwiseAngle((*i)->orig_face->plane.N, base_vector, edge_vector);
- }
- return true;
- }
-
- static bool processReverseEdgeSurfaces(GrpEdgeSurfMap &edge_surfaces,
- const std::list<FaceLoop *> &rev,
- const carve::geom3d::Vector &edge_vector,
- const carve::geom3d::Vector &base_vector) {
- for (std::list<FaceLoop *>::const_iterator i = rev.begin(), e = rev.end(); i != e; ++i) {
- EdgeSurface &es = (edge_surfaces[(*i)->orig_face->mesh]);
- if (es.rev != NULL) return false;
- es.rev = (*i);
- es.rev_ang = carve::geom3d::antiClockwiseAngle(-(*i)->orig_face->plane.N, base_vector, edge_vector);
- }
- return true;
- }
-
-
-
- static void processOneEdge(const V2 &edge,
- const carve::csg::detail::LoopEdges &a_edge_map,
- const carve::csg::detail::LoopEdges &b_edge_map,
- Classification &a_classification,
- Classification &b_classification) {
- GrpEdgeSurfMap a_edge_surfaces;
- GrpEdgeSurfMap b_edge_surfaces;
-
- carve::geom3d::Vector edge_vector = (edge.second->v - edge.first->v).normalized();
- carve::geom3d::Vector base_vector = perpendicular(edge_vector);
-
- carve::csg::detail::LoopEdges::const_iterator ae_f = a_edge_map.find(edge);
- carve::csg::detail::LoopEdges::const_iterator ae_r = a_edge_map.find(flip(edge));
- CARVE_ASSERT(ae_f != a_edge_map.end() || ae_r != a_edge_map.end());
-
- carve::csg::detail::LoopEdges::const_iterator be_f = b_edge_map.find(edge);
- carve::csg::detail::LoopEdges::const_iterator be_r = b_edge_map.find(flip(edge));
- CARVE_ASSERT(be_f != b_edge_map.end() || be_r != b_edge_map.end());
-
- if (ae_f != a_edge_map.end() && !processForwardEdgeSurfaces(a_edge_surfaces, (*ae_f).second, edge_vector, base_vector)) return;
- if (ae_r != a_edge_map.end() && !processReverseEdgeSurfaces(a_edge_surfaces, (*ae_r).second, edge_vector, base_vector)) return;
- if (be_f != b_edge_map.end() && !processForwardEdgeSurfaces(b_edge_surfaces, (*be_f).second, edge_vector, base_vector)) return;
- if (be_r != b_edge_map.end() && !processReverseEdgeSurfaces(b_edge_surfaces, (*be_r).second, edge_vector, base_vector)) return;
-
- classifyAB(a_edge_surfaces, b_edge_surfaces, b_classification);
- classifyAB(b_edge_surfaces, a_edge_surfaces, a_classification);
- }
-
-
-
-#if 0
- static void traceIntersectionGraph(const V2Set &shared_edges,
- const FLGroupList & /* a_loops_grouped */,
- const FLGroupList & /* b_loops_grouped */,
- const carve::csg::detail::LoopEdges &a_edge_map,
- const carve::csg::detail::LoopEdges &b_edge_map) {
-
- carve::csg::detail::VVSMap shared_edge_graph;
- carve::csg::detail::VSet branch_points;
-
- // first, make the intersection graph.
- for (V2Set::const_iterator i = shared_edges.begin(); i != shared_edges.end(); ++i) {
- const V2Set::key_type &edge = (*i);
- carve::csg::detail::VVSMap::mapped_type &out = (shared_edge_graph[edge.first]);
- out.insert(edge.second);
- if (out.size() == 3) branch_points.insert(edge.first);
-
-#if defined(CARVE_DEBUG) && defined(DEBUG_DRAW_INTERSECTION_LINE)
- HOOK(drawEdge(edge.first, edge.second, 1, 1, 1, 1, 1, 1, 1, 1, 1.0););
-#endif
- }
-#if defined(CARVE_DEBUG)
- std::cerr << "graph nodes: " << shared_edge_graph.size() << std::endl;
- std::cerr << "branch nodes: " << branch_points.size() << std::endl;
-#endif
-
- std::list<V2> out;
- while (shared_edge_graph.size()) {
- carve::csg::detail::VVSMap::iterator i = shared_edge_graph.begin();
- carve::mesh::MeshSet<3>::vertex_t *v1 = (*i).first;
- carve::mesh::MeshSet<3>::vertex_t *v2 = *((*i).second.begin());
- walkGraphSegment(shared_edge_graph, branch_points, V2(v1, v2), a_edge_map, b_edge_map, out);
- }
- }
-#endif
-
- void hashByPerimeter(FLGroupList &grp, PerimMap &perim_map) {
- for (FLGroupList::iterator i = grp.begin(); i != grp.end(); ++i) {
- size_t perim_size = (*i).perimeter.size();
- // can be the case for non intersecting groups. (and groups that intersect at a point?)
- if (!perim_size) continue;
- const carve::mesh::MeshSet<3>::vertex_t *perim_min = std::min_element((*i).perimeter.begin(), (*i).perimeter.end())->first;
- perim_map[std::make_pair(perim_size, perim_min)].insert(&(*i));
- }
- }
-
-
-
- bool same_edge_set_fwd(const V2Set &a, const V2Set &b) {
- if (a.size() != b.size()) return false;
- for (V2Set::const_iterator i = a.begin(), e = a.end(); i != e; ++i) {
- if (b.find(*i) == b.end()) return false;
- }
- return true;
- }
-
-
-
- bool same_edge_set_rev(const V2Set &a, const V2Set &b) {
- if (a.size() != b.size()) return false;
- for (V2Set::const_iterator i = a.begin(), e = a.end(); i != e; ++i) {
- if (b.find(std::make_pair((*i).second, (*i).first)) == b.end()) return false;
- }
- return true;
- }
-
-
-
- int same_edge_set(const V2Set &a, const V2Set &b) {
- if (same_edge_set_fwd(a, b)) return +1;
- if (same_edge_set_rev(a, b)) return -1;
- return 0;
- }
-
-
-
- void generateCandidateOnSets(FLGroupList &a_grp,
- FLGroupList &b_grp,
- CandidateOnMap &candidate_on_map,
- Classification &a_classification,
- Classification &b_classification) {
- PerimMap a_grp_by_perim, b_grp_by_perim;
-
- hashByPerimeter(a_grp, a_grp_by_perim);
- hashByPerimeter(b_grp, b_grp_by_perim);
-
- for (PerimMap::iterator i = a_grp_by_perim.begin(), ie = a_grp_by_perim.end(); i != ie; ++i) {
- PerimMap::iterator j = b_grp_by_perim.find((*i).first);
- if (j == b_grp_by_perim.end()) continue;
-
- for (PerimMap::mapped_type::iterator a = (*i).second.begin(), ae = (*i).second.end(); a != ae; ++a) {
- for (PerimMap::mapped_type::iterator b = (*j).second.begin(), be = (*j).second.end(); b != be; ++b) {
- int x = same_edge_set((*a)->perimeter, (*b)->perimeter);
- if (!x) continue;
- candidate_on_map[(*a)].insert(std::make_pair(x, (*b)));
- if ((*a)->face_loops.count == 1 && (*b)->face_loops.count == 1) {
- uint32_t fcb = x == +1 ? FACE_ON_ORIENT_OUT_BIT : FACE_ON_ORIENT_IN_BIT;
-
-#if defined(CARVE_DEBUG)
- std::cerr << "paired groups: " << (*a) << ", " << (*b) << std::endl;
-#endif
-
- ClassificationData &a_data = a_classification[std::make_pair((*a), (*b)->face_loops.head->orig_face->mesh)];
- a_data.class_bits = fcb; a_data.class_decided = 1;
-
- ClassificationData &b_data = b_classification[std::make_pair((*b), (*a)->face_loops.head->orig_face->mesh)];
- b_data.class_bits = fcb; b_data.class_decided = 1;
- }
- }
- }
- }
- }
-
- }
-
-
- static inline std::string CODE(const FaceLoopGroup *grp) {
- const std::list<ClassificationInfo> &cinfo = (grp->classification);
- if (cinfo.size() == 0) {
- return "?";
- }
-
- FaceClass fc = FACE_UNCLASSIFIED;
-
- for (std::list<ClassificationInfo>::const_iterator i = grp->classification.begin(), e = grp->classification.end(); i != e; ++i) {
- if ((*i).intersected_mesh == NULL) {
- // classifier only returns global info
- fc = (*i).classification;
- break;
- }
-
- if ((*i).intersectedMeshIsClosed()) {
- if ((*i).classification == FACE_UNCLASSIFIED) continue;
- if (fc == FACE_UNCLASSIFIED) {
- fc = (*i).classification;
- } else if (fc != (*i).classification) {
- return "X";
- }
- }
- }
- if (fc == FACE_IN) return "I";
- if (fc == FACE_ON_ORIENT_IN) return "<";
- if (fc == FACE_ON_ORIENT_OUT) return ">";
- if (fc == FACE_OUT) return "O";
- return "*";
- }
-
- void CSG::classifyFaceGroupsEdge(const V2Set &shared_edges,
- VertexClassification &vclass,
- carve::mesh::MeshSet<3> *poly_a,
- const face_rtree_t *poly_a_rtree,
- FLGroupList &a_loops_grouped,
- const detail::LoopEdges &a_edge_map,
- carve::mesh::MeshSet<3> *poly_b,
- const face_rtree_t *poly_b_rtree,
- FLGroupList &b_loops_grouped,
- const detail::LoopEdges &b_edge_map,
- CSG::Collector &collector) {
- Classification a_classification;
- Classification b_classification;
-
- CandidateOnMap candidate_on_map;
-
-#if defined(CARVE_DEBUG)
- std::cerr << "a input loops (" << a_loops_grouped.size() << "): ";
- for (FLGroupList::iterator i = a_loops_grouped.begin(); i != a_loops_grouped.end(); ++i) {
- std::cerr << &*i << " ";
- }
- std::cerr << std::endl;
- std::cerr << "b input loops (" << b_loops_grouped.size() << "): ";
- for (FLGroupList::iterator i = b_loops_grouped.begin(); i != b_loops_grouped.end(); ++i) {
- std::cerr << &*i << " ";
- }
- std::cerr << std::endl;
-#endif
-
-#if defined(DISPLAY_GRP_GRAPH)
- // XXX: this is hopelessly inefficient.
- std::map<const FaceLoopGroup *, std::set<const FaceLoopGroup *> > grp_graph_fwd, grp_graph_rev;
- {
- for (FLGroupList::iterator i = a_loops_grouped.begin(); i != a_loops_grouped.end(); ++i) {
- FaceLoopGroup *src = &(*i);
- for (V2Set::const_iterator k = src->perimeter.begin(); k != src->perimeter.end(); ++k) {
- V2 fwd = *k;
- V2 rev = std::make_pair(fwd.second, fwd.first);
- for (FLGroupList::iterator j = a_loops_grouped.begin(); j != a_loops_grouped.end(); ++j) {
- FaceLoopGroup *tgt = &(*j);
- if (tgt->perimeter.find(fwd) != tgt->perimeter.end()) { grp_graph_fwd[src].insert(tgt); }
- if (tgt->perimeter.find(rev) != tgt->perimeter.end()) { grp_graph_rev[src].insert(tgt); }
- }
- for (FLGroupList::iterator j = b_loops_grouped.begin(); j != b_loops_grouped.end(); ++j) {
- FaceLoopGroup *tgt = &(*j);
- if (tgt->perimeter.find(fwd) != tgt->perimeter.end()) { grp_graph_fwd[src].insert(tgt); }
- if (tgt->perimeter.find(rev) != tgt->perimeter.end()) { grp_graph_rev[src].insert(tgt); }
- }
- }
- }
- for (FLGroupList::iterator i = b_loops_grouped.begin(); i != b_loops_grouped.end(); ++i) {
- FaceLoopGroup *src = &(*i);
- for (V2Set::const_iterator k = src->perimeter.begin(); k != src->perimeter.end(); ++k) {
- V2 fwd = *k;
- V2 rev = std::make_pair(fwd.second, fwd.first);
- for (FLGroupList::iterator j = a_loops_grouped.begin(); j != a_loops_grouped.end(); ++j) {
- FaceLoopGroup *tgt = &(*j);
- if (tgt->perimeter.find(fwd) != tgt->perimeter.end()) { grp_graph_fwd[src].insert(tgt); }
- if (tgt->perimeter.find(rev) != tgt->perimeter.end()) { grp_graph_rev[src].insert(tgt); }
- }
- for (FLGroupList::iterator j = b_loops_grouped.begin(); j != b_loops_grouped.end(); ++j) {
- FaceLoopGroup *tgt = &(*j);
- if (tgt->perimeter.find(fwd) != tgt->perimeter.end()) { grp_graph_fwd[src].insert(tgt); }
- if (tgt->perimeter.find(rev) != tgt->perimeter.end()) { grp_graph_rev[src].insert(tgt); }
- }
- }
- }
- }
-#endif
-
- generateCandidateOnSets(a_loops_grouped, b_loops_grouped, candidate_on_map, a_classification, b_classification);
-
-
- for (V2Set::const_iterator i = shared_edges.begin(); i != shared_edges.end(); ++i) {
- const V2 &edge = (*i);
- processOneEdge(edge, a_edge_map, b_edge_map, a_classification, b_classification);
- }
-
-
- for (Classification::iterator i = a_classification.begin(), e = a_classification.end(); i != e; ++i) {
- if (!(*i).second.class_decided) {
- if ((*i).second.c[FACE_IN + 2] == 0) (*i).second.class_bits &= ~ FACE_IN_BIT;
- if ((*i).second.c[FACE_ON_ORIENT_IN + 2] == 0) (*i).second.class_bits &= ~ FACE_ON_ORIENT_IN_BIT;
- if ((*i).second.c[FACE_ON_ORIENT_OUT + 2] == 0) (*i).second.class_bits &= ~ FACE_ON_ORIENT_OUT_BIT;
- if ((*i).second.c[FACE_OUT + 2] == 0) (*i).second.class_bits &= ~ FACE_OUT_BIT;
-
- // XXX: this is the wrong thing to do. It's intended just as a test.
- if ((*i).second.class_bits == (FACE_IN_BIT | FACE_OUT_BIT)) {
- if ((*i).second.c[FACE_OUT + 2] > (*i).second.c[FACE_IN + 2]) {
- (*i).second.class_bits = FACE_OUT_BIT;
- } else {
- (*i).second.class_bits = FACE_IN_BIT;
- }
- }
-
- if (single_bit_set((*i).second.class_bits)) (*i).second.class_decided = 1;
- }
- }
-
- for (Classification::iterator i = b_classification.begin(), e = b_classification.end(); i != e; ++i) {
- if (!(*i).second.class_decided) {
- if ((*i).second.c[FACE_IN + 2] == 0) (*i).second.class_bits &= ~ FACE_IN_BIT;
- if ((*i).second.c[FACE_ON_ORIENT_IN + 2] == 0) (*i).second.class_bits &= ~ FACE_ON_ORIENT_IN_BIT;
- if ((*i).second.c[FACE_ON_ORIENT_OUT + 2] == 0) (*i).second.class_bits &= ~ FACE_ON_ORIENT_OUT_BIT;
- if ((*i).second.c[FACE_OUT + 2] == 0) (*i).second.class_bits &= ~ FACE_OUT_BIT;
-
- // XXX: this is the wrong thing to do. It's intended just as a test.
- if ((*i).second.class_bits == (FACE_IN_BIT | FACE_OUT_BIT)) {
- if ((*i).second.c[FACE_OUT + 2] > (*i).second.c[FACE_IN + 2]) {
- (*i).second.class_bits = FACE_OUT_BIT;
- } else {
- (*i).second.class_bits = FACE_IN_BIT;
- }
- }
-
- if (single_bit_set((*i).second.class_bits)) (*i).second.class_decided = 1;
- }
- }
-
-
-#if defined(CARVE_DEBUG)
- std::cerr << "poly a:" << std::endl;
- for (Classification::iterator i = a_classification.begin(), e = a_classification.end(); i != e; ++i) {
- FaceLoopGroup *grp = ((*i).first.first);
-
- std::cerr << " group: " << grp << " gid: " << (*i).first.second
- << " "
- << ((*i).second.class_decided ? "+" : "-")
- << " "
- << ((*i).second.class_bits & FACE_IN_BIT ? "I" : ".")
- << ((*i).second.class_bits & FACE_ON_ORIENT_IN_BIT ? "<" : ".")
- << ((*i).second.class_bits & FACE_ON_ORIENT_OUT_BIT ? ">" : ".")
- << ((*i).second.class_bits & FACE_OUT_BIT ? "O" : ".")
- << " ["
- << std::setw(4) << (*i).second.c[0] << " "
- << std::setw(4) << (*i).second.c[1] << " "
- << std::setw(4) << (*i).second.c[2] << " "
- << std::setw(4) << (*i).second.c[3] << " "
- << std::setw(4) << (*i).second.c[4] << "]" << std::endl;
- }
-
- std::cerr << "poly b:" << std::endl;
- for (Classification::iterator i = b_classification.begin(), e = b_classification.end(); i != e; ++i) {
- FaceLoopGroup *grp = ((*i).first.first);
-
- std::cerr << " group: " << grp << " gid: " << (*i).first.second
- << " "
- << ((*i).second.class_decided ? "+" : "-")
- << " "
- << ((*i).second.class_bits & FACE_IN_BIT ? "I" : ".")
- << ((*i).second.class_bits & FACE_ON_ORIENT_IN_BIT ? "<" : ".")
- << ((*i).second.class_bits & FACE_ON_ORIENT_OUT_BIT ? ">" : ".")
- << ((*i).second.class_bits & FACE_OUT_BIT ? "O" : ".")
- << " ["
- << std::setw(4) << (*i).second.c[0] << " "
- << std::setw(4) << (*i).second.c[1] << " "
- << std::setw(4) << (*i).second.c[2] << " "
- << std::setw(4) << (*i).second.c[3] << " "
- << std::setw(4) << (*i).second.c[4] << "]" << std::endl;
- }
-#endif
-
- for (Classification::iterator i = a_classification.begin(), e = a_classification.end(); i != e; ++i) {
- FaceLoopGroup *grp = ((*i).first.first);
-
- grp->classification.push_back(ClassificationInfo());
- ClassificationInfo &info = grp->classification.back();
-
- info.intersected_mesh = (*i).first.second;
-
- if ((*i).second.class_decided) {
- info.classification = class_bit_to_class((*i).second.class_bits);
- } else {
- info.classification = FACE_UNCLASSIFIED;
- }
- }
-
- for (Classification::iterator i = b_classification.begin(), e = b_classification.end(); i != e; ++i) {
- FaceLoopGroup *grp = ((*i).first.first);
-
- grp->classification.push_back(ClassificationInfo());
- ClassificationInfo &info = grp->classification.back();
-
- info.intersected_mesh = (*i).first.second;
-
- if ((*i).second.class_decided) {
- info.classification = class_bit_to_class((*i).second.class_bits);
- } else {
- info.classification = FACE_UNCLASSIFIED;
- }
- }
-
- for (FLGroupList::iterator i = a_loops_grouped.begin(); i != a_loops_grouped.end(); ++i) {
- if ((*i).classification.size() == 0) {
-#if defined(CARVE_DEBUG)
- std::cerr << " non intersecting group (poly a): " << &(*i) << std::endl;
-#endif
- bool classified = false;
- for (FaceLoop *fl = (*i).face_loops.head; !classified && fl != NULL; fl = fl->next) {
- for (size_t fli = 0; !classified && fli < fl->vertices.size(); ++fli) {
- if (vclass[fl->vertices[fli]].cls[1] == POINT_UNK) {
- vclass[fl->vertices[fli]].cls[1] = carve::mesh::classifyPoint(poly_b, poly_b_rtree, fl->vertices[fli]->v);
- }
- switch (vclass[fl->vertices[fli]].cls[1]) {
- case POINT_IN:
- (*i).classification.push_back(ClassificationInfo(NULL, FACE_IN));
- classified = true;
- break;
- case POINT_OUT:
- (*i).classification.push_back(ClassificationInfo(NULL, FACE_OUT));
- classified = true;
- break;
- default:
- break;
- }
- }
- }
- if (!classified) {
- throw carve::exception("non intersecting group is not IN or OUT! (poly_a)");
- }
- }
- }
-
- for (FLGroupList::iterator i = b_loops_grouped.begin(); i != b_loops_grouped.end(); ++i) {
- if ((*i).classification.size() == 0) {
-#if defined(CARVE_DEBUG)
- std::cerr << " non intersecting group (poly b): " << &(*i) << std::endl;
-#endif
- bool classified = false;
- for (FaceLoop *fl = (*i).face_loops.head; !classified && fl != NULL; fl = fl->next) {
- for (size_t fli = 0; !classified && fli < fl->vertices.size(); ++fli) {
- if (vclass[fl->vertices[fli]].cls[0] == POINT_UNK) {
- vclass[fl->vertices[fli]].cls[0] = carve::mesh::classifyPoint(poly_a, poly_a_rtree, fl->vertices[fli]->v);
- }
- switch (vclass[fl->vertices[fli]].cls[0]) {
- case POINT_IN:
- (*i).classification.push_back(ClassificationInfo(NULL, FACE_IN));
- classified = true;
- break;
- case POINT_OUT:
- (*i).classification.push_back(ClassificationInfo(NULL, FACE_OUT));
- classified = true;
- break;
- default:
- break;
- }
- }
- }
- if (!classified) {
- throw carve::exception("non intersecting group is not IN or OUT! (poly_b)");
- }
- }
- }
-
-#if defined(DISPLAY_GRP_GRAPH)
-#define POLY(grp) (std::string((grp)->face_loops.head->orig_face->polyhedron == poly_a ? "[A:" : "[B:") + CODE(grp) + "]")
-
- for (std::map<const FaceLoopGroup *, std::set<const FaceLoopGroup *> >::iterator i = grp_graph_fwd.begin(); i != grp_graph_fwd.end(); ++i) {
- const FaceLoopGroup *grp = (*i).first;
-
- std::cerr << "GRP: " << grp << POLY(grp) << std::endl;
-
- std::set<const FaceLoopGroup *> &fwd_set = grp_graph_fwd[grp];
- std::set<const FaceLoopGroup *> &rev_set = grp_graph_rev[grp];
- std::cerr << " FWD: ";
- for (std::set<const FaceLoopGroup *>::const_iterator j = fwd_set.begin(); j != fwd_set.end(); ++j) {
- std::cerr << " " << (*j) << POLY(*j);
- }
- std::cerr << std::endl;
- std::cerr << " REV: ";
- for (std::set<const FaceLoopGroup *>::const_iterator j = rev_set.begin(); j != rev_set.end(); ++j) {
- std::cerr << " " << (*j) << POLY(*j);
- }
- std::cerr << std::endl;
- }
-#endif
-
- for (FLGroupList::iterator i = a_loops_grouped.begin(); i != a_loops_grouped.end(); ++i) {
- collector.collect(&*i, hooks);
- }
-
- for (FLGroupList::iterator i = b_loops_grouped.begin(); i != b_loops_grouped.end(); ++i) {
- collector.collect(&*i, hooks);
- }
-
- // traceIntersectionGraph(shared_edges, a_loops_grouped, b_loops_grouped, a_edge_map, b_edge_map);
- }
-
- }
-}
diff --git a/extern/carve/lib/intersect_classify_group.cpp b/extern/carve/lib/intersect_classify_group.cpp
deleted file mode 100644
index b1b19a2eb15..00000000000
--- a/extern/carve/lib/intersect_classify_group.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/csg.hpp>
-#include <carve/debug_hooks.hpp>
-
-#include <list>
-#include <set>
-#include <iostream>
-
-#include <algorithm>
-
-#include "intersect_common.hpp"
-#include "intersect_classify_common.hpp"
-#include "intersect_classify_common_impl.hpp"
-
-
-namespace carve {
- namespace csg {
-
- namespace {
-
-#if defined(_MSC_VER) && _MSC_VER < 1300
- // VC++ 6.0 gets an internal compiler when compiling
- // the FaceMaker template. Not sure why but for now we just bypass
- // the template
- class FaceMaker0 {
- public:
- CSG::Collector &collector;
- CSG::Hooks &hooks;
-
- FaceMaker0(CSG::Collector &c, CSG::Hooks &h) : collector(c), hooks(h) {
- }
- bool pointOn(VertexClassification &vclass, FaceLoop *f, size_t index) const {
- return vclass[f->vertices[index]].cls[1] == POINT_ON;
- }
- void explain(FaceLoop *f, size_t index, PointClass pc) const {
-#if defined(CARVE_DEBUG)
- std::cerr << "face loop " << f << " from poly " << "ab"[0] << " is easy because vertex " << index << " (" << *f->vertices[index] << ") is " << ENUM(pc) << std::endl;
-#endif
- }
- };
- class FaceMaker1 {
- public:
- CSG::Collector &collector;
- CSG::Hooks &hooks;
-
- FaceMaker1(CSG::Collector &c, CSG::Hooks &h) : collector(c), hooks(h) {
- }
- bool pointOn(VertexClassification &vclass, FaceLoop *f, size_t index) const {
- return vclass[f->vertices[index]].cls[0] == POINT_ON;
- }
- void explain(FaceLoop *f, size_t index, PointClass pc) const {
-#if defined(CARVE_DEBUG)
- std::cerr << "face loop " << f << " from poly " << "ab"[1] << " is easy because vertex " << index << " (" << *f->vertices[index] << ") is " << ENUM(pc) << std::endl;
-#endif
- }
- };
-#else
- template <int poly_num>
- class FaceMaker {
- FaceMaker &operator=(const FaceMaker &);
-
- public:
- CSG::Collector &collector;
- CSG::Hooks &hooks;
-
- FaceMaker(CSG::Collector &c, CSG::Hooks &h) : collector(c), hooks(h) {
- }
-
- bool pointOn(VertexClassification &vclass, FaceLoop *f, size_t index) const {
- return vclass[f->vertices[index]].cls[1 - poly_num] == POINT_ON;
- }
-
- void explain(FaceLoop *f, size_t index, PointClass pc) const {
-#if defined(CARVE_DEBUG)
- std::cerr << "face loop " << f << " from poly " << "ab"[poly_num] << " is easy because vertex " << index << " (" << f->vertices[index]->v << ") is " << ENUM(pc) << std::endl;
-#endif
- }
- };
- typedef FaceMaker<0> FaceMaker0;
- typedef FaceMaker<1> FaceMaker1;
-#endif
- class ClassifyFaceGroups {
- ClassifyFaceGroups &operator=(const ClassifyFaceGroups &);
-
- public:
- CSG::Collector &collector;
- CSG::Hooks &hooks;
-
- ClassifyFaceGroups(CSG::Collector &c, CSG::Hooks &h) : collector(c), hooks(h) {
- }
-
- void classifySimple(FLGroupList &a_loops_grouped,
- FLGroupList &b_loops_grouped,
- VertexClassification & /* vclass */,
- carve::mesh::MeshSet<3> *poly_a,
- carve::mesh::MeshSet<3> *poly_b) const {
- if (a_loops_grouped.size() < b_loops_grouped.size()) {
- performClassifySimpleOnFaceGroups(a_loops_grouped, b_loops_grouped, poly_a, poly_b, collector, hooks);
- } else {
- performClassifySimpleOnFaceGroups(b_loops_grouped, a_loops_grouped, poly_b, poly_a, collector, hooks);
- }
-#if defined(CARVE_DEBUG)
- std::cerr << "after removal of simple on groups: " << a_loops_grouped.size() << " a groups" << std::endl;
- std::cerr << "after removal of simple on groups: " << b_loops_grouped.size() << " b groups" << std::endl;
-#endif
- }
-
- void classifyEasy(FLGroupList &a_loops_grouped,
- FLGroupList &b_loops_grouped,
- VertexClassification &vclass,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- carve::mesh::MeshSet<3> *poly_b,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_b_rtree) const {
- performClassifyEasyFaceGroups(a_loops_grouped, poly_b, poly_b_rtree, vclass, FaceMaker0(collector, hooks), collector, hooks);
- performClassifyEasyFaceGroups(b_loops_grouped, poly_a, poly_a_rtree, vclass, FaceMaker1(collector, hooks), collector, hooks);
-#if defined(CARVE_DEBUG)
- std::cerr << "after removal of easy groups: " << a_loops_grouped.size() << " a groups" << std::endl;
- std::cerr << "after removal of easy groups: " << b_loops_grouped.size() << " b groups" << std::endl;
-#endif
- }
-
- void classifyHard(FLGroupList &a_loops_grouped,
- FLGroupList &b_loops_grouped,
- VertexClassification & /* vclass */,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- carve::mesh::MeshSet<3> *poly_b,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_b_rtree) const {
- performClassifyHardFaceGroups(a_loops_grouped, poly_b, poly_b_rtree, FaceMaker0(collector, hooks), collector, hooks);
- performClassifyHardFaceGroups(b_loops_grouped, poly_a, poly_a_rtree, FaceMaker1(collector, hooks), collector, hooks);
-#if defined(CARVE_DEBUG)
- std::cerr << "after removal of hard groups: " << a_loops_grouped.size() << " a groups" << std::endl;
- std::cerr << "after removal of hard groups: " << b_loops_grouped.size() << " b groups" << std::endl;
-#endif
- }
-
- void faceLoopWork(FLGroupList &a_loops_grouped,
- FLGroupList &b_loops_grouped,
- VertexClassification & /* vclass */,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- carve::mesh::MeshSet<3> *poly_b,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_b_rtree) const {
- performFaceLoopWork(poly_b, poly_b_rtree, a_loops_grouped, *this, collector, hooks);
- performFaceLoopWork(poly_a, poly_a_rtree, b_loops_grouped, *this, collector, hooks);
- }
-
- void postRemovalCheck(FLGroupList &a_loops_grouped,
- FLGroupList &b_loops_grouped) const {
-#if defined(CARVE_DEBUG)
- std::cerr << "after removal of on groups: " << a_loops_grouped.size() << " a groups" << std::endl;
- std::cerr << "after removal of on groups: " << b_loops_grouped.size() << " b groups" << std::endl;
-#endif
- }
-
- bool faceLoopSanityChecker(FaceLoopGroup &i) const {
- return i.face_loops.size() != 1;
- }
-
- void finish(FLGroupList &a_loops_grouped,FLGroupList &b_loops_grouped) const {
-#if defined(CARVE_DEBUG)
- if (a_loops_grouped.size() || b_loops_grouped.size())
- std::cerr << "UNCLASSIFIED! a=" << a_loops_grouped.size() << ", b=" << b_loops_grouped.size() << std::endl;
-#endif
- }
- };
- }
-
- void CSG::classifyFaceGroups(const V2Set & /* shared_edges */,
- VertexClassification &vclass,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- FLGroupList &a_loops_grouped,
- const detail::LoopEdges & /* a_edge_map */,
- carve::mesh::MeshSet<3> *poly_b,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_b_rtree,
- FLGroupList &b_loops_grouped,
- const detail::LoopEdges & /* b_edge_map */,
- CSG::Collector &collector) {
- ClassifyFaceGroups classifier(collector, hooks);
-#if defined(CARVE_DEBUG)
- std::cerr << "initial groups: " << a_loops_grouped.size() << " a groups" << std::endl;
- std::cerr << "initial groups: " << b_loops_grouped.size() << " b groups" << std::endl;
-#endif
- performClassifyFaceGroups(
- a_loops_grouped,
- b_loops_grouped,
- vclass,
- poly_a,
- poly_a_rtree,
- poly_b,
- poly_b_rtree,
- classifier,
- collector,
- hooks);
- }
-
- }
-}
diff --git a/extern/carve/lib/intersect_common.hpp b/extern/carve/lib/intersect_common.hpp
deleted file mode 100644
index 3dea5932818..00000000000
--- a/extern/carve/lib/intersect_common.hpp
+++ /dev/null
@@ -1,83 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#pragma once
-
-
-static inline bool facesAreCoplanar(const carve::mesh::MeshSet<3>::face_t *a, const carve::mesh::MeshSet<3>::face_t *b) {
- carve::geom3d::Ray temp;
- // XXX: Find a better definition. This may be a source of problems
- // if floating point inaccuracies cause an incorrect answer.
- return !carve::geom3d::planeIntersection(a->plane, b->plane, temp);
-}
-
-#if defined(CARVE_DEBUG)
-
-#include <carve/debug_hooks.hpp>
-
-#endif
-
-namespace carve {
- namespace csg {
-
- static inline carve::mesh::MeshSet<3>::vertex_t *map_vertex(const VVMap &vmap, carve::mesh::MeshSet<3>::vertex_t *v) {
- VVMap::const_iterator i = vmap.find(v);
- if (i == vmap.end()) return v;
- return (*i).second;
- }
-
-#if defined(CARVE_DEBUG)
-
- class IntersectDebugHooks;
- extern IntersectDebugHooks *g_debug;
-
-#define HOOK(x) do { if (g_debug) { g_debug->x } } while(0)
-
- static inline void drawFaceLoopList(const FaceLoopList &ll,
- float rF, float gF, float bF, float aF,
- float rB, float gB, float bB, float aB,
- bool lit) {
- for (FaceLoop *flb = ll.head; flb; flb = flb->next) {
- const carve::mesh::MeshSet<3>::face_t *f = (flb->orig_face);
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &loop = flb->vertices;
- HOOK(drawFaceLoop2(loop, f->plane.N, rF, gF, bF, aF, rB, gB, bB, aB, true, lit););
- HOOK(drawFaceLoopWireframe(loop, f->plane.N, 1, 1, 1, 0.1f););
- }
- }
-
- static inline void drawFaceLoopListWireframe(const FaceLoopList &ll) {
- for (FaceLoop *flb = ll.head; flb; flb = flb->next) {
- const carve::mesh::MeshSet<3>::face_t *f = (flb->orig_face);
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &loop = flb->vertices;
- HOOK(drawFaceLoopWireframe(loop, f->plane.N, 1, 1, 1, 0.1f););
- }
- }
-
- template<typename T>
- static inline void drawEdges(T begin, T end,
- float rB, float gB, float bB, float aB,
- float rE, float gE, float bE, float aE,
- float w) {
- for (; begin != end; ++begin) {
- HOOK(drawEdge((*begin).first, (*begin).second, rB, gB, bB, aB, rE, gE, bE, aE, w););
- }
- }
-
-#endif
-
- }
-}
diff --git a/extern/carve/lib/intersect_debug.cpp b/extern/carve/lib/intersect_debug.cpp
deleted file mode 100644
index 50201d3cfb5..00000000000
--- a/extern/carve/lib/intersect_debug.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/csg.hpp>
-
-#include <list>
-#include <set>
-#include <iostream>
-
-#include <algorithm>
-
-#include "intersect_debug.hpp"
-
-namespace carve {
- namespace csg {
-
-#if defined(CARVE_DEBUG)
-
-#define DEBUG_DRAW_FACE_EDGES
-#define DEBUG_DRAW_INTERSECTIONS
-// #define DEBUG_DRAW_OCTREE
-#define DEBUG_DRAW_INTERSECTION_LINE
-// #define DEBUG_DRAW_GROUPS
-// #define DEBUG_PRINT_RESULT_FACES
-
- IntersectDebugHooks *g_debug = NULL;
-
- IntersectDebugHooks *intersect_installDebugHooks(IntersectDebugHooks *hooks) {
- IntersectDebugHooks *h = g_debug;
- g_debug = hooks;
- return h;
- }
-
- bool intersect_debugEnabled() { return true; }
-
-#else
-
- IntersectDebugHooks *intersect_installDebugHooks(IntersectDebugHooks * /* hooks */) {
- return NULL;
- }
-
- bool intersect_debugEnabled() { return false; }
-
-#endif
-
- }
-}
diff --git a/extern/carve/lib/intersect_debug.hpp b/extern/carve/lib/intersect_debug.hpp
deleted file mode 100644
index d68f49ce2c1..00000000000
--- a/extern/carve/lib/intersect_debug.hpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#include <carve/debug_hooks.hpp>
-
-#if defined(CARVE_DEBUG)
-
-#define DEBUG_DRAW_FACE_EDGES
-#define DEBUG_DRAW_INTERSECTIONS
-// #define DEBUG_DRAW_OCTREE
-#define DEBUG_DRAW_INTERSECTION_LINE
-// #define DEBUG_DRAW_GROUPS
-// #define DEBUG_PRINT_RESULT_FACES
-
-#endif
diff --git a/extern/carve/lib/intersect_face_division.cpp b/extern/carve/lib/intersect_face_division.cpp
deleted file mode 100644
index 6554ef500ed..00000000000
--- a/extern/carve/lib/intersect_face_division.cpp
+++ /dev/null
@@ -1,1765 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/csg.hpp>
-#include <carve/polyline.hpp>
-#include <carve/debug_hooks.hpp>
-#include <carve/timing.hpp>
-#include <carve/triangulator.hpp>
-
-#include <list>
-#include <set>
-#include <iostream>
-
-#include <algorithm>
-
-#include "csg_detail.hpp"
-#include "csg_data.hpp"
-
-#include "intersect_common.hpp"
-
-
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
-void writePLY(const std::string &out_file, const carve::line::PolylineSet *lines, bool ascii);
-#endif
-
-
-
-namespace {
-
-
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- template<typename iter_t>
- void dumpFacesAndHoles(iter_t f_begin, iter_t f_end,
- iter_t h_begin, iter_t h_end,
- const std::string &fname) {
- std::cerr << "dumping " << std::distance(f_begin, f_end) << " faces, " << std::distance(h_begin, h_end) << " holes." << std::endl;
- std::map<carve::mesh::MeshSet<3>::vertex_t *, size_t> v_included;
-
- for (iter_t i = f_begin; i != f_end; ++i) {
- for (size_t j = 0; j < (*i).size(); ++j) {
- if (v_included.find((*i)[j]) == v_included.end()) {
- size_t &p = v_included[(*i)[j]];
- p = v_included.size() - 1;
- }
- }
- }
-
- for (iter_t i = h_begin; i != h_end; ++i) {
- for (size_t j = 0; j < (*i).size(); ++j) {
- if (v_included.find((*i)[j]) == v_included.end()) {
- size_t &p = v_included[(*i)[j]];
- p = v_included.size() - 1;
- }
- }
- }
-
- carve::line::PolylineSet fh;
- fh.vertices.resize(v_included.size());
- for (std::map<carve::mesh::MeshSet<3>::vertex_t *, size_t>::const_iterator
- i = v_included.begin(); i != v_included.end(); ++i) {
- fh.vertices[(*i).second].v = (*i).first->v;
- }
-
- {
- std::vector<size_t> connected;
- for (iter_t i = f_begin; i != f_end; ++i) {
- connected.clear();
- for (size_t j = 0; j < (*i).size(); ++j) {
- connected.push_back(v_included[(*i)[j]]);
- }
- fh.addPolyline(true, connected.begin(), connected.end());
- }
- for (iter_t i = h_begin; i != h_end; ++i) {
- connected.clear();
- for (size_t j = 0; j < (*i).size(); ++j) {
- connected.push_back(v_included[(*i)[j]]);
- }
- fh.addPolyline(true, connected.begin(), connected.end());
- }
- }
-
- ::writePLY(fname, &fh, true);
- }
-#endif
-
-
-
- template<typename T>
- void populateVectorFromList(std::list<T> &l, std::vector<T> &v) {
- v.clear();
- v.reserve(l.size());
- for (typename std::list<T>::iterator i = l.begin(); i != l.end(); ++i) {
- v.push_back(T());
- std::swap(*i, v.back());
- }
- l.clear();
- }
-
- template<typename T>
- void populateListFromVector(std::vector<T> &v, std::list<T> &l) {
- l.clear();
- for (size_t i = 0; i < v.size(); ++i) {
- l.push_back(T());
- std::swap(v[i], l.back());
- }
- v.clear();
- }
-
-
-
- struct GraphEdge {
- GraphEdge *next;
- GraphEdge *prev;
- GraphEdge *loop_next;
- carve::mesh::MeshSet<3>::vertex_t *src;
- carve::mesh::MeshSet<3>::vertex_t *tgt;
- double ang;
- int visited;
-
- GraphEdge(carve::mesh::MeshSet<3>::vertex_t *_src, carve::mesh::MeshSet<3>::vertex_t *_tgt) :
- next(NULL), prev(NULL), loop_next(NULL),
- src(_src), tgt(_tgt),
- ang(0.0), visited(-1) {
- }
- };
-
-
-
- struct GraphEdges {
- GraphEdge *edges;
- carve::geom2d::P2 proj;
-
- GraphEdges() : edges(NULL), proj() {
- }
- };
-
-
-
- struct Graph {
- typedef std::unordered_map<carve::mesh::MeshSet<3>::vertex_t *, GraphEdges> graph_t;
-
- graph_t graph;
-
- Graph() : graph() {
- }
-
- ~Graph() {
- int c = 0;
-
- GraphEdge *edge;
- for (graph_t::iterator i = graph.begin(), e = graph.end(); i != e; ++i) {
- edge = (*i).second.edges;
- while (edge) {
- GraphEdge *temp = edge;
- ++c;
- edge = edge->next;
- delete temp;
- }
- }
-
- if (c) {
- std::cerr << "warning: "
- << c
- << " edges should have already been removed at graph destruction time"
- << std::endl;
- }
- }
-
- const carve::geom2d::P2 &projection(carve::mesh::MeshSet<3>::vertex_t *v) const {
- graph_t::const_iterator i = graph.find(v);
- CARVE_ASSERT(i != graph.end());
- return (*i).second.proj;
- }
-
- void computeProjection(carve::mesh::MeshSet<3>::face_t *face) {
- for (graph_t::iterator i = graph.begin(), e = graph.end(); i != e; ++i) {
- (*i).second.proj = face->project((*i).first->v);
- }
- for (graph_t::iterator i = graph.begin(), e = graph.end(); i != e; ++i) {
- for (GraphEdge *e = (*i).second.edges; e; e = e->next) {
- e->ang = carve::math::ANG(carve::geom2d::atan2(projection(e->tgt) - projection(e->src)));
- }
- }
- }
-
- void print(std::ostream &out, const carve::csg::VertexIntersections *vi) const {
- for (graph_t::const_iterator i = graph.begin(), e = graph.end(); i != e; ++i) {
- out << (*i).first << (*i).first->v << '(' << projection((*i).first).x << ',' << projection((*i).first).y << ") :";
- for (const GraphEdge *e = (*i).second.edges; e; e = e->next) {
- out << ' ' << e->tgt << e->tgt->v << '(' << projection(e->tgt).x << ',' << projection(e->tgt).y << ')';
- }
- out << std::endl;
- if (vi) {
- carve::csg::VertexIntersections::const_iterator j = vi->find((*i).first);
- if (j != vi->end()) {
- out << " (int) ";
- for (carve::csg::IObjPairSet::const_iterator
- k = (*j).second.begin(), ke = (*j).second.end(); k != ke; ++k) {
- if ((*k).first < (*k).second) {
- out << (*k).first << ".." << (*k).second << "; ";
- }
- }
- out << std::endl;
- }
- }
- }
- }
-
- void addEdge(carve::mesh::MeshSet<3>::vertex_t *v1, carve::mesh::MeshSet<3>::vertex_t *v2) {
- GraphEdges &edges = graph[v1];
- GraphEdge *edge = new GraphEdge(v1, v2);
- if (edges.edges) edges.edges->prev = edge;
- edge->next = edges.edges;
- edges.edges = edge;
- }
-
- void removeEdge(GraphEdge *edge) {
- if (edge->prev != NULL) {
- edge->prev->next = edge->next;
- } else {
- if (edge->next != NULL) {
- GraphEdges &edges = (graph[edge->src]);
- edges.edges = edge->next;
- } else {
- graph.erase(edge->src);
- }
- }
- if (edge->next != NULL) {
- edge->next->prev = edge->prev;
- }
- delete edge;
- }
-
- bool empty() const {
- return graph.size() == 0;
- }
-
- GraphEdge *pickStartEdge() {
- // Try and find a vertex from which there is only one outbound edge. Won't always succeed.
- for (graph_t::iterator i = graph.begin(); i != graph.end(); ++i) {
- GraphEdges &ge = i->second;
- if (ge.edges->next == NULL) {
- return ge.edges;
- }
- }
- return (*graph.begin()).second.edges;
- }
-
- GraphEdge *outboundEdges(carve::mesh::MeshSet<3>::vertex_t *v) {
- return graph[v].edges;
- }
- };
-
-
-
- /**
- * \brief Take a set of new edges and split a face based upon those edges.
- *
- * @param[in] face The face to be split.
- * @param[in] edges
- * @param[out] face_loops Output list of face loops
- * @param[out] hole_loops Output list of hole loops
- * @param vi
- */
- static void splitFace(carve::mesh::MeshSet<3>::face_t *face,
- const carve::csg::V2Set &edges,
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &face_loops,
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &hole_loops,
- const carve::csg::VertexIntersections & /* vi */) {
- Graph graph;
-
- for (carve::csg::V2Set::const_iterator
- i = edges.begin(), e = edges.end();
- i != e;
- ++i) {
- carve::mesh::MeshSet<3>::vertex_t *v1 = ((*i).first), *v2 = ((*i).second);
- if (carve::geom::equal(v1->v, v2->v)) std::cerr << "WARNING! " << v1->v << "==" << v2->v << std::endl;
- graph.addEdge(v1, v2);
- }
-
- graph.computeProjection(face);
-
- while (!graph.empty()) {
- GraphEdge *edge;
- GraphEdge *start;
- start = edge = graph.pickStartEdge();
-
- edge->visited = 0;
-
- int len = 0;
-
- for (;;) {
- double in_ang = M_PI + edge->ang;
- if (in_ang > M_TWOPI) in_ang -= M_TWOPI;
-
- GraphEdge *opts;
- GraphEdge *out = NULL;
- double best = M_TWOPI + 1.0;
-
- for (opts = graph.outboundEdges(edge->tgt); opts; opts = opts->next) {
- if (opts->tgt == edge->src) {
- if (out == NULL && opts->next == NULL) out = opts;
- } else {
- double out_ang = carve::math::ANG(in_ang - opts->ang);
-
- if (out == NULL || out_ang < best) {
- out = opts;
- best = out_ang;
- }
- }
- }
-
- CARVE_ASSERT(out != NULL);
-
- edge->loop_next = out;
-
- if (out->visited >= 0) {
- while (start != out) {
- GraphEdge *e = start;
- start = start->loop_next;
- e->loop_next = NULL;
- e->visited = -1;
- }
- len = edge->visited - out->visited + 1;
- break;
- }
-
- out->visited = edge->visited + 1;
- edge = out;
- }
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> loop(len);
- std::vector<carve::geom2d::P2> projected(len);
-
- edge = start;
- for (int i = 0; i < len; ++i) {
- GraphEdge *next = edge->loop_next;
- loop[i] = edge->src;
- projected[i] = graph.projection(edge->src);
- graph.removeEdge(edge);
- edge = next;
- }
-
- CARVE_ASSERT(edge == start);
-
- if (carve::geom2d::signedArea(projected) < 0) {
- face_loops.push_back(std::vector<carve::mesh::MeshSet<3>::vertex_t *>());
- face_loops.back().swap(loop);
- } else {
- hole_loops.push_back(std::vector<carve::mesh::MeshSet<3>::vertex_t *>());
- hole_loops.back().swap(loop);
- }
- }
- }
-
-
-
- /**
- * \brief Determine the relationship between a face loop and a hole loop.
- *
- * Determine whether a face and hole share an edge, or a vertex,
- * or do not touch. Find a hole vertex that is not part of the
- * face, and a hole,face vertex pair that are coincident, if such
- * a pair exists.
- *
- * @param[in] f A face loop.
- * @param[in] f_sort A vector indexing \a f in address order
- * @param[in] h A hole loop.
- * @param[in] h_sort A vector indexing \a h in address order
- * @param[out] f_idx Index of a face vertex that is shared with the hole.
- * @param[out] h_idx Index of the hole vertex corresponding to \a f_idx.
- * @param[out] unmatched_h_idx Index of a hole vertex that is not part of the face.
- * @param[out] shares_vertex Boolean indicating that the face and the hole share a vertex.
- * @param[out] shares_edge Boolean indicating that the face and the hole share an edge.
- */
- static void compareFaceLoopAndHoleLoop(const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &f,
- const std::vector<unsigned> &f_sort,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &h,
- const std::vector<unsigned> &h_sort,
- unsigned &f_idx,
- unsigned &h_idx,
- int &unmatched_h_idx,
- bool &shares_vertex,
- bool &shares_edge) {
- const size_t F = f.size();
- const size_t H = h.size();
-
- shares_vertex = shares_edge = false;
- unmatched_h_idx = -1;
-
- unsigned I, J;
- for (I = J = 0; I < F && J < H;) {
- unsigned i = f_sort[I], j = h_sort[J];
- if (f[i] == h[j]) {
- shares_vertex = true;
- f_idx = i;
- h_idx = j;
- if (f[(i + F - 1) % F] == h[(j + 1) % H]) {
- shares_edge = true;
- }
- carve::mesh::MeshSet<3>::vertex_t *t = f[i];
- do { ++I; } while (I < F && f[f_sort[I]] == t);
- do { ++J; } while (J < H && h[h_sort[J]] == t);
- } else if (f[i] < h[j]) {
- ++I;
- } else {
- unmatched_h_idx = j;
- ++J;
- }
- }
- if (J < H) {
- unmatched_h_idx = h_sort[J];
- }
- }
-
-
-
- /**
- * \brief Compute an embedding for a set of face loops and hole loops.
- *
- * Because face and hole loops may be contained within each other,
- * it must be determined which hole loops are directly contained
- * within a face loop.
- *
- * @param[in] face The face from which these face and hole loops derive.
- * @param[in] face_loops
- * @param[in] hole_loops
- * @param[out] containing_faces A vector which for each hole loop
- * lists the indices of the face
- * loops it is containined in.
- * @param[out] hole_shared_vertices A map from a face,hole pair to
- * a shared vertex pair.
- */
- static void computeContainment(carve::mesh::MeshSet<3>::face_t *face,
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &face_loops,
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &hole_loops,
- std::vector<std::vector<int> > &containing_faces,
- std::map<int, std::map<int, std::pair<unsigned, unsigned> > > &hole_shared_vertices) {
-#if defined(CARVE_DEBUG)
- std::cerr << "input: "
- << face_loops.size() << "faces, "
- << hole_loops.size() << "holes."
- << std::endl;
-#endif
-
- std::vector<std::vector<carve::geom2d::P2> > face_loops_projected, hole_loops_projected;
- std::vector<carve::geom::aabb<2> > face_loop_aabb, hole_loop_aabb;
- std::vector<std::vector<unsigned> > face_loops_sorted, hole_loops_sorted;
-
- std::vector<double> face_loop_areas, hole_loop_areas;
-
- face_loops_projected.resize(face_loops.size());
- face_loops_sorted.resize(face_loops.size());
- face_loop_aabb.resize(face_loops.size());
- face_loop_areas.resize(face_loops.size());
-
- hole_loops_projected.resize(hole_loops.size());
- hole_loops_sorted.resize(hole_loops.size());
- hole_loop_aabb.resize(hole_loops.size());
- hole_loop_areas.resize(hole_loops.size());
-
- // produce a projection of each face loop onto a 2D plane, and an
- // index vector which sorts vertices by address.
- for (size_t m = 0; m < face_loops.size(); ++m) {
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &f_loop = (face_loops[m]);
- face_loops_projected[m].reserve(f_loop.size());
- face_loops_sorted[m].reserve(f_loop.size());
- for (size_t n = 0; n < f_loop.size(); ++n) {
- face_loops_projected[m].push_back(face->project(f_loop[n]->v));
- face_loops_sorted[m].push_back(n);
- }
- face_loop_areas.push_back(carve::geom2d::signedArea(face_loops_projected[m]));
-
- std::sort(face_loops_sorted[m].begin(), face_loops_sorted[m].end(),
- carve::make_index_sort(face_loops[m].begin()));
- face_loop_aabb[m].fit(face_loops_projected[m].begin(), face_loops_projected[m].end());
- }
-
- // produce a projection of each hole loop onto a 2D plane, and an
- // index vector which sorts vertices by address.
- for (size_t m = 0; m < hole_loops.size(); ++m) {
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &h_loop = (hole_loops[m]);
- hole_loops_projected[m].reserve(h_loop.size());
- hole_loops_projected[m].reserve(h_loop.size());
- for (size_t n = 0; n < h_loop.size(); ++n) {
- hole_loops_projected[m].push_back(face->project(h_loop[n]->v));
- hole_loops_sorted[m].push_back(n);
- }
- hole_loop_areas.push_back(carve::geom2d::signedArea(hole_loops_projected[m]));
-
- std::sort(hole_loops_sorted[m].begin(), hole_loops_sorted[m].end(),
- carve::make_index_sort(hole_loops[m].begin()));
- hole_loop_aabb[m].fit(hole_loops_projected[m].begin(), hole_loops_projected[m].end());
- }
-
- containing_faces.resize(hole_loops.size());
-
- for (unsigned i = 0; i < hole_loops.size(); ++i) {
-
- for (unsigned j = 0; j < face_loops.size(); ++j) {
- if (!face_loop_aabb[j].completelyContains(hole_loop_aabb[i])) {
-#if defined(CARVE_DEBUG)
- std::cerr << "face: " << j
- << " hole: " << i
- << " skipped test (aabb fail)"
- << std::endl;
-#endif
- continue;
- }
-
- unsigned f_idx, h_idx;
- int unmatched_h_idx;
- bool shares_vertex, shares_edge;
- compareFaceLoopAndHoleLoop(face_loops[j],
- face_loops_sorted[j],
- hole_loops[i],
- hole_loops_sorted[i],
- f_idx, h_idx,
- unmatched_h_idx,
- shares_vertex,
- shares_edge);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "face: " << j
- << " hole: " << i
- << " shares_vertex: " << shares_vertex
- << " shares_edge: " << shares_edge
- << std::endl;
-#endif
-
- carve::geom3d::Vector test = hole_loops[i][0]->v;
- carve::geom2d::P2 test_p = face->project(test);
-
- if (shares_vertex) {
- hole_shared_vertices[i][j] = std::make_pair(h_idx, f_idx);
- // Hole touches face. Should be able to connect it up
- // trivially. Still need to record its containment, so that
- // the assignment below works.
- if (unmatched_h_idx != -1) {
-#if defined(CARVE_DEBUG)
- std::cerr << "using unmatched vertex: " << unmatched_h_idx << std::endl;
-#endif
- test = hole_loops[i][unmatched_h_idx]->v;
- test_p = face->project(test);
- } else {
- // XXX: hole shares ALL vertices with face. Pick a point
- // internal to the projected poly.
- if (shares_edge) {
- // Hole shares edge with face => face can't contain hole.
- continue;
- }
-
- // XXX: how is this possible? Doesn't share an edge, but
- // also doesn't have any vertices that are not in
- // common. Degenerate hole?
-
- // XXX: come up with a test case for this.
- CARVE_FAIL("implement me");
- }
- }
-
-
- // XXX: use loop area to avoid some point-in-poly tests? Loop
- // area is faster, but not sure which is more robust.
- if (carve::geom2d::pointInPolySimple(face_loops_projected[j], test_p)) {
-#if defined(CARVE_DEBUG)
- std::cerr << "contains: " << i << " - " << j << std::endl;
-#endif
- containing_faces[i].push_back(j);
- } else {
-#if defined(CARVE_DEBUG)
- std::cerr << "does not contain: " << i << " - " << j << std::endl;
-#endif
- }
- }
-
-#if defined(CARVE_DEBUG)
- if (containing_faces[i].size() == 0) {
- //HOOK(drawFaceLoopWireframe(hole_loops[i], face->normal, 1.0, 0.0, 0.0, 1.0););
- std::cerr << "hole loop: ";
- for (unsigned j = 0; j < hole_loops[i].size(); ++j) {
- std::cerr << " " << hole_loops[i][j] << ":" << hole_loops[i][j]->v;
- }
- std::cerr << std::endl;
- for (unsigned j = 0; j < face_loops.size(); ++j) {
- //HOOK(drawFaceLoopWireframe(face_loops[j], face->normal, 0.0, 1.0, 0.0, 1.0););
- }
- }
-#endif
-
- // CARVE_ASSERT(containing_faces[i].size() >= 1);
- }
- }
-
-
-
- /**
- * \brief Merge face loops and hole loops to produce a set of face loops without holes.
- *
- * @param[in] face The face from which these face loops derive.
- * @param[in,out] f_loops A list of face loops.
- * @param[in] h_loops A list of hole loops to be incorporated into face loops.
- */
- static void mergeFacesAndHoles(carve::mesh::MeshSet<3>::face_t *face,
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &f_loops,
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &h_loops,
- carve::csg::CSG::Hooks & /* hooks */) {
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > face_loops;
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > hole_loops;
-
- std::vector<std::vector<int> > containing_faces;
- std::map<int, std::map<int, std::pair<unsigned, unsigned> > > hole_shared_vertices;
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- dumpFacesAndHoles(f_loops.begin(), f_loops.end(), h_loops.begin(), h_loops.end(), "/tmp/pre_merge.ply");
-#endif
-
- {
- // move input face and hole loops to temp vectors.
- size_t m;
- face_loops.resize(f_loops.size());
- m = 0;
- for (std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> >::iterator
- i = f_loops.begin(), ie = f_loops.end();
- i != ie;
- ++i, ++m) {
- face_loops[m].swap((*i));
- }
-
- hole_loops.resize(h_loops.size());
- m = 0;
- for (std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> >::iterator
- i = h_loops.begin(), ie = h_loops.end();
- i != ie;
- ++i, ++m) {
- hole_loops[m].swap((*i));
- }
- f_loops.clear();
- h_loops.clear();
- }
-
- // work out the embedding of holes and faces.
- computeContainment(face, face_loops, hole_loops, containing_faces, hole_shared_vertices);
-
- int unassigned = (int)hole_loops.size();
-
- std::vector<std::vector<int> > face_holes;
- face_holes.resize(face_loops.size());
-
- for (unsigned i = 0; i < containing_faces.size(); ++i) {
- if (containing_faces[i].size() == 0) {
- std::map<int, std::map<int, std::pair<unsigned, unsigned> > >::iterator it = hole_shared_vertices.find(i);
- if (it != hole_shared_vertices.end()) {
- std::map<int, std::pair<unsigned, unsigned> >::iterator it2 = (*it).second.begin();
- int f = (*it2).first;
- unsigned h_idx = (*it2).second.first;
- unsigned f_idx = (*it2).second.second;
-
- // patch the hole into the face directly. because
- // f_loop[f_idx] == h_loop[h_idx], we don't need to
- // duplicate the f_loop vertex.
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &f_loop = face_loops[f];
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &h_loop = hole_loops[i];
-
- f_loop.insert(f_loop.begin() + f_idx + 1, h_loop.size(), NULL);
-
- unsigned p = f_idx + 1;
- for (unsigned a = h_idx + 1; a < h_loop.size(); ++a, ++p) {
- f_loop[p] = h_loop[a];
- }
- for (unsigned a = 0; a <= h_idx; ++a, ++p) {
- f_loop[p] = h_loop[a];
- }
-
-#if defined(CARVE_DEBUG)
- std::cerr << "hook face " << f << " to hole " << i << "(vertex)" << std::endl;
-#endif
- } else {
- std::cerr << "uncontained hole loop does not share vertices with any face loop!" << std::endl;
- }
- unassigned--;
- }
- }
-
-
- // work out which holes are directly contained within which faces.
- while (unassigned) {
- std::set<int> removed;
-
- for (unsigned i = 0; i < containing_faces.size(); ++i) {
- if (containing_faces[i].size() == 1) {
- int f = containing_faces[i][0];
- face_holes[f].push_back(i);
-#if defined(CARVE_DEBUG)
- std::cerr << "hook face " << f << " to hole " << i << std::endl;
-#endif
- removed.insert(f);
- unassigned--;
- }
- }
-
- if (!removed.size())
- throw carve::exception("Failed to merge holes");
-
- for (std::set<int>::iterator f = removed.begin(); f != removed.end(); ++f) {
- for (unsigned i = 0; i < containing_faces.size(); ++i) {
- containing_faces[i].erase(std::remove(containing_faces[i].begin(),
- containing_faces[i].end(),
- *f),
- containing_faces[i].end());
- }
- }
- }
-
-#if 0
- // use old templated projection code to patch holes into faces.
- for (unsigned i = 0; i < face_loops.size(); ++i) {
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > face_hole_loops;
- face_hole_loops.resize(face_holes[i].size());
- for (unsigned j = 0; j < face_holes[i].size(); ++j) {
- face_hole_loops[j].swap(hole_loops[face_holes[i][j]]);
- }
- if (face_hole_loops.size()) {
-
- f_loops.push_back(carve::triangulate::incorporateHolesIntoPolygon(
- carve::mesh::MeshSet<3>::face_t::projection_mapping(face->project),
- face_loops[i],
- face_hole_loops));
- } else {
- f_loops.push_back(face_loops[i]);
- }
- }
-
-#else
- // use new 2d-only hole patching code.
- for (size_t i = 0; i < face_loops.size(); ++i) {
- if (!face_holes[i].size()) {
- f_loops.push_back(face_loops[i]);
- continue;
- }
-
- std::vector<std::vector<carve::geom2d::P2> > projected_poly;
- projected_poly.resize(face_holes[i].size() + 1);
- projected_poly[0].reserve(face_loops[i].size());
- for (size_t j = 0; j < face_loops[i].size(); ++j) {
- projected_poly[0].push_back(face->project(face_loops[i][j]->v));
- }
- for (size_t j = 0; j < face_holes[i].size(); ++j) {
- projected_poly[j+1].reserve(hole_loops[face_holes[i][j]].size());
- for (size_t k = 0; k < hole_loops[face_holes[i][j]].size(); ++k) {
- projected_poly[j+1].push_back(face->project(hole_loops[face_holes[i][j]][k]->v));
- }
- }
-
- std::vector<std::pair<size_t, size_t> > result = carve::triangulate::incorporateHolesIntoPolygon(projected_poly);
-
- f_loops.push_back(std::vector<carve::mesh::MeshSet<3>::vertex_t *>());
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &out = f_loops.back();
- out.reserve(result.size());
- for (size_t j = 0; j < result.size(); ++j) {
- if (result[j].first == 0) {
- out.push_back(face_loops[i][result[j].second]);
- } else {
- out.push_back(hole_loops[face_holes[i][result[j].first-1]][result[j].second]);
- }
- }
- }
-#endif
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- dumpFacesAndHoles(f_loops.begin(), f_loops.end(), h_loops.begin(), h_loops.end(), "/tmp/post_merge.ply");
-#endif
-
- }
-
-
-
- /**
- * \brief Assemble the base loop for a face.
- *
- * The base loop is the original face loop, including vertices
- * created by intersections crossing any of its edges.
- *
- * @param[in] face The face to process.
- * @param[in] vmap
- * @param[in] face_split_edges
- * @param[in] divided_edges A mapping from edge pointer to sets of
- * ordered vertices corrsponding to the intersection points
- * on that edge.
- * @param[out] base_loop A vector of the vertices of the base loop.
- */
- static bool assembleBaseLoop(carve::mesh::MeshSet<3>::face_t *face,
- const carve::csg::detail::Data &data,
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &base_loop,
- carve::csg::CSG::Hooks &hooks) {
- base_loop.clear();
-
- // XXX: assumes that face->edges is in the same order as
- // face->vertices. (Which it is)
- carve::mesh::MeshSet<3>::edge_t *e = face->edge;
- size_t e_idx = 0;
- bool face_edge_intersected = false;
- do {
- base_loop.push_back(carve::csg::map_vertex(data.vmap, e->vert));
-
- carve::csg::detail::EVVMap::const_iterator ev = data.divided_edges.find(e);
-
- if (ev != data.divided_edges.end()) {
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &ev_vec = ((*ev).second);
-
- for (size_t k = 0, ke = ev_vec.size(); k < ke;) {
- base_loop.push_back(ev_vec[k++]);
- }
-
- if (ev_vec.size() && hooks.hasHook(carve::csg::CSG::Hooks::EDGE_DIVISION_HOOK)) {
- carve::mesh::MeshSet<3>::vertex_t *v1 = e->vert;
- carve::mesh::MeshSet<3>::vertex_t *v2;
- for (size_t k = 0, ke = ev_vec.size(); k < ke;) {
- v2 = ev_vec[k++];
- hooks.edgeDivision(e, e_idx, v1, v2);
- v1 = v2;
- }
- v2 = e->v2();
- hooks.edgeDivision(e, e_idx, v1, v2);
- }
-
- face_edge_intersected = true;
- }
- e = e->next;
- ++e_idx;
- } while (e != face->edge);
-
- return face_edge_intersected;
- }
-
-
-
- // the crossing_data structure holds temporary information regarding
- // paths, and their relationship to the loop of edges that forms the
- // face perimeter.
- struct crossing_data {
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> *path;
- size_t edge_idx[2];
-
- crossing_data(std::vector<carve::mesh::MeshSet<3>::vertex_t *> *p, size_t e1, size_t e2) : path(p) {
- edge_idx[0] = e1; edge_idx[1] = e2;
- }
-
- bool operator<(const crossing_data &c) const {
- // the sort order for paths is in order of increasing initial
- // position on the edge loop, but decreasing final position.
- return edge_idx[0] < c.edge_idx[0] || (edge_idx[0] == c.edge_idx[0] && edge_idx[1] > c.edge_idx[1]);
- }
- };
-
-
-
- bool processCrossingEdges(carve::mesh::MeshSet<3>::face_t *face,
- const carve::csg::VertexIntersections &vertex_intersections,
- carve::csg::CSG::Hooks &hooks,
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &base_loop,
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &paths,
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &face_loops_out) {
- const size_t N = base_loop.size();
- std::vector<crossing_data> endpoint_indices;
-
- endpoint_indices.reserve(paths.size());
-
- for (size_t i = 0; i < paths.size(); ++i) {
- endpoint_indices.push_back(crossing_data(&paths[i], N, N));
- }
-
- // Step 1:
- // locate endpoints of paths on the base loop.
- for (size_t i = 0; i < N; ++i) {
- for (size_t j = 0; j < paths.size(); ++j) {
- // test beginning of path.
- if (paths[j].front() == base_loop[i]) {
- if (endpoint_indices[j].edge_idx[0] == N) {
- endpoint_indices[j].edge_idx[0] = i;
- } else {
- // there is a duplicated vertex in the face perimeter. The
- // path might attach to either of the duplicate instances
- // so we have to work out which is the right one to attach
- // to. We assume it's the index currently being examined,
- // if the path heads in a direction that's internal to the
- // angle made by the prior and next edges of the face
- // perimeter. Otherwise, leave it as the currently
- // selected index (until another duplicate is found, if it
- // exists, and is tested).
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &p = *endpoint_indices[j].path;
- const size_t pN = p.size();
-
- carve::mesh::MeshSet<3>::vertex_t *a, *b, *c;
- a = base_loop[(i+N-1)%N];
- b = base_loop[i];
- c = base_loop[(i+1)%N];
-
- carve::mesh::MeshSet<3>::vertex_t *adj = (p[0] == base_loop[i]) ? p[1] : p[pN-2];
-
- if (carve::geom2d::internalToAngle(face->project(c->v),
- face->project(b->v),
- face->project(a->v),
- face->project(adj->v))) {
- endpoint_indices[j].edge_idx[0] = i;
- }
- }
- }
-
- // test end of path.
- if (paths[j].back() == base_loop[i]) {
- if (endpoint_indices[j].edge_idx[1] == N) {
- endpoint_indices[j].edge_idx[1] = i;
- } else {
- // Work out which of the duplicated vertices is the right
- // one to attach to, as above.
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &p = *endpoint_indices[j].path;
- const size_t pN = p.size();
-
- carve::mesh::MeshSet<3>::vertex_t *a, *b, *c;
- a = base_loop[(i+N-1)%N];
- b = base_loop[i];
- c = base_loop[(i+1)%N];
-
- carve::mesh::MeshSet<3>::vertex_t *adj = (p[0] == base_loop[i]) ? p[1] : p[pN-2];
-
- if (carve::geom2d::internalToAngle(face->project(c->v),
- face->project(b->v),
- face->project(a->v),
- face->project(adj->v))) {
- endpoint_indices[j].edge_idx[1] = i;
- }
- }
- }
- }
- }
-
-#if defined(CARVE_DEBUG)
- std::cerr << "### N: " << N << std::endl;
- for (size_t i = 0; i < paths.size(); ++i) {
- std::cerr << "### path: " << i << " endpoints: " << endpoint_indices[i].edge_idx[0] << " - " << endpoint_indices[i].edge_idx[1] << std::endl;
- }
-#endif
-
-
- // Step 2:
- // divide paths up into those that connect to the base loop in two
- // places (cross), and those that do not (noncross).
- std::vector<crossing_data> cross, noncross;
- cross.reserve(endpoint_indices.size() + 1);
- noncross.reserve(endpoint_indices.size());
-
- for (size_t i = 0; i < endpoint_indices.size(); ++i) {
-#if defined(CARVE_DEBUG)
- std::cerr << "### orienting path: " << i << " endpoints: " << endpoint_indices[i].edge_idx[0] << " - " << endpoint_indices[i].edge_idx[1] << std::endl;
-#endif
- if (endpoint_indices[i].edge_idx[0] != N && endpoint_indices[i].edge_idx[1] != N) {
- // Orient each path correctly. Paths should progress from
- // smaller perimeter index to larger, but if the path starts
- // and ends at the same perimeter index, then the decision
- // needs to be made based upon area.
- if (endpoint_indices[i].edge_idx[0] == endpoint_indices[i].edge_idx[1]) {
- // The path forms a loop that starts and ends at the same
- // vertex of the perimeter. In this case, we need to orient
- // the path so that the constructed loop has the right
- // signed area.
- double area = carve::geom2d::signedArea(endpoint_indices[i].path->begin() + 1,
- endpoint_indices[i].path->end(),
- carve::mesh::MeshSet<3>::face_t::projection_mapping(face->project));
- if (area < 0) {
- // XXX: Create test case to check that this is the correct sign for the area.
- std::reverse(endpoint_indices[i].path->begin(), endpoint_indices[i].path->end());
- }
- } else {
- if (endpoint_indices[i].edge_idx[0] > endpoint_indices[i].edge_idx[1]) {
- std::swap(endpoint_indices[i].edge_idx[0], endpoint_indices[i].edge_idx[1]);
- std::reverse(endpoint_indices[i].path->begin(), endpoint_indices[i].path->end());
- }
- }
- }
-
- if (endpoint_indices[i].edge_idx[0] != N &&
- endpoint_indices[i].edge_idx[1] != N &&
- endpoint_indices[i].edge_idx[0] != endpoint_indices[i].edge_idx[1]) {
- cross.push_back(endpoint_indices[i]);
- } else {
- noncross.push_back(endpoint_indices[i]);
- }
- }
-
- // Step 3:
- // add a temporary crossing path that connects the beginning and the
- // end of the base loop. this stops us from needing special case
- // code to handle the left over loop after all the other crossing
- // paths are considered.
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> base_loop_temp_path;
- base_loop_temp_path.reserve(2);
- base_loop_temp_path.push_back(base_loop.front());
- base_loop_temp_path.push_back(base_loop.back());
-
- cross.push_back(crossing_data(&base_loop_temp_path, 0, base_loop.size() - 1));
-#if defined(CARVE_DEBUG)
- std::cerr << "### crossing edge count (with sentinel): " << cross.size() << std::endl;
-#endif
-
- // Step 4:
- // sort paths by increasing beginning point and decreasing ending point.
- std::sort(cross.begin(), cross.end());
- std::sort(noncross.begin(), noncross.end());
-
- // Step 5:
- // divide up the base loop based upon crossing paths.
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > divided_base_loop;
- divided_base_loop.reserve(cross.size());
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> out;
-
- for (size_t i = 0; i < cross.size(); ++i) {
- size_t j;
- for (j = i + 1;
- j < cross.size() &&
- cross[i].edge_idx[0] == cross[j].edge_idx[0] &&
- cross[i].edge_idx[1] == cross[j].edge_idx[1];
- ++j) {}
- if (j - i >= 2) {
- // when there are multiple paths that begin and end at the
- // same point, they need to be ordered so that the constructed
- // loops have the right orientation. this means that the loop
- // made by taking path(i+1) forward, then path(i) backward
- // needs to have negative area. this combined area is equal to
- // the area of path(i+1) minus the area of path(i). in turn
- // this means that the loop made by path path(i+1) alone has
- // to have smaller signed area than loop made by path(i).
- // thus, we sort paths in order of decreasing area.
-
- std::vector<std::pair<double, std::vector<carve::mesh::MeshSet<3>::vertex_t *> *> > order;
- order.reserve(j - i);
- for (size_t k = i; k < j; ++k) {
- double area = carve::geom2d::signedArea(cross[k].path->begin(),
- cross[k].path->end(),
- carve::mesh::MeshSet<3>::face_t::projection_mapping(face->project));
-#if defined(CARVE_DEBUG)
- std::cerr << "### k=" << k << " area=" << area << std::endl;
-#endif
- order.push_back(std::make_pair(-area, cross[k].path));
- }
- std::sort(order.begin(), order.end());
- for (size_t k = i; k < j; ++k) {
- cross[k].path = order[k-i].second;
-#if defined(CARVE_DEBUG)
- std::cerr << "### post-sort k=" << k << " cross[k].path->size()=" << cross[k].path->size() << std::endl;
-#endif
- }
- }
- }
-
- // Step 6:
- for (size_t i = 0; i < cross.size(); ++i) {
-#if defined(CARVE_DEBUG)
- std::cerr << "### i=" << i << " working on edge: " << cross[i].edge_idx[0] << " - " << cross[i].edge_idx[1] << std::endl;
-#endif
- size_t e1_0 = cross[i].edge_idx[0];
- size_t e1_1 = cross[i].edge_idx[1];
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &p1 = *cross[i].path;
-#if defined(CARVE_DEBUG)
- std::cerr << "### path size = " << p1.size() << std::endl;
-#endif
-
- out.clear();
-
- if (i < cross.size() - 1 &&
- cross[i+1].edge_idx[1] <= cross[i].edge_idx[1]) {
-#if defined(CARVE_DEBUG)
- std::cerr << "### complex case" << std::endl;
-#endif
- // complex case. crossing path with other crossing paths embedded within.
- size_t pos = e1_0;
-
- size_t skip = i+1;
-
- while (pos != e1_1) {
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &p2 = *cross[skip].path;
- size_t e2_0 = cross[skip].edge_idx[0];
- size_t e2_1 = cross[skip].edge_idx[1];
-
- // copy up to the beginning of the next path.
- std::copy(base_loop.begin() + pos, base_loop.begin() + e2_0, std::back_inserter(out));
-
- CARVE_ASSERT(base_loop[e2_0] == p2[0]);
- // copy the next path in the right direction.
- std::copy(p2.begin(), p2.end() - 1, std::back_inserter(out));
-
- // move to the position of the end of the path.
- pos = e2_1;
-
- // advance to the next hit path.
- do {
- ++skip;
- } while(skip != cross.size() && cross[skip].edge_idx[0] < e2_1);
-
- if (skip == cross.size()) break;
-
- // if the next hit path is past the start point of the current path, we're done.
- if (cross[skip].edge_idx[0] >= e1_1) break;
- }
-
- // copy up to the end of the path.
- if (pos < e1_1) {
- std::copy(base_loop.begin() + pos, base_loop.begin() + e1_1, std::back_inserter(out));
- }
-
- CARVE_ASSERT(base_loop[e1_1] == p1.back());
- std::copy(p1.rbegin(), p1.rend() - 1, std::back_inserter(out));
- } else {
- size_t loop_size = (e1_1 - e1_0) + (p1.size() - 1);
- out.reserve(loop_size);
-
- std::copy(base_loop.begin() + e1_0, base_loop.begin() + e1_1, std::back_inserter(out));
- std::copy(p1.rbegin(), p1.rend() - 1, std::back_inserter(out));
-
- CARVE_ASSERT(out.size() == loop_size);
- }
- divided_base_loop.push_back(out);
-
-#if defined(CARVE_DEBUG)
- {
- std::vector<carve::geom2d::P2> projected;
- projected.reserve(out.size());
- for (size_t n = 0; n < out.size(); ++n) {
- projected.push_back(face->project(out[n]->v));
- }
-
- double A = carve::geom2d::signedArea(projected);
- std::cerr << "### out area=" << A << std::endl;
- CARVE_ASSERT(A <= 0);
- }
-#endif
- }
-
- if (!noncross.size()) {
- // If there are no non-crossing paths then we're done.
- populateListFromVector(divided_base_loop, face_loops_out);
- return true;
- }
-
- // for each divided base loop, work out which noncrossing paths and
- // loops are part of it. use the old algorithm to combine these into
- // the divided base loop. if none, the divided base loop is just
- // output.
- std::vector<std::vector<carve::geom2d::P2> > proj;
- std::vector<carve::geom::aabb<2> > proj_aabb;
- proj.resize(divided_base_loop.size());
- proj_aabb.resize(divided_base_loop.size());
-
- // calculate an aabb for each divided base loop, to avoid expensive
- // point-in-poly tests.
- for (size_t i = 0; i < divided_base_loop.size(); ++i) {
- proj[i].reserve(divided_base_loop[i].size());
- for (size_t j = 0; j < divided_base_loop[i].size(); ++j) {
- proj[i].push_back(face->project(divided_base_loop[i][j]->v));
- }
- proj_aabb[i].fit(proj[i].begin(), proj[i].end());
- }
-
- for (size_t i = 0; i < divided_base_loop.size(); ++i) {
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> *> inc;
- carve::geom2d::P2 test;
-
- // for each noncrossing path, choose an endpoint that isn't on the
- // base loop as a test point.
- for (size_t j = 0; j < noncross.size(); ++j) {
- if (noncross[j].edge_idx[0] < N) {
- if (noncross[j].path->front() == base_loop[noncross[j].edge_idx[0]]) {
- // noncrossing paths may be loops that run from the edge, back to the same vertex.
- if (noncross[j].path->front() == noncross[j].path->back()) {
- CARVE_ASSERT(noncross[j].path->size() > 2);
- test = face->project((*noncross[j].path)[1]->v);
- } else {
- test = face->project(noncross[j].path->back()->v);
- }
- } else {
- test = face->project(noncross[j].path->front()->v);
- }
- } else {
- test = face->project(noncross[j].path->front()->v);
- }
-
- if (proj_aabb[i].intersects(test) &&
- carve::geom2d::pointInPoly(proj[i], test).iclass != carve::POINT_OUT) {
- inc.push_back(noncross[j].path);
- }
- }
-
-#if defined(CARVE_DEBUG)
- std::cerr << "### divided base loop:" << i << " inc.size()=" << inc.size() << std::endl;
- std::cerr << "### inc = [";
- for (size_t j = 0; j < inc.size(); ++j) {
- std::cerr << " " << inc[j];
- }
- std::cerr << " ]" << std::endl;
-#endif
-
- if (inc.size()) {
- carve::csg::V2Set face_edges;
-
- for (size_t j = 0; j < divided_base_loop[i].size() - 1; ++j) {
- face_edges.insert(std::make_pair(divided_base_loop[i][j],
- divided_base_loop[i][j+1]));
- }
-
- face_edges.insert(std::make_pair(divided_base_loop[i].back(),
- divided_base_loop[i].front()));
-
- for (size_t j = 0; j < inc.size(); ++j) {
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &path = *inc[j];
- for (size_t k = 0; k < path.size() - 1; ++k) {
- face_edges.insert(std::make_pair(path[k], path[k+1]));
- face_edges.insert(std::make_pair(path[k+1], path[k]));
- }
- }
-
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > face_loops;
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > hole_loops;
-
- splitFace(face, face_edges, face_loops, hole_loops, vertex_intersections);
-
- if (hole_loops.size()) {
- mergeFacesAndHoles(face, face_loops, hole_loops, hooks);
- }
- std::copy(face_loops.begin(), face_loops.end(), std::back_inserter(face_loops_out));
- } else {
- face_loops_out.push_back(divided_base_loop[i]);
- }
- }
- return true;
- }
-
-
-
- void composeEdgesIntoPaths(const carve::csg::V2Set &edges,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &extra_endpoints,
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &paths,
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &cuts,
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &loops) {
- using namespace carve::csg;
-
- detail::VVSMap vertex_graph;
- detail::VSet endpoints;
- detail::VSet cut_endpoints;
-
- typedef std::vector<carve::mesh::MeshSet<3>::vertex_t *> vvec_t;
- vvec_t path;
-
- std::list<vvec_t> path_list, cut_list, loop_list;
-
- // build graph from edges.
- for (V2Set::const_iterator i = edges.begin(); i != edges.end(); ++i) {
-#if defined(CARVE_DEBUG)
- std::cerr << "### edge: " << (*i).first << " - " << (*i).second << std::endl;
-#endif
- vertex_graph[(*i).first].insert((*i).second);
- vertex_graph[(*i).second].insert((*i).first);
- }
-
- // find the endpoints in the graph.
- // every vertex with number of incident edges != 2 is an endpoint.
- for (detail::VVSMap::const_iterator i = vertex_graph.begin(); i != vertex_graph.end(); ++i) {
- if ((*i).second.size() != 2) {
-#if defined(CARVE_DEBUG)
- std::cerr << "### endpoint: " << (*i).first << std::endl;
-#endif
- endpoints.insert((*i).first);
- if ((*i).second.size() == 1) {
- cut_endpoints.insert((*i).first);
- }
- }
- }
-
- // every vertex on the perimeter of the face is also an endpoint.
- for (size_t i = 0; i < extra_endpoints.size(); ++i) {
- if (vertex_graph.find(extra_endpoints[i]) != vertex_graph.end()) {
-#if defined(CARVE_DEBUG)
- std::cerr << "### extra endpoint: " << extra_endpoints[i] << std::endl;
-#endif
- endpoints.insert(extra_endpoints[i]);
- cut_endpoints.erase(extra_endpoints[i]);
- }
- }
-
- while (endpoints.size()) {
- carve::mesh::MeshSet<3>::vertex_t *v = *endpoints.begin();
- detail::VVSMap::iterator p = vertex_graph.find(v);
- if (p == vertex_graph.end()) {
- endpoints.erase(endpoints.begin());
- continue;
- }
-
- path.clear();
- path.push_back(v);
-
- for (;;) {
- CARVE_ASSERT(p != vertex_graph.end());
-
- // pick a connected vertex to move to.
- if ((*p).second.size() == 0) break;
-
- carve::mesh::MeshSet<3>::vertex_t *n = *((*p).second.begin());
- detail::VVSMap::iterator q = vertex_graph.find(n);
-
- // remove the link.
- (*p).second.erase(n);
- (*q).second.erase(v);
-
- // move on.
- v = n;
- path.push_back(v);
-
- if ((*p).second.size() == 0) vertex_graph.erase(p);
- if ((*q).second.size() == 0) {
- vertex_graph.erase(q);
- q = vertex_graph.end();
- }
-
- p = q;
-
- if (v == path[0] || p == vertex_graph.end() || endpoints.find(v) != endpoints.end()) break;
- }
- CARVE_ASSERT(endpoints.find(path.back()) != endpoints.end());
-
- bool is_cut =
- cut_endpoints.find(path.front()) != cut_endpoints.end() &&
- cut_endpoints.find(path.back()) != cut_endpoints.end();
-
- if (is_cut) {
- cut_list.push_back(vvec_t()); path.swap(cut_list.back());
- } else {
- path_list.push_back(vvec_t()); path.swap(path_list.back());
- }
- }
-
- populateVectorFromList(path_list, paths);
- populateVectorFromList(cut_list, cuts);
-
- // now only loops should remain in the graph.
- while (vertex_graph.size()) {
- detail::VVSMap::iterator p = vertex_graph.begin();
- carve::mesh::MeshSet<3>::vertex_t *v = (*p).first;
- CARVE_ASSERT((*p).second.size() == 2);
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> path;
- path.clear();
- path.push_back(v);
-
- for (;;) {
- CARVE_ASSERT(p != vertex_graph.end());
- // pick a connected vertex to move to.
-
- carve::mesh::MeshSet<3>::vertex_t *n = *((*p).second.begin());
- detail::VVSMap::iterator q = vertex_graph.find(n);
-
- // remove the link.
- (*p).second.erase(n);
- (*q).second.erase(v);
-
- // move on.
- v = n;
- path.push_back(v);
-
- if ((*p).second.size() == 0) vertex_graph.erase(p);
- if ((*q).second.size() == 0) vertex_graph.erase(q);
-
- p = q;
-
- if (v == path[0]) break;
- }
-
- loop_list.push_back(vvec_t()); path.swap(loop_list.back());
- }
-
- populateVectorFromList(loop_list, loops);
- }
-
-
-
- template<typename T>
- std::string ptrstr(const T *ptr) {
- std::ostringstream s;
- s << ptr;
- return s.str().substr(1);
- }
-
-#if 0
- void dumpAsGraph(carve::mesh::MeshSet<3>::face_t *face,
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &base_loop,
- const carve::csg::V2Set &face_edges,
- const carve::csg::V2Set &split_edges) {
- std::map<carve::mesh::MeshSet<3>::vertex_t *, carve::geom2d::P2> proj;
-
- for (size_t i = 0; i < base_loop.size(); ++i) {
- proj[base_loop[i]] = face->project(base_loop[i]->v);
- }
- for (carve::csg::V2Set::const_iterator i = split_edges.begin(); i != split_edges.end(); ++i) {
- proj[(*i).first] = face->project((*i).first->v);
- proj[(*i).second] = face->project((*i).second->v);
- }
-
- {
- carve::geom2d::P2 lo, hi;
- std::map<carve::mesh::MeshSet<3>::vertex_t *, carve::geom2d::P2>::iterator i;
- i = proj.begin();
- lo = hi = (*i).second;
- for (; i != proj.end(); ++i) {
- lo.x = std::min(lo.x, (*i).second.x); lo.y = std::min(lo.y, (*i).second.y);
- hi.x = std::max(hi.x, (*i).second.x); hi.y = std::max(hi.y, (*i).second.y);
- }
- for (i = proj.begin(); i != proj.end(); ++i) {
- (*i).second.x = ((*i).second.x - lo.x) / (hi.x - lo.x) * 10;
- (*i).second.y = ((*i).second.y - lo.y) / (hi.y - lo.y) * 10;
- }
- }
-
- std::cerr << "graph G {\nnode [shape=circle,style=filled,fixedsize=true,width=\".1\",height=\".1\"];\nedge [len=4]\n";
- for (std::map<carve::mesh::MeshSet<3>::vertex_t *, carve::geom2d::P2>::iterator i = proj.begin(); i != proj.end(); ++i) {
- std::cerr << " " << ptrstr((*i).first) << " [pos=\"" << (*i).second.x << "," << (*i).second.y << "!\"];\n";
- }
- for (carve::csg::V2Set::const_iterator i = face_edges.begin(); i != face_edges.end(); ++i) {
- std::cerr << " " << ptrstr((*i).first) << " -- " << ptrstr((*i).second) << ";\n";
- }
- for (carve::csg::V2Set::const_iterator i = split_edges.begin(); i != split_edges.end(); ++i) {
- std::cerr << " " << ptrstr((*i).first) << " -- " << ptrstr((*i).second) << " [color=\"blue\"];\n";
- }
- std::cerr << "};\n";
- }
-#endif
-
- void generateOneFaceLoop(carve::mesh::MeshSet<3>::face_t *face,
- const carve::csg::detail::Data &data,
- const carve::csg::VertexIntersections &vertex_intersections,
- carve::csg::CSG::Hooks &hooks,
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > &face_loops) {
- using namespace carve::csg;
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> base_loop;
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > hole_loops;
-
- /*bool face_edge_intersected = */assembleBaseLoop(face, data, base_loop, hooks);
-
- detail::FV2SMap::const_iterator fse_iter = data.face_split_edges.find(face);
-
- face_loops.clear();
-
- if (fse_iter == data.face_split_edges.end()) {
- // simple case: input face is output face (possibly with the
- // addition of vertices at intersections).
- face_loops.push_back(base_loop);
- return;
- }
-
- // complex case: input face is split into multiple output faces.
- V2Set face_edges;
-
- for (size_t j = 0, je = base_loop.size() - 1; j < je; ++j) {
- face_edges.insert(std::make_pair(base_loop[j], base_loop[j + 1]));
- }
- face_edges.insert(std::make_pair(base_loop.back(), base_loop[0]));
-
- // collect the split edges (as long as they're not on the perimeter)
- const detail::FV2SMap::mapped_type &fse = ((*fse_iter).second);
-
- // split_edges contains all of the edges created by intersections
- // that aren't part of the perimeter of the face.
- V2Set split_edges;
-
- for (detail::FV2SMap::mapped_type::const_iterator
- j = fse.begin(), je = fse.end();
- j != je;
- ++j) {
- carve::mesh::MeshSet<3>::vertex_t *v1 = ((*j).first), *v2 = ((*j).second);
-
- if (face_edges.find(std::make_pair(v1, v2)) == face_edges.end() &&
- face_edges.find(std::make_pair(v2, v1)) == face_edges.end()) {
- // If the edge isn't part of the face perimeter, add it to
- // split_edges.
- split_edges.insert(ordered_edge(v1, v2));
- }
- }
-
- // face is unsplit.
- if (!split_edges.size()) {
- face_loops.push_back(base_loop);
- return;
- }
-
-#if defined(CARVE_DEBUG)
- dumpAsGraph(face, base_loop, face_edges, split_edges);
-#endif
-
-#if 0
- // old face splitting method.
- for (V2Set::const_iterator i = split_edges.begin(); i != split_edges.end(); ++i) {
- face_edges.insert(std::make_pair((*i).first, (*i).second));
- face_edges.insert(std::make_pair((*i).second, (*i).first));
- }
- splitFace(face, face_edges, face_loops, hole_loops, vertex_intersections);
-
- if (hole_loops.size()) {
- mergeFacesAndHoles(face, face_loops, hole_loops, hooks);
- }
- return;
-#endif
-
-#if defined(CARVE_DEBUG)
- std::cerr << "### split_edges.size(): " << split_edges.size() << std::endl;
-#endif
- if (split_edges.size() == 1) {
- // handle the common case of a face that's split by a single edge.
- carve::mesh::MeshSet<3>::vertex_t *v1 = split_edges.begin()->first;
- carve::mesh::MeshSet<3>::vertex_t *v2 = split_edges.begin()->second;
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *>::iterator vi1 = std::find(base_loop.begin(), base_loop.end(), v1);
- std::vector<carve::mesh::MeshSet<3>::vertex_t *>::iterator vi2 = std::find(base_loop.begin(), base_loop.end(), v2);
-
- if (vi1 != base_loop.end() && vi2 != base_loop.end()) {
- // this is an inserted edge that connects two points on the base loop. nice and simple.
- if (vi2 < vi1) std::swap(vi1, vi2);
-
- size_t loop1_size = vi2 - vi1 + 1;
- size_t loop2_size = base_loop.size() + 2 - loop1_size;
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> l1;
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> l2;
-
- l1.reserve(loop1_size);
- l2.reserve(loop2_size);
-
- std::copy(vi1, vi2+1, std::back_inserter(l1));
- std::copy(vi2, base_loop.end(), std::back_inserter(l2));
- std::copy(base_loop.begin(), vi1+1, std::back_inserter(l2));
-
- CARVE_ASSERT(l1.size() == loop1_size);
- CARVE_ASSERT(l2.size() == loop2_size);
-
- face_loops.push_back(l1);
- face_loops.push_back(l2);
-
- return;
- }
-
- // Consider handling cases where one end of the edge touches the
- // perimeter, and where neither end does.
- }
-
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > paths;
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > cuts;
- std::vector<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > loops;
-
- // Take the split edges and compose them into a set of paths and
- // loops. Loops are edge paths that do not touch the boundary, or
- // any other path or loop - they are holes cut out of the centre
- // of the face. Paths are made up of all the other edge segments,
- // and start and end at the face perimeter, or where they meet
- // another path (sometimes both cases will be true).
- composeEdgesIntoPaths(split_edges, base_loop, paths, cuts, loops);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "### paths.size(): " << paths.size() << std::endl;
- std::cerr << "### cuts.size(): " << cuts.size() << std::endl;
- std::cerr << "### loops.size(): " << loops.size() << std::endl;
-#endif
-
- if (!paths.size()) {
- // No complex paths.
- face_loops.push_back(base_loop);
- } else {
- if (processCrossingEdges(face, vertex_intersections, hooks, base_loop, paths, face_loops)) {
- // Worked.
- } else {
- // complex case - fall back to old edge tracing code.
-#if defined(CARVE_DEBUG)
- std::cerr << "### processCrossingEdges failed. Falling back to edge tracing code" << std::endl;
-#endif
- for (size_t i = 0; i < paths.size(); ++i) {
- for (size_t j = 0; j < paths[i].size() - 1; ++j) {
- face_edges.insert(std::make_pair(paths[i][j], paths[i][j+1]));
- face_edges.insert(std::make_pair(paths[i][j+1], paths[i][j]));
- }
- }
- splitFace(face, face_edges, face_loops, hole_loops, vertex_intersections);
- }
- }
-
- // Now merge cuts and loops into face loops.
-
- // every cut creates a hole.
- for (size_t i = 0; i < cuts.size(); ++i) {
- hole_loops.push_back(std::vector<carve::mesh::MeshSet<3>::vertex_t *>());
- hole_loops.back().reserve(2 * cuts[i].size() - 2);
- std::copy(cuts[i].begin(), cuts[i].end(), std::back_inserter(hole_loops.back()));
- if (cuts[i].size() > 2) {
- std::copy(cuts[i].rbegin() + 1, cuts[i].rend() - 1, std::back_inserter(hole_loops.back()));
- }
- }
-
- // every loop creates a hole and a corresponding face.
- for (size_t i = 0; i < loops.size(); ++i) {
- hole_loops.push_back(std::vector<carve::mesh::MeshSet<3>::vertex_t *>());
- hole_loops.back().reserve(loops[i].size()-1);
- std::copy(loops[i].begin(), loops[i].end()-1, std::back_inserter(hole_loops.back()));
-
- face_loops.push_back(std::vector<carve::mesh::MeshSet<3>::vertex_t *>());
- face_loops.back().reserve(loops[i].size()-1);
- std::copy(loops[i].rbegin()+1, loops[i].rend(), std::back_inserter(face_loops.back()));
-
- std::vector<carve::geom2d::P2> projected;
- projected.reserve(face_loops.back().size());
- for (size_t i = 0; i < face_loops.back().size(); ++i) {
- projected.push_back(face->project(face_loops.back()[i]->v));
- }
-
- if (carve::geom2d::signedArea(projected) > 0.0) {
- std::swap(face_loops.back(), hole_loops.back());
- }
- }
-
- // if there are holes, then they need to be merged with faces.
- if (hole_loops.size()) {
- mergeFacesAndHoles(face, face_loops, hole_loops, hooks);
- }
- }
-}
-
-
-
-/**
- * \brief Build a set of face loops for all (split) faces of a Polyhedron.
- *
- * @param[in] poly The polyhedron to process
- * @param[in] data Internal intersection data
- * @param[out] face_loops_out The resulting face loops
- *
- * @return The number of edges generated.
- */
-size_t carve::csg::CSG::generateFaceLoops(carve::mesh::MeshSet<3> *poly,
- const detail::Data &data,
- FaceLoopList &face_loops_out) {
- static carve::TimingName FUNC_NAME("CSG::generateFaceLoops()");
- carve::TimingBlock block(FUNC_NAME);
- size_t generated_edges = 0;
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> base_loop;
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > face_loops;
-
- for (carve::mesh::MeshSet<3>::face_iter i = poly->faceBegin(); i != poly->faceEnd(); ++i) {
- carve::mesh::MeshSet<3>::face_t *face = (*i);
-
-#if defined(CARVE_DEBUG)
- double in_area = 0.0, out_area = 0.0;
-
- {
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> base_loop;
- assembleBaseLoop(face, data, base_loop);
-
- {
- std::vector<carve::geom2d::P2> projected;
- projected.reserve(base_loop.size());
- for (size_t n = 0; n < base_loop.size(); ++n) {
- projected.push_back(face->project(base_loop[n]->v));
- }
-
- in_area = carve::geom2d::signedArea(projected);
- std::cerr << "### in_area=" << in_area << std::endl;
- }
- }
-#endif
-
- generateOneFaceLoop(face, data, vertex_intersections, hooks, face_loops);
-
-#if defined(CARVE_DEBUG)
- {
- V2Set face_edges;
-
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> base_loop;
- assembleBaseLoop(face, data, base_loop);
-
- for (size_t j = 0, je = base_loop.size() - 1; j < je; ++j) {
- face_edges.insert(std::make_pair(base_loop[j+1], base_loop[j]));
- }
- face_edges.insert(std::make_pair(base_loop[0], base_loop.back()));
- for (std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> >::const_iterator fli = face_loops.begin(); fli != face_loops.end(); ++ fli) {
-
- {
- std::vector<carve::geom2d::P2> projected;
- projected.reserve((*fli).size());
- for (size_t n = 0; n < (*fli).size(); ++n) {
- projected.push_back(face->project((*fli)[n]->v));
- }
-
- double area = carve::geom2d::signedArea(projected);
- std::cerr << "### loop_area[" << std::distance((std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> >::const_iterator)face_loops.begin(), fli) << "]=" << area << std::endl;
- out_area += area;
- }
-
- const std::vector<carve::mesh::MeshSet<3>::vertex_t *> &fl = *fli;
- for (size_t j = 0, je = fl.size() - 1; j < je; ++j) {
- face_edges.insert(std::make_pair(fl[j], fl[j+1]));
- }
- face_edges.insert(std::make_pair(fl.back(), fl[0]));
- }
- for (V2Set::const_iterator j = face_edges.begin(); j != face_edges.end(); ++j) {
- if (face_edges.find(std::make_pair((*j).second, (*j).first)) == face_edges.end()) {
- std::cerr << "### error: unmatched edge [" << (*j).first << "-" << (*j).second << "]" << std::endl;
- }
- }
- std::cerr << "### out_area=" << out_area << std::endl;
- if (out_area != in_area) {
- std::cerr << "### error: area does not match. delta = " << (out_area - in_area) << std::endl;
- // CARVE_ASSERT(fabs(out_area - in_area) < 1e-5);
- }
- }
-#endif
-
- // now record all the resulting face loops.
-#if defined(CARVE_DEBUG)
- std::cerr << "### ======" << std::endl;
-#endif
- for (std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> >::const_iterator
- f = face_loops.begin(), fe = face_loops.end();
- f != fe;
- ++f) {
-#if defined(CARVE_DEBUG)
- std::cerr << "### loop:";
- for (size_t i = 0; i < (*f).size(); ++i) {
- std::cerr << " " << (*f)[i];
- }
- std::cerr << std::endl;
-#endif
-
- face_loops_out.append(new FaceLoop(face, *f));
- generated_edges += (*f).size();
- }
-#if defined(CARVE_DEBUG)
- std::cerr << "### ======" << std::endl;
-#endif
- }
- return generated_edges;
-}
diff --git a/extern/carve/lib/intersect_group.cpp b/extern/carve/lib/intersect_group.cpp
deleted file mode 100644
index ec28791150a..00000000000
--- a/extern/carve/lib/intersect_group.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/csg.hpp>
-#include <carve/timing.hpp>
-
-#include "csg_detail.hpp"
-#include "intersect_common.hpp"
-
-void carve::csg::CSG::makeEdgeMap(const carve::csg::FaceLoopList &loops,
- size_t edge_count,
- detail::LoopEdges &edge_map) {
-#if defined(UNORDERED_COLLECTIONS_SUPPORT_RESIZE)
- edge_map.resize(edge_count);
-#endif
-
- for (carve::csg::FaceLoop *i = loops.head; i; i = i->next) {
- edge_map.addFaceLoop(i);
- i->group = NULL;
- }
-}
-
-#include <carve/polyline.hpp>
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
-void writePLY(const std::string &out_file, const carve::mesh::MeshSet<3> *poly, bool ascii);
-void writePLY(const std::string &out_file, const carve::line::PolylineSet *lines, bool ascii);
-#endif
-
-void carve::csg::CSG::findSharedEdges(const detail::LoopEdges &edge_map_a,
- const detail::LoopEdges &edge_map_b,
- V2Set &shared_edges) {
- for (detail::LoopEdges::const_iterator
- i = edge_map_a.begin(), e = edge_map_a.end();
- i != e;
- ++i) {
- detail::LoopEdges::const_iterator j = edge_map_b.find((*i).first);
- if (j != edge_map_b.end()) {
- shared_edges.insert((*i).first);
- }
- }
-
-#if defined(CARVE_DEBUG)
- detail::VVSMap edge_graph;
-
- for (V2Set::const_iterator i = shared_edges.begin(); i != shared_edges.end(); ++i) {
- edge_graph[(*i).first].insert((*i).second);
- edge_graph[(*i).second].insert((*i).first);
- }
-
- std::cerr << "*** testing consistency of edge graph" << std::endl;
- for (detail::VVSMap::const_iterator i = edge_graph.begin(); i != edge_graph.end(); ++i) {
- if ((*i).second.size() > 2) {
- std::cerr << "branch at: " << (*i).first << std::endl;
- }
- if ((*i).second.size() == 1) {
- std::cerr << "endpoint at: " << (*i).first << std::endl;
- std::cerr << "coordinate: " << (*i).first->v << std::endl;
- }
- }
-
- {
- carve::line::PolylineSet intersection_graph;
- intersection_graph.vertices.resize(edge_graph.size());
- std::map<const carve::mesh::MeshSet<3>::vertex_t *, size_t> vmap;
-
- size_t j = 0;
- for (detail::VVSMap::const_iterator i = edge_graph.begin(); i != edge_graph.end(); ++i) {
- intersection_graph.vertices[j].v = (*i).first->v;
- vmap[(*i).first] = j++;
- }
-
- while (edge_graph.size()) {
- detail::VVSMap::iterator prior_i = edge_graph.begin();
- carve::mesh::MeshSet<3>::vertex_t *prior = (*prior_i).first;
- std::vector<size_t> connected;
- connected.push_back(vmap[prior]);
- while (prior_i != edge_graph.end() && (*prior_i).second.size()) {
- carve::mesh::MeshSet<3>::vertex_t *next = *(*prior_i).second.begin();
- detail::VVSMap::iterator next_i = edge_graph.find(next);
- CARVE_ASSERT(next_i != edge_graph.end());
- connected.push_back(vmap[next]);
- (*prior_i).second.erase(next);
- (*next_i).second.erase(prior);
- if (!(*prior_i).second.size()) { edge_graph.erase(prior_i); prior_i = edge_graph.end(); }
- if (!(*next_i).second.size()) { edge_graph.erase(next_i); next_i = edge_graph.end(); }
- prior_i = next_i;
- prior = next;
- }
- bool closed = connected.front() == connected.back();
- for (size_t k = 0; k < connected.size(); ++k) {
- std::cerr << " " << connected[k];
- }
- std::cerr << std::endl;
- intersection_graph.addPolyline(closed, connected.begin(), connected.end());
- }
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- std::string out("/tmp/intersection.ply");
- ::writePLY(out, &intersection_graph, true);
-#endif
- }
-
- std::cerr << "*** edge graph consistency test done" << std::endl;
-#endif
-}
-
-
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
-static carve::mesh::MeshSet<3> *groupToPolyhedron(const carve::csg::FaceLoopGroup &grp) {
- const carve::csg::FaceLoopList &fl = grp.face_loops;
- std::vector<carve::mesh::MeshSet<3>::face_t *> faces;
- faces.reserve(fl.size());
- for (carve::csg::FaceLoop *f = fl.head; f; f = f->next) {
- faces.push_back(f->orig_face->create(f->vertices.begin(), f->vertices.end(), false));
- }
- carve::mesh::MeshSet<3> *poly = new carve::mesh::MeshSet<3>(faces);
-
- poly->canonicalize();
- return poly;
-}
-#endif
-
-
-
-void carve::csg::CSG::groupFaceLoops(carve::mesh::MeshSet<3> *src,
- carve::csg::FaceLoopList &face_loops,
- const carve::csg::detail::LoopEdges &loop_edges,
- const carve::csg::V2Set &no_cross,
- carve::csg::FLGroupList &out_loops) {
- // Find all the groups of face loops that are connected by edges
- // that are not part of no_cross.
- // this could potentially be done with a disjoint set data-structure.
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- static int call_num = 0;
- call_num++;
-#endif
-
- static carve::TimingName GROUP_FACE_LOOPS("groupFaceLoops()");
-
- carve::TimingBlock block(GROUP_FACE_LOOPS);
-
- int tag_num = 0;
- while (face_loops.size()) {
- out_loops.push_back(FaceLoopGroup(src));
- carve::csg::FaceLoopGroup &group = (out_loops.back());
- carve::csg::FaceLoopList &curr = (group.face_loops);
- carve::csg::V2Set &perim = (group.perimeter);
-
- carve::csg::FaceLoop *expand = face_loops.head;
-
- expand->group = &group;
- face_loops.remove(expand);
- curr.append(expand);
-
- while (expand) {
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &loop = (expand->vertices);
- carve::mesh::MeshSet<3>::vertex_t *v1, *v2;
-
- v1 = loop.back();
- for (size_t i = 0; i < loop.size(); ++i) {
- v2 = loop[i];
-
- carve::csg::V2Set::const_iterator nc = no_cross.find(std::make_pair(v1, v2));
- if (nc == no_cross.end()) {
- carve::csg::detail::LoopEdges::const_iterator j;
-
- j = loop_edges.find(std::make_pair(v1, v2));
- if (j != loop_edges.end()) {
- for (std::list<carve::csg::FaceLoop *>::const_iterator
- k = (*j).second.begin(), ke = (*j).second.end();
- k != ke; ++k) {
- if ((*k)->group != NULL ||
- (*k)->orig_face->mesh != expand->orig_face->mesh) continue;
- face_loops.remove((*k));
- curr.append((*k));
- (*k)->group = &group;
- }
- }
-
- j = loop_edges.find(std::make_pair(v2, v1));
- if (j != loop_edges.end()) {
- for (std::list<carve::csg::FaceLoop *>::const_iterator
- k = (*j).second.begin(), ke = (*j).second.end();
- k != ke; ++k) {
- if ((*k)->group != NULL ||
- (*k)->orig_face->mesh != expand->orig_face->mesh) continue;
- face_loops.remove((*k));
- curr.append((*k));
- (*k)->group = &group;
- }
- }
- } else {
- perim.insert(std::make_pair(v1, v2));
- }
- v1 = v2;
- }
- expand = expand->next;
- }
- tag_num++;
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- {
- carve::mesh::MeshSet<3> *poly = groupToPolyhedron(group);
- char buf[128];
- sprintf(buf, "/tmp/group-%d-%p.ply", call_num, &curr);
- std::string out(buf);
- ::writePLY(out, poly, false);
- delete poly;
- }
-#endif
- }
-}
diff --git a/extern/carve/lib/intersect_half_classify_group.cpp b/extern/carve/lib/intersect_half_classify_group.cpp
deleted file mode 100644
index 74c37c30bfe..00000000000
--- a/extern/carve/lib/intersect_half_classify_group.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/csg.hpp>
-#include <carve/debug_hooks.hpp>
-
-#include <list>
-#include <set>
-#include <iostream>
-
-#include <algorithm>
-
-#include "intersect_common.hpp"
-#include "intersect_classify_common.hpp"
-#include "intersect_classify_common_impl.hpp"
-
-namespace carve {
- namespace csg {
-
- namespace {
- struct GroupPoly : public CSG::Collector {
- carve::mesh::MeshSet<3> *want_groups_from;
- std::list<std::pair<FaceClass, carve::mesh::MeshSet<3> *> > &out;
-
- GroupPoly(carve::mesh::MeshSet<3> *poly,
- std::list<std::pair<FaceClass, carve::mesh::MeshSet<3> *> > &_out) : CSG::Collector(), want_groups_from(poly), out(_out) {
- }
-
- virtual ~GroupPoly() {
- }
-
- virtual void collect(FaceLoopGroup *grp, CSG::Hooks & /* hooks */) {
- if (grp->face_loops.head->orig_face->mesh->meshset != want_groups_from) return;
-
- std::list<ClassificationInfo> &cinfo = (grp->classification);
- if (cinfo.size() == 0) {
- std::cerr << "WARNING! group " << grp << " has no classification info!" << std::endl;
- return;
- }
- // XXX: check all the cinfo elements for consistency.
- FaceClass fc = cinfo.front().classification;
-
- std::vector<carve::mesh::MeshSet<3>::face_t *> faces;
- faces.reserve(grp->face_loops.size());
- for (FaceLoop *loop = grp->face_loops.head; loop != NULL; loop = loop->next) {
- faces.push_back(loop->orig_face->create(loop->vertices.begin(), loop->vertices.end(), false));
- }
-
- out.push_back(std::make_pair(fc, new carve::mesh::MeshSet<3>(faces)));
- }
-
- virtual carve::mesh::MeshSet<3> *done(CSG::Hooks & /* hooks */) {
- return NULL;
- }
- };
-
- class FaceMaker {
- public:
-
- bool pointOn(VertexClassification &vclass, FaceLoop *f, size_t index) const {
- return vclass[f->vertices[index]].cls[0] == POINT_ON;
- }
-
- void explain(FaceLoop *f, size_t index, PointClass pc) const {
-#if defined(CARVE_DEBUG)
- std::cerr << "face loop " << f << " from poly b is easy because vertex " << index << " (" << f->vertices[index]->v << ") is " << ENUM(pc) << std::endl;
-#endif
- }
- };
-
- class HalfClassifyFaceGroups {
- HalfClassifyFaceGroups &operator=(const HalfClassifyFaceGroups &);
-
- public:
- std::list<std::pair<FaceClass, carve::mesh::MeshSet<3> *> > &b_out;
- CSG::Hooks &hooks;
-
- HalfClassifyFaceGroups(std::list<std::pair<FaceClass, carve::mesh::MeshSet<3> *> > &c, CSG::Hooks &h) : b_out(c), hooks(h) {
- }
-
- void classifySimple(FLGroupList &a_loops_grouped,
- FLGroupList &b_loops_grouped,
- VertexClassification & /* vclass */,
- carve::mesh::MeshSet<3> *poly_a,
- carve::mesh::MeshSet<3> *poly_b) const {
- GroupPoly group_poly(poly_b, b_out);
- performClassifySimpleOnFaceGroups(a_loops_grouped, b_loops_grouped, poly_a, poly_b, group_poly, hooks);
-#if defined(CARVE_DEBUG)
- std::cerr << "after removal of simple on groups: " << b_loops_grouped.size() << " b groups" << std::endl;
-#endif
- }
-
- void classifyEasy(FLGroupList & /* a_loops_grouped */,
- FLGroupList &b_loops_grouped,
- VertexClassification & vclass,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- carve::mesh::MeshSet<3> *poly_b,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_b_rtree) const {
- GroupPoly group_poly(poly_b, b_out);
- performClassifyEasyFaceGroups(b_loops_grouped, poly_a, poly_a_rtree, vclass, FaceMaker(), group_poly, hooks);
-#if defined(CARVE_DEBUG)
- std::cerr << "after removal of easy groups: " << b_loops_grouped.size() << " b groups" << std::endl;
-#endif
- }
-
- void classifyHard(FLGroupList & /* a_loops_grouped */,
- FLGroupList &b_loops_grouped,
- VertexClassification & /* vclass */,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- carve::mesh::MeshSet<3> *poly_b,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_b_rtree) const {
- GroupPoly group_poly(poly_b, b_out);
- performClassifyHardFaceGroups(b_loops_grouped, poly_a, poly_a_rtree, FaceMaker(), group_poly, hooks);
-#if defined(CARVE_DEBUG)
- std::cerr << "after removal of hard groups: " << b_loops_grouped.size() << " b groups" << std::endl;
-#endif
-
- }
-
- void faceLoopWork(FLGroupList & /* a_loops_grouped */,
- FLGroupList &b_loops_grouped,
- VertexClassification & /* vclass */,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- carve::mesh::MeshSet<3> *poly_b,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_b_rtree) const {
- GroupPoly group_poly(poly_b, b_out);
- performFaceLoopWork(poly_a, poly_a_rtree, b_loops_grouped, *this, group_poly, hooks);
- }
-
- void postRemovalCheck(FLGroupList & /* a_loops_grouped */,
- FLGroupList &b_loops_grouped) const {
-#if defined(CARVE_DEBUG)
- std::cerr << "after removal of on groups: " << b_loops_grouped.size() << " b groups" << std::endl;
-#endif
- }
-
- bool faceLoopSanityChecker(FaceLoopGroup &i) const {
- return false;
- return i.face_loops.size() != 1;
- }
-
- void finish(FLGroupList &a_loops_grouped,FLGroupList &b_loops_grouped) const {
-#if defined(CARVE_DEBUG)
- if (a_loops_grouped.size() || b_loops_grouped.size())
- std::cerr << "UNCLASSIFIED! a=" << a_loops_grouped.size() << ", b=" << b_loops_grouped.size() << std::endl;
-#endif
- }
- };
- }
-
- void CSG::halfClassifyFaceGroups(const V2Set & /* shared_edges */,
- VertexClassification &vclass,
- carve::mesh::MeshSet<3> *poly_a,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_a_rtree,
- FLGroupList &a_loops_grouped,
- const detail::LoopEdges & /* a_edge_map */,
- carve::mesh::MeshSet<3> *poly_b,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *poly_b_rtree,
- FLGroupList &b_loops_grouped,
- const detail::LoopEdges & /* b_edge_map */,
- std::list<std::pair<FaceClass, carve::mesh::MeshSet<3> *> > &b_out) {
- HalfClassifyFaceGroups classifier(b_out, hooks);
- GroupPoly group_poly(poly_b, b_out);
- performClassifyFaceGroups(
- a_loops_grouped,
- b_loops_grouped,
- vclass,
- poly_a,
- poly_a_rtree,
- poly_b,
- poly_b_rtree,
- classifier,
- group_poly,
- hooks);
- }
-
- }
-}
diff --git a/extern/carve/lib/intersection.cpp b/extern/carve/lib/intersection.cpp
deleted file mode 100644
index fe694e32d14..00000000000
--- a/extern/carve/lib/intersection.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <algorithm>
-
-#include <carve/carve.hpp>
-#include <carve/poly.hpp>
-#include <carve/timing.hpp>
-#include <carve/intersection.hpp>
-
-
-
-void carve::csg::Intersections::collect(const IObj &obj,
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> *collect_v,
- std::vector<carve::mesh::MeshSet<3>::edge_t *> *collect_e,
- std::vector<carve::mesh::MeshSet<3>::face_t *> *collect_f) const {
- carve::csg::Intersections::const_iterator i = find(obj);
- if (i != end()) {
- Intersections::mapped_type::const_iterator a, b;
- for (a = (*i).second.begin(), b = (*i).second.end(); a != b; ++a) {
- switch ((*a).first.obtype) {
- case carve::csg::IObj::OBTYPE_VERTEX:
- if (collect_v) collect_v->push_back((*a).first.vertex);
- break;
- case carve::csg::IObj::OBTYPE_EDGE:
- if (collect_e) collect_e->push_back((*a).first.edge);
- break;
- case carve::csg::IObj::OBTYPE_FACE:
- if (collect_f) collect_f->push_back((*a).first.face);
- break;
- default:
- throw carve::exception("should not happen " __FILE__ ":" XSTR(__LINE__));
- }
- }
- }
-}
-
-
-
-bool carve::csg::Intersections::intersectsFace(carve::mesh::MeshSet<3>::vertex_t *v,
- carve::mesh::MeshSet<3>::face_t *f) const {
- const_iterator i = find(v);
- if (i != end()) {
- mapped_type::const_iterator a, b;
-
- for (a = (*i).second.begin(), b = (*i).second.end(); a != b; ++a) {
- switch ((*a).first.obtype) {
- case IObj::OBTYPE_VERTEX: {
- const carve::mesh::MeshSet<3>::edge_t *edge = f->edge;
- do {
- if (edge->vert == (*a).first.vertex) return true;
- edge = edge->next;
- } while (edge != f->edge);
- break;
- }
- case carve::csg::IObj::OBTYPE_EDGE: {
- const carve::mesh::MeshSet<3>::edge_t *edge = f->edge;
- do {
- if (edge == (*a).first.edge) return true;
- edge = edge->next;
- } while (edge != f->edge);
- break;
- }
- case carve::csg::IObj::OBTYPE_FACE: {
- if ((*a).first.face == f) return true;
- break;
- }
- default:
- throw carve::exception("should not happen " __FILE__ ":" XSTR(__LINE__));
- }
- }
- }
- return false;
-}
diff --git a/extern/carve/lib/math.cpp b/extern/carve/lib/math.cpp
deleted file mode 100644
index 3b7f95193c1..00000000000
--- a/extern/carve/lib/math.cpp
+++ /dev/null
@@ -1,355 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/math.hpp>
-#include <carve/matrix.hpp>
-
-#include <iostream>
-#include <limits>
-
-#include <stdio.h>
-
-#define M_2PI_3 2.0943951023931953
-#define M_SQRT_3_4 0.8660254037844386
-#define EPS std::numeric_limits<double>::epsilon()
-
-namespace carve {
- namespace math {
-
- struct Root {
- double root;
- int multiplicity;
-
- Root(double r) : root(r), multiplicity(1) {}
- Root(double r, int m) : root(r), multiplicity(m) {}
- };
-
- namespace {
-#if 0
- void cplx_sqrt(double re, double im,
- double &re_1, double &im_1,
- double &re_2, double &im_2) {
- if (re == 0.0 && im == 0.0) {
- re_1 = re_2 = re;
- im_1 = im_2 = im;
- } else {
- double d = sqrt(re * re + im * im);
- re_1 = sqrt((d + re) / 2.0);
- re_2 = re_1;
- im_1 = fabs(sqrt((d - re) / 2.0));
- im_2 = -im_1;
- }
- }
-#endif
-
-#if 0
- void cplx_cbrt(double re, double im,
- double &re_1, double &im_1,
- double &re_2, double &im_2,
- double &re_3, double &im_3) {
- if (re == 0.0 && im == 0.0) {
- re_1 = re_2 = re_3 = re;
- im_1 = im_2 = im_3 = im;
- } else {
- double r = cbrt(sqrt(re * re + im * im));
- double t = atan2(im, re) / 3.0;
- re_1 = r * cos(t);
- im_1 = r * sin(t);
- re_2 = r * cos(t + M_TWOPI / 3.0);
- im_2 = r * sin(t + M_TWOPI / 3.0);
- re_3 = r * cos(t + M_TWOPI * 2.0 / 3.0);
- im_3 = r * sin(t + M_TWOPI * 2.0 / 3.0);
- }
- }
-#endif
-
- void add_root(std::vector<Root> &roots, double root) {
- for (size_t i = 0; i < roots.size(); ++i) {
- if (roots[i].root == root) {
- roots[i].multiplicity++;
- return;
- }
- }
- roots.push_back(Root(root));
- }
-
- void linear_roots(double c1, double c0, std::vector<Root> &roots) {
- roots.push_back(Root(c0 / c1));
- }
-
- void quadratic_roots(double c2, double c1, double c0, std::vector<Root> &roots) {
- if (fabs(c2) < EPS) {
- linear_roots(c1, c0, roots);
- return;
- }
-
- double p = 0.5 * c1 / c2;
- double dis = p * p - c0 / c2;
-
- if (dis > 0.0) {
- dis = sqrt(dis);
- if (-p - dis != -p + dis) {
- roots.push_back(Root(-p - dis));
- roots.push_back(Root(-p + dis));
- } else {
- roots.push_back(Root(-p, 2));
- }
- }
- }
-
- void cubic_roots(double c3, double c2, double c1, double c0, std::vector<Root> &roots) {
- int n_sol = 0;
- double _r[3];
-
- if (fabs(c3) < EPS) {
- quadratic_roots(c2, c1, c0, roots);
- return;
- }
-
- if (fabs(c0) < EPS) {
- quadratic_roots(c3, c2, c1, roots);
- add_root(roots, 0.0);
- return;
- }
-
- double xN = -c2 / (3.0 * c3);
- double yN = c0 + xN * (c1 + xN * (c2 + c3 * xN));
-
- double delta_sq = (c2 * c2 - 3.0 * c3 * c1) / (9.0 * c3 * c3);
- double h_sq = 4.0 / 9.0 * (c2 * c2 - 3.0 * c3 * c1) * (delta_sq * delta_sq);
- double dis = yN * yN - h_sq;
-
- if (dis > EPS) {
- // One real root, two complex roots.
-
- double dis_sqrt = sqrt(dis);
- double r_p = yN - dis_sqrt;
- double r_q = yN + dis_sqrt;
- double p = cbrt(fabs(r_p)/(2.0 * c3));
- double q = cbrt(fabs(r_q)/(2.0 * c3));
-
- if (r_p > 0.0) p = -p;
- if (r_q > 0.0) q = -q;
-
- _r[0] = xN + p + q;
- n_sol = 1;
-
- double re = xN - p * .5 - q * .5;
- double im = p * M_SQRT_3_4 - q * M_SQRT_3_4;
-
- // root 2: xN + p * exp(M_2PI_3.i) + q * exp(-M_2PI_3.i);
- // root 3: complex conjugate of root 2
-
- if (im < EPS) {
- _r[1] = _r[2] = re;
- n_sol += 2;
- }
- } else if (dis < -EPS) {
- // Three distinct real roots.
- double theta = acos(-yN / sqrt(h_sq)) / 3.0;
- double delta = sqrt(c2 * c2 - 3.0 * c3 * c1) / (3.0 * c3);
-
- _r[0] = xN + (2.0 * delta) * cos(theta);
- _r[1] = xN + (2.0 * delta) * cos(M_2PI_3 - theta);
- _r[2] = xN + (2.0 * delta) * cos(M_2PI_3 + theta);
- n_sol = 3;
- } else {
- // Three real roots (two or three equal).
- double r = yN / (2.0 * c3);
- double delta = cbrt(r);
-
- _r[0] = xN + delta;
- _r[1] = xN + delta;
- _r[2] = xN - 2.0 * delta;
- n_sol = 3;
- }
-
- for (int i=0; i < n_sol; i++) {
- add_root(roots, _r[i]);
- }
- }
- }
-
- static void U(const Matrix3 &m,
- double l,
- double u[6],
- double &u_max,
- int &u_argmax) {
- u[0] = (m._22 - l) * (m._33 - l) - m._23 * m._23;
- u[1] = m._13 * m._23 - m._12 * (m._33 - l);
- u[2] = m._12 * m._23 - m._13 * (m._22 - l);
- u[3] = (m._11 - l) * (m._33 - l) - m._13 * m._13;
- u[4] = m._12 * m._13 - m._23 * (m._11 - l);
- u[5] = (m._11 - l) * (m._22 - l) - m._12 * m._12;
-
- u_max = -1.0;
- u_argmax = -1;
-
- for (int i = 0; i < 6; ++i) {
- if (u_max < fabs(u[i])) { u_max = fabs(u[i]); u_argmax = i; }
- }
- }
-
- static void eig1(const Matrix3 &m, double l, carve::geom::vector<3> &e) {
- double u[6];
- double u_max;
- int u_argmax;
-
- U(m, l, u, u_max, u_argmax);
-
- switch(u_argmax) {
- case 0:
- e.x = u[0]; e.y = u[1]; e.z = u[2]; break;
- case 1: case 3:
- e.x = u[1]; e.y = u[3]; e.z = u[4]; break;
- case 2: case 4: case 5:
- e.x = u[2]; e.y = u[4]; e.z = u[5]; break;
- }
- e.normalize();
- }
-
- static void eig2(const Matrix3 &m, double l, carve::geom::vector<3> &e1, carve::geom::vector<3> &e2) {
- double u[6];
- double u_max;
- int u_argmax;
-
- U(m, l, u, u_max, u_argmax);
-
- switch(u_argmax) {
- case 0: case 1:
- e1.x = -m._12; e1.y = m._11; e1.z = 0.0;
- e2.x = -m._13 * m._11; e2.y = -m._13 * m._12; e2.z = m._11 * m._11 + m._12 * m._12;
- break;
- case 2:
- e1.x = m._12; e1.y = 0.0; e1.z = -m._11;
- e2.x = -m._12 * m._11; e2.y = m._11 * m._11 + m._13 * m._13; e2.z = -m._12 * m._13;
- break;
- case 3: case 4:
- e1.x = 0.0; e1.y = -m._23; e1.z = -m._22;
- e2.x = m._22 * m._22 + m._23 * m._23; e2.y = -m._12 * m._22; e2.z = -m._12 * m._23;
- break;
- case 5:
- e1.x = 0.0; e1.y = -m._33; e1.z = m._23;
- e2.x = m._23 * m._23 + m._33 * m._33; e2.y = -m._13 * m._23; e2.z = -m._13 * m._33;
- }
- e1.normalize();
- e2.normalize();
- }
-
-#if 0
- static void eig3(const Matrix3 &m,
- double l,
- carve::geom::vector<3> &e1,
- carve::geom::vector<3> &e2,
- carve::geom::vector<3> &e3) {
- e1.x = 1.0; e1.y = 0.0; e1.z = 0.0;
- e2.x = 0.0; e2.y = 1.0; e2.z = 0.0;
- e3.x = 0.0; e3.y = 0.0; e3.z = 1.0;
- }
-#endif
-
- void eigSolveSymmetric(const Matrix3 &m,
- double &l1, carve::geom::vector<3> &e1,
- double &l2, carve::geom::vector<3> &e2,
- double &l3, carve::geom::vector<3> &e3) {
- double c0 =
- m._11 * m._22 * m._33 +
- 2.0 * m._12 * m._13 * m._23 -
- m._11 * m._23 * m._23 -
- m._22 * m._13 * m._13 -
- m._33 * m._12 * m._12;
- double c1 =
- m._11 * m._22 -
- m._12 * m._12 +
- m._11 * m._33 -
- m._13 * m._13 +
- m._22 * m._33 -
- m._23 * m._23;
- double c2 =
- m._11 +
- m._22 +
- m._33;
-
- double a = (3.0 * c1 - c2 * c2) / 3.0;
- double b = (-2.0 * c2 * c2 * c2 + 9.0 * c1 * c2 - 27.0 * c0) / 27.0;
-
- double Q = b * b / 4.0 + a * a * a / 27.0;
-
- if (fabs(Q) < 1e-16) {
- l1 = m._11; e1.x = 1.0; e1.y = 0.0; e1.z = 0.0;
- l2 = m._22; e2.x = 0.0; e2.y = 1.0; e2.z = 0.0;
- l3 = m._33; e3.x = 0.0; e3.y = 0.0; e3.z = 1.0;
- } else if (Q > 0) {
- l1 = l2 = c2 / 3.0 + cbrt(b / 2.0);
- l3 = c2 / 3.0 - 2.0 * cbrt(b / 2.0);
-
- eig2(m, l1, e1, e2);
- eig1(m, l3, e3);
- } else if (Q < 0) {
- double t = atan2(sqrt(-Q), -b / 2.0);
- double cos_t3 = cos(t / 3.0);
- double sin_t3 = sin(t / 3.0);
- double r = cbrt(sqrt(b * b / 4.0 - Q));
-
- l1 = c2 / 3.0 + 2 * r * cos_t3;
- l2 = c2 / 3.0 - r * (cos_t3 + M_SQRT_3 * sin_t3);
- l3 = c2 / 3.0 - r * (cos_t3 - M_SQRT_3 * sin_t3);
-
- eig1(m, l1, e1);
- eig1(m, l2, e2);
- eig1(m, l3, e3);
- }
- }
-
- void eigSolve(const Matrix3 &m, double &l1, double &l2, double &l3) {
- double c3, c2, c1, c0;
- std::vector<Root> roots;
-
- c3 = -1.0;
- c2 = m._11 + m._22 + m._33;
- c1 =
- -(m._22 * m._33 + m._11 * m._22 + m._11 * m._33)
- +(m._23 * m._32 + m._13 * m._31 + m._12 * m._21);
- c0 =
- +(m._11 * m._22 - m._12 * m._21) * m._33
- -(m._11 * m._23 - m._13 * m._21) * m._32
- +(m._12 * m._23 - m._13 * m._22) * m._31;
-
- cubic_roots(c3, c2, c1, c0, roots);
-
- for (size_t i = 0; i < roots.size(); i++) {
- Matrix3 M(m);
- M._11 -= roots[i].root;
- M._22 -= roots[i].root;
- M._33 -= roots[i].root;
- // solve M.v = 0
- }
-
- std::cerr << "n_roots=" << roots.size() << std::endl;
- for (size_t i = 0; i < roots.size(); i++) {
- fprintf(stderr, " %.24f(%d)", roots[i].root, roots[i].multiplicity);
- }
- std::cerr << std::endl;
- }
-
- }
-}
-
diff --git a/extern/carve/lib/mesh.cpp b/extern/carve/lib/mesh.cpp
deleted file mode 100644
index fe66927a707..00000000000
--- a/extern/carve/lib/mesh.cpp
+++ /dev/null
@@ -1,1215 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/mesh.hpp>
-#include <carve/mesh_impl.hpp>
-#include <carve/rtree.hpp>
-
-#include <carve/poly.hpp>
-
-namespace {
- inline double CALC_X(const carve::geom::plane<3> &p, double y, double z) { return -(p.d + p.N.y * y + p.N.z * z) / p.N.x; }
- inline double CALC_Y(const carve::geom::plane<3> &p, double x, double z) { return -(p.d + p.N.x * x + p.N.z * z) / p.N.y; }
- inline double CALC_Z(const carve::geom::plane<3> &p, double x, double y) { return -(p.d + p.N.x * x + p.N.y * y) / p.N.z; }
-
- carve::geom::vector<2> _project_1(const carve::geom::vector<3> &v) {
- return carve::geom::VECTOR(v.z, v.y);
- }
-
- carve::geom::vector<2> _project_2(const carve::geom::vector<3> &v) {
- return carve::geom::VECTOR(v.x, v.z);
- }
-
- carve::geom::vector<2> _project_3(const carve::geom::vector<3> &v) {
- return carve::geom::VECTOR(v.y, v.x);
- }
-
- carve::geom::vector<2> _project_4(const carve::geom::vector<3> &v) {
- return carve::geom::VECTOR(v.y, v.z);
- }
-
- carve::geom::vector<2> _project_5(const carve::geom::vector<3> &v) {
- return carve::geom::VECTOR(v.z, v.x);
- }
-
- carve::geom::vector<2> _project_6(const carve::geom::vector<3> &v) {
- return carve::geom::VECTOR(v.x, v.y);
- }
-
- carve::geom::vector<3> _unproject_1(const carve::geom::vector<2> &p, const carve::geom3d::Plane &plane) {
- return carve::geom::VECTOR(CALC_X(plane, p.y, p.x), p.y, p.x);
- }
-
- carve::geom::vector<3> _unproject_2(const carve::geom::vector<2> &p, const carve::geom3d::Plane &plane) {
- return carve::geom::VECTOR(p.x, CALC_Y(plane, p.x, p.y), p.y);
- }
-
- carve::geom::vector<3> _unproject_3(const carve::geom::vector<2> &p, const carve::geom3d::Plane &plane) {
- return carve::geom::VECTOR(p.y, p.x, CALC_Z(plane, p.y, p.x));
- }
-
- carve::geom::vector<3> _unproject_4(const carve::geom::vector<2> &p, const carve::geom3d::Plane &plane) {
- return carve::geom::VECTOR(CALC_X(plane, p.x, p.y), p.x, p.y);
- }
-
- carve::geom::vector<3> _unproject_5(const carve::geom::vector<2> &p, const carve::geom3d::Plane &plane) {
- return carve::geom::VECTOR(p.y, CALC_Y(plane, p.y, p.x), p.x);
- }
-
- carve::geom::vector<3> _unproject_6(const carve::geom::vector<2> &p, const carve::geom3d::Plane &plane) {
- return carve::geom::VECTOR(p.x, p.y, CALC_Z(plane, p.x, p.y));
- }
-
- static carve::geom::vector<2> (*project_tab[2][3])(const carve::geom::vector<3> &) = {
- { &_project_1, &_project_2, &_project_3 },
- { &_project_4, &_project_5, &_project_6 }
- };
-
- static carve::geom::vector<3> (*unproject_tab[2][3])(const carve::geom::vector<2> &, const carve::geom3d::Plane &) = {
- { &_unproject_1, &_unproject_2, &_unproject_3 },
- { &_unproject_4, &_unproject_5, &_unproject_6 }
- };
-
-}
-
-namespace carve {
- namespace mesh {
-
-
-
- template<unsigned ndim>
- typename Face<ndim>::project_t Face<ndim>::getProjector(bool positive_facing, int axis) const {
- return NULL;
- }
-
-
-
- template<>
- Face<3>::project_t Face<3>::getProjector(bool positive_facing, int axis) const {
- return project_tab[positive_facing ? 1 : 0][axis];
- }
-
-
-
- template<unsigned ndim>
- typename Face<ndim>::unproject_t Face<ndim>::getUnprojector(bool positive_facing, int axis) const {
- return NULL;
- }
-
-
-
- template<>
- Face<3>::unproject_t Face<3>::getUnprojector(bool positive_facing, int axis) const {
- return unproject_tab[positive_facing ? 1 : 0][axis];
- }
-
-
-
- template<unsigned ndim>
- bool Face<ndim>::containsPoint(const vector_t &p) const {
- if (!carve::math::ZERO(carve::geom::distance(plane, p))) return false;
- // return pointInPolySimple(vertices, projector(), (this->*project)(p));
- std::vector<carve::geom::vector<2> > verts;
- getProjectedVertices(verts);
- return carve::geom2d::pointInPoly(verts, project(p)).iclass != carve::POINT_OUT;
- }
-
-
-
- template<unsigned ndim>
- bool Face<ndim>::containsPointInProjection(const vector_t &p) const {
- std::vector<carve::geom::vector<2> > verts;
- getProjectedVertices(verts);
- return carve::geom2d::pointInPoly(verts, project(p)).iclass != carve::POINT_OUT;
- }
-
-
-
- template<unsigned ndim>
- bool Face<ndim>::simpleLineSegmentIntersection(
- const carve::geom::linesegment<ndim> &line,
- vector_t &intersection) const {
- if (!line.OK()) return false;
-
- carve::mesh::MeshSet<3>::vertex_t::vector_t p;
- carve::IntersectionClass intersects =
- carve::geom3d::lineSegmentPlaneIntersection(plane, line, p);
- if (intersects == carve::INTERSECT_NONE || intersects == carve::INTERSECT_BAD) {
- return false;
- }
-
- std::vector<carve::geom::vector<2> > verts;
- getProjectedVertices(verts);
- if (carve::geom2d::pointInPolySimple(verts, project(p))) {
- intersection = p;
- return true;
- }
- return false;
- }
-
-
-
- template<unsigned ndim>
- IntersectionClass Face<ndim>::lineSegmentIntersection(const carve::geom::linesegment<ndim> &line,
- vector_t &intersection) const {
- if (!line.OK()) return INTERSECT_NONE;
-
-
- vector_t p;
- IntersectionClass intersects = carve::geom3d::lineSegmentPlaneIntersection(plane, line, p);
- if (intersects == INTERSECT_NONE || intersects == INTERSECT_BAD) {
- return intersects;
- }
-
- std::vector<carve::geom::vector<2> > verts;
- getProjectedVertices(verts);
- carve::geom2d::PolyInclusionInfo pi = carve::geom2d::pointInPoly(verts, project(p));
- switch (pi.iclass) {
- case POINT_VERTEX:
- intersection = p;
- return INTERSECT_VERTEX;
-
- case POINT_EDGE:
- intersection = p;
- return INTERSECT_EDGE;
-
- case POINT_IN:
- intersection = p;
- return INTERSECT_FACE;
-
- case POINT_OUT:
- return INTERSECT_NONE;
-
- default:
- break;
- }
- return INTERSECT_NONE;
- }
-
-
-
- template<unsigned ndim>
- Face<ndim> *Face<ndim>::closeLoop(typename Face<ndim>::edge_t *start) {
- edge_t *e = start;
- std::vector<edge_t *> loop_edges;
- do {
- CARVE_ASSERT(e->rev == NULL);
- loop_edges.push_back(e);
- e = e->perimNext();
- } while (e != start);
-
- const size_t N = loop_edges.size();
- for (size_t i = 0; i < N; ++i) {
- loop_edges[i]->rev = new edge_t(loop_edges[i]->v2(), NULL);
- }
-
- for (size_t i = 0; i < N; ++i) {
- edge_t *e1 = loop_edges[i]->rev;
- edge_t *e2 = loop_edges[(i+1)%N]->rev;
- e1->prev = e2;
- e2->next = e1;
- }
-
- Face *f = new Face(start->rev);
-
- CARVE_ASSERT(f->n_edges == N);
-
- return f;
- }
-
-
-
- namespace detail {
-
-
-
- bool FaceStitcher::EdgeOrderData::Cmp::operator()(const EdgeOrderData &a, const EdgeOrderData &b) const {
- int v = carve::geom3d::compareAngles(edge_dir, base_dir, a.face_dir, b.face_dir);
-
-#if defined(CARVE_DEBUG)
- {
- double da = carve::geom3d::antiClockwiseAngle(base_dir, a.face_dir, edge_dir);
- double db = carve::geom3d::antiClockwiseAngle(base_dir, b.face_dir, edge_dir);
- int v_cmp = 0;
- if (da < db) v_cmp = -1;
- if (db < da) v_cmp = +1;
- if (v_cmp != v) {
- std::cerr << "v= " << v << " v_cmp= " << v_cmp << " da= " << da << " db= " << db << " edge_dir=" << edge_dir << " base_dir=" << base_dir << " a=" << a.face_dir << " b=" << b.face_dir << std::endl;
- }
- }
-#endif
-
- if (v < 0) return true;
- if (v == 0) {
- if (a.is_reversed && !b.is_reversed) return true;
- if (a.is_reversed == b.is_reversed) {
- return a.group_id < b.group_id;
- }
- }
- return false;
- }
-
-
-
- void FaceStitcher::matchSimpleEdges() {
- // join faces that share an edge, where no other faces are incident.
- for (edge_map_t::iterator i = edges.begin(); i != edges.end(); ++i) {
- const vpair_t &ev = (*i).first;
- edge_map_t::iterator j = edges.find(vpair_t(ev.second, ev.first));
- if (j == edges.end()) {
- for (edgelist_t::iterator k = (*i).second.begin(); k != (*i).second.end(); ++k) {
- is_open[ (*k)->face->id] = true;
- }
- } else if ((*i).second.size() != 1 || (*j).second.size() != 1) {
- std::swap(complex_edges[(*i).first], (*i).second);
- } else {
- // simple edge.
- edge_t *a = (*i).second.front();
- edge_t *b = (*j).second.front();
- if (a < b) {
- // every simple edge pair is encountered twice. only merge once.
- a->rev = b;
- b->rev = a;
- face_groups.merge_sets(a->face->id, b->face->id);
- }
- }
- }
- }
-
-
-
- size_t FaceStitcher::faceGroupID(const Face<3> *face) {
- return face_groups.find_set_head(face->id);
- }
-
-
-
- size_t FaceStitcher::faceGroupID(const Edge<3> *edge) {
- return face_groups.find_set_head(edge->face->id);
- }
-
-
-
- void FaceStitcher::orderForwardAndReverseEdges(std::vector<std::vector<Edge<3> *> > &efwd,
- std::vector<std::vector<Edge<3> *> > &erev,
- std::vector<std::vector<EdgeOrderData> > &result) {
- const size_t Nfwd = efwd.size();
- const size_t Nrev = erev.size();
- const size_t N = efwd[0].size();
-
- result.resize(N);
-
- for (size_t i = 0; i < N; ++i) {
- Edge<3> *base = efwd[0][i];
-
- result[i].reserve(Nfwd + Nrev);
- for (size_t j = 0; j < Nfwd; ++j) {
- result[i].push_back(EdgeOrderData(efwd[j][i], j, false));
- CARVE_ASSERT(efwd[0][i]->v1() == efwd[j][i]->v1());
- CARVE_ASSERT(efwd[0][i]->v2() == efwd[j][i]->v2());
- }
- for (size_t j = 0; j < Nrev; ++j) {
- result[i].push_back(EdgeOrderData(erev[j][i], j, true));
- CARVE_ASSERT(erev[0][i]->v1() == erev[j][i]->v1());
- CARVE_ASSERT(erev[0][i]->v2() == erev[j][i]->v2());
- }
-
- geom::vector<3> sort_dir;
- if (opts.opt_avoid_cavities) {
- sort_dir = base->v1()->v - base->v2()->v;
- } else {
- sort_dir = base->v2()->v - base->v1()->v;
- }
-
- std::sort(result[i].begin(), result[i].end(), EdgeOrderData::Cmp(sort_dir, result[i][0].face_dir));
- }
- }
-
-
-
- void FaceStitcher::edgeIncidentGroups(const vpair_t &e,
- const edge_map_t &all_edges,
- std::pair<std::set<size_t>, std::set<size_t> > &groups) {
- groups.first.clear();
- groups.second.clear();
- edge_map_t::const_iterator i;
-
- i = all_edges.find(e);
- if (i != all_edges.end()) {
- for (edgelist_t::const_iterator j = (*i).second.begin(); j != (*i).second.end(); ++j) {
- groups.first.insert(faceGroupID(*j));
- }
- }
-
- i = all_edges.find(vpair_t(e.second, e.first));
- if (i != all_edges.end()) {
- for (edgelist_t::const_iterator j = (*i).second.begin(); j != (*i).second.end(); ++j) {
- groups.second.insert(faceGroupID(*j));
- }
- }
- }
-
-
-
- void FaceStitcher::buildEdgeGraph(const edge_map_t &all_edges) {
- for (edge_map_t::const_iterator i = all_edges.begin();
- i != all_edges.end();
- ++i) {
- edge_graph[(*i).first.first].insert((*i).first.second);
- }
- }
-
-
-
- void FaceStitcher::extractPath(std::vector<const vertex_t *> &path) {
- path.clear();
-
- edge_graph_t::iterator iter = edge_graph.begin();
-
-
- const vertex_t *init = (*iter).first;
- const vertex_t *next = *(*iter).second.begin();
- const vertex_t *prev = NULL;
- const vertex_t *vert = init;
-
- while ((*iter).second.size() == 2) {
- prev = *std::find_if((*iter).second.begin(),
- (*iter).second.end(),
- std::bind2nd(std::not_equal_to<const vertex_t *>(), next));
- next = vert;
- vert = prev;
- iter = edge_graph.find(vert);
- CARVE_ASSERT(iter != edge_graph.end());
- if (vert == init) break;
- }
- init = vert;
-
- std::vector<const edge_t *> efwd;
- std::vector<const edge_t *> erev;
-
- edge_map_t::iterator edgeiter;
- edgeiter = complex_edges.find(vpair_t(vert, next));
- std::copy((*edgeiter).second.begin(), (*edgeiter).second.end(), std::back_inserter(efwd));
-
- edgeiter = complex_edges.find(vpair_t(next, vert));
- std::copy((*edgeiter).second.begin(), (*edgeiter).second.end(), std::back_inserter(erev));
-
- path.push_back(vert);
-
- prev = vert;
- vert = next;
- path.push_back(vert);
- iter = edge_graph.find(vert);
- CARVE_ASSERT(iter != edge_graph.end());
-
- while (vert != init && (*iter).second.size() == 2) {
- next = *std::find_if((*iter).second.begin(),
- (*iter).second.end(),
- std::bind2nd(std::not_equal_to<const vertex_t *>(), prev));
-
- edgeiter = complex_edges.find(vpair_t(vert, next));
- if ((*edgeiter).second.size() != efwd.size()) goto done;
-
- for (size_t i = 0; i < efwd.size(); ++i) {
- Edge<3> *e_next = efwd[i]->perimNext();
- if (e_next->v2() != next) goto done;
- efwd[i] = e_next;
- }
-
- edgeiter = complex_edges.find(vpair_t(next, vert));
- if ((*edgeiter).second.size() != erev.size()) goto done;
-
- for (size_t i = 0; i < erev.size(); ++i) {
- Edge<3> *e_prev = erev[i]->perimPrev();
- if (e_prev->v1() != next) goto done;
- erev[i] = e_prev;
- }
-
- prev = vert;
- vert = next;
- path.push_back(vert);
- iter = edge_graph.find(vert);
- CARVE_ASSERT(iter != edge_graph.end());
- }
- done:;
- }
-
-
-
- void FaceStitcher::removePath(const std::vector<const vertex_t *> &path) {
- for (size_t i = 1; i < path.size() - 1; ++i) {
- edge_graph.erase(path[i]);
- }
-
- edge_graph[path[0]].erase(path[1]);
- if (edge_graph[path[0]].size() == 0) {
- edge_graph.erase(path[0]);
- }
-
- edge_graph[path[path.size()-1]].erase(path[path.size()-2]);
- if (edge_graph[path[path.size()-1]].size() == 0) {
- edge_graph.erase(path[path.size()-1]);
- }
- }
-
-
-
- void FaceStitcher::reorder(std::vector<EdgeOrderData> &ordering,
- size_t grp) {
- if (!ordering[0].is_reversed && ordering[0].group_id == grp) return;
- for (size_t i = 1; i < ordering.size(); ++i) {
- if (!ordering[i].is_reversed && ordering[i].group_id == grp) {
- std::vector<EdgeOrderData> temp;
- temp.reserve(ordering.size());
- std::copy(ordering.begin() + i, ordering.end(), std::back_inserter(temp));
- std::copy(ordering.begin(), ordering.begin() + i, std::back_inserter(temp));
- std::copy(temp.begin(), temp.end(), ordering.begin());
- return;
- }
- }
- }
-
-
-
- struct lt_second {
- template<typename pair_t>
- bool operator()(const pair_t &a, const pair_t &b) const {
- return a.second < b.second;
- }
- };
-
-
-
- void FaceStitcher::fuseEdges(std::vector<Edge<3> *> &fwd,
- std::vector<Edge<3> *> &rev) {
- for (size_t i = 0; i < fwd.size(); ++i) {
- fwd[i]->rev = rev[i];
- rev[i]->rev = fwd[i];
- face_groups.merge_sets(fwd[i]->face->id, rev[i]->face->id);
- }
- }
-
-
-
- void FaceStitcher::joinGroups(std::vector<std::vector<Edge<3> *> > &efwd,
- std::vector<std::vector<Edge<3> *> > &erev,
- size_t fwd_grp,
- size_t rev_grp) {
- fuseEdges(efwd[fwd_grp], erev[rev_grp]);
- }
-
-
-
- void FaceStitcher::matchOrderedEdges(const std::vector<std::vector<EdgeOrderData> >::iterator begin,
- const std::vector<std::vector<EdgeOrderData> >::iterator end,
- std::vector<std::vector<Edge<3> *> > &efwd,
- std::vector<std::vector<Edge<3> *> > &erev) {
- typedef std::unordered_map<std::pair<size_t, size_t>, size_t> pair_counts_t;
- for (;;) {
- pair_counts_t pair_counts;
-
- for (std::vector<std::vector<EdgeOrderData> >::iterator i = begin; i != end; ++i) {
- std::vector<EdgeOrderData> &e = *i;
- for (size_t j = 0; j < e.size(); ++j) {
- if (!e[j].is_reversed && e[(j+1)%e.size()].is_reversed) {
- pair_counts[std::make_pair(e[j].group_id,
- e[(j+1)%e.size()].group_id)]++;
- }
- }
- }
-
- if (!pair_counts.size()) break;
-
- std::vector<std::pair<size_t, std::pair<size_t, size_t> > > counts;
- counts.reserve(pair_counts.size());
- for (pair_counts_t::iterator iter = pair_counts.begin(); iter != pair_counts.end(); ++iter) {
- counts.push_back(std::make_pair((*iter).second, (*iter).first));
- }
- std::make_heap(counts.begin(), counts.end());
-
- std::set<size_t> rem_fwd, rem_rev;
-
- while (counts.size()) {
- std::pair<size_t, size_t> join = counts.front().second;
- std::pop_heap(counts.begin(), counts.end());
- counts.pop_back();
- if (rem_fwd.find(join.first) != rem_fwd.end()) continue;
- if (rem_rev.find(join.second) != rem_rev.end()) continue;
-
- size_t g1 = join.first;
- size_t g2 = join.second;
-
- joinGroups(efwd, erev, g1, g2);
-
- for (std::vector<std::vector<EdgeOrderData> >::iterator i = begin; i != end; ++i) {
- (*i).erase(std::remove_if((*i).begin(), (*i).end(), EdgeOrderData::TestGroups(g1, g2)), (*i).end());
- }
-
- rem_fwd.insert(g1);
- rem_rev.insert(g2);
- }
- }
- }
-
-
-
- void FaceStitcher::resolveOpenEdges() {
- // Remove open regions of mesh. Doing this may make additional
- // edges simple (for example, removing a fin from the edge of
- // a cube), and may also expose more open mesh regions. In the
- // latter case, the process must be repeated to deal with the
- // newly uncovered regions.
- std::unordered_set<size_t> open_groups;
-
- for (size_t i = 0; i < is_open.size(); ++i) {
- if (is_open[i]) open_groups.insert(face_groups.find_set_head(i));
- }
-
- while (!open_groups.empty()) {
- std::list<vpair_t> edge_0, edge_1;
-
- for (edge_map_t::iterator i = complex_edges.begin(); i != complex_edges.end(); ++i) {
- bool was_modified = false;
- for(edgelist_t::iterator j = (*i).second.begin(); j != (*i).second.end(); ) {
- if (open_groups.find(faceGroupID(*j)) != open_groups.end()) {
- j = (*i).second.erase(j);
- was_modified = true;
- } else {
- ++j;
- }
- }
- if (was_modified) {
- if ((*i).second.empty()) {
- edge_0.push_back((*i).first);
- } else if ((*i).second.size() == 1) {
- edge_1.push_back((*i).first);
- }
- }
- }
-
- for (std::list<vpair_t>::iterator i = edge_1.begin(); i != edge_1.end(); ++i) {
- vpair_t e1 = *i;
- edge_map_t::iterator e1i = complex_edges.find(e1);
- if (e1i == complex_edges.end()) continue;
- vpair_t e2 = vpair_t(e1.second, e1.first);
- edge_map_t::iterator e2i = complex_edges.find(e2);
- CARVE_ASSERT(e2i != complex_edges.end()); // each complex edge should have a mate.
-
- if ((*e2i).second.size() == 1) {
- // merge newly simple edges, delete both from complex_edges.
- edge_t *a = (*e1i).second.front();
- edge_t *b = (*e2i).second.front();
- a->rev = b;
- b->rev = a;
- face_groups.merge_sets(a->face->id, b->face->id);
- complex_edges.erase(e1i);
- complex_edges.erase(e2i);
- }
- }
-
- open_groups.clear();
-
- for (std::list<vpair_t>::iterator i = edge_0.begin(); i != edge_0.end(); ++i) {
- vpair_t e1 = *i;
- edge_map_t::iterator e1i = complex_edges.find(e1);
- vpair_t e2 = vpair_t(e1.second, e1.first);
- edge_map_t::iterator e2i = complex_edges.find(e2);
- if (e2i == complex_edges.end()) {
- // This could occur, for example, when two faces share
- // an edge in the same direction, but are both not
- // touching anything else. Both get removed by the open
- // group removal code, leaving an edge map with zero
- // edges. The edge in the opposite direction does not
- // exist, because there's no face that adjoins either of
- // the two open faces.
- continue;
- }
-
- for (edgelist_t::iterator j = (*e2i).second.begin(); j != (*e2i).second.end(); ++j) {
- open_groups.insert(faceGroupID(*j));
- }
- complex_edges.erase(e1i);
- complex_edges.erase(e2i);
- }
- }
- }
-
-
-
- void FaceStitcher::extractConnectedEdges(std::vector<const vertex_t *>::iterator begin,
- std::vector<const vertex_t *>::iterator end,
- std::vector<std::vector<Edge<3> *> > &efwd,
- std::vector<std::vector<Edge<3> *> > &erev) {
- const size_t N = std::distance(begin, end) - 1;
-
- std::vector<const vertex_t *>::iterator e1, e2;
- e1 = e2 = begin; ++e2;
- vpair_t start_f = vpair_t(*e1, *e2);
- vpair_t start_r = vpair_t(*e2, *e1);
-
- const size_t Nfwd = complex_edges[start_f].size();
- const size_t Nrev = complex_edges[start_r].size();
-
- size_t j;
- edgelist_t::iterator ji;
-
- efwd.clear(); efwd.resize(Nfwd);
- erev.clear(); erev.resize(Nrev);
-
- for (j = 0, ji = complex_edges[start_f].begin();
- ji != complex_edges[start_f].end();
- ++j, ++ji) {
- efwd[j].reserve(N);
- efwd[j].push_back(*ji);
- }
-
- for (j = 0, ji = complex_edges[start_r].begin();
- ji != complex_edges[start_r].end();
- ++j, ++ji) {
- erev[j].reserve(N);
- erev[j].push_back(*ji);
- }
-
- std::vector<Edge<3> *> temp_f, temp_r;
- temp_f.resize(Nfwd);
- temp_r.resize(Nrev);
-
- for (j = 1; j < N; ++j) {
- ++e1; ++e2;
- vpair_t ef = vpair_t(*e1, *e2);
- vpair_t er = vpair_t(*e2, *e1);
-
- if (complex_edges[ef].size() != Nfwd || complex_edges[ef].size() != Nrev) break;
-
- for (size_t k = 0; k < Nfwd; ++k) {
- Edge<3> *e_next = efwd[k].back()->perimNext();
- CARVE_ASSERT(e_next == NULL || e_next->rev == NULL);
- if (e_next == NULL || e_next->v2() != *e2) goto done;
- CARVE_ASSERT(e_next->v1() == *e1);
- CARVE_ASSERT(std::find(complex_edges[ef].begin(), complex_edges[ef].end(), e_next) != complex_edges[ef].end());
- temp_f[k] = e_next;
- }
-
- for (size_t k = 0; k < Nrev; ++k) {
- Edge<3> *e_next = erev[k].back()->perimPrev();
- if (e_next == NULL || e_next->v1() != *e2) goto done;
- CARVE_ASSERT(e_next->v2() == *e1);
- CARVE_ASSERT(std::find(complex_edges[er].begin(), complex_edges[er].end(), e_next) != complex_edges[er].end());
- temp_r[k] = e_next;
- }
-
- for (size_t k = 0; k < Nfwd; ++k) {
- efwd[k].push_back(temp_f[k]);
- }
-
- for (size_t k = 0; k < Nrev; ++k) {
- erev[k].push_back(temp_r[k]);
- }
- }
- done:;
- }
-
-
-
- void FaceStitcher::construct() {
- matchSimpleEdges();
- if (!complex_edges.size()) return;
-
- resolveOpenEdges();
- if (!complex_edges.size()) return;
-
- buildEdgeGraph(complex_edges);
-
- std::list<std::vector<const vertex_t *> > paths;
-
- while (edge_graph.size()) {
- paths.push_back(std::vector<const vertex_t *>());
- extractPath(paths.back());
- removePath(paths.back());
- };
-
-
- for (std::list<std::vector<const vertex_t *> >::iterator path = paths.begin(); path != paths.end(); ++path) {
- for (size_t i = 0; i < (*path).size() - 1;) {
- std::vector<std::vector<Edge<3> *> > efwd, erev;
-
- extractConnectedEdges((*path).begin() + i, (*path).end(), efwd, erev);
-
- std::vector<std::vector<EdgeOrderData> > orderings;
- orderForwardAndReverseEdges(efwd, erev, orderings);
-
- matchOrderedEdges(orderings.begin(), orderings.end(), efwd, erev);
- i += efwd[0].size();
- }
- }
- }
-
- FaceStitcher::FaceStitcher(const MeshOptions &_opts) : opts(_opts) {
- }
- }
- }
-
-
-
-
- // construct a MeshSet from a Polyhedron, maintaining on the
- // connectivity information in the Polyhedron.
- mesh::MeshSet<3> *meshFromPolyhedron(const poly::Polyhedron *poly, int manifold_id) {
- typedef mesh::Vertex<3> vertex_t;
- typedef mesh::Edge<3> edge_t;
- typedef mesh::Face<3> face_t;
- typedef mesh::Mesh<3> mesh_t;
- typedef mesh::MeshSet<3> meshset_t;
-
- std::vector<vertex_t> vertex_storage;
- vertex_storage.reserve(poly->vertices.size());
- for (size_t i = 0; i < poly->vertices.size(); ++i) {
- vertex_storage.push_back(vertex_t(poly->vertices[i].v));
- }
-
- std::vector<std::vector<face_t *> > faces;
- faces.resize(poly->manifold_is_closed.size());
-
- std::unordered_map<std::pair<size_t, size_t>, std::list<edge_t *> > vertex_to_edge;
-
- std::vector<vertex_t *> vert_ptrs;
- for (size_t i = 0; i < poly->faces.size(); ++i) {
- const poly::Polyhedron::face_t &src = poly->faces[i];
- if (manifold_id != -1 && src.manifold_id != manifold_id) continue;
- vert_ptrs.clear();
- vert_ptrs.reserve(src.nVertices());
- for (size_t j = 0; j < src.nVertices(); ++j) {
- size_t vi = poly->vertexToIndex_fast(src.vertex(j));
- vert_ptrs.push_back(&vertex_storage[vi]);
- }
- face_t *face = new face_t(vert_ptrs.begin(), vert_ptrs.end());
- face->id = src.manifold_id;
- faces[src.manifold_id].push_back(face);
-
- edge_t *edge = face->edge;
- do {
- vertex_to_edge[std::make_pair(size_t(edge->v1() - &vertex_storage[0]),
- size_t(edge->v2() - &vertex_storage[0]))].push_back(edge);
- edge = edge->next;
- } while (edge != face->edge);
- }
-
- // copy connectivity from Polyhedron.
- for (size_t i = 0; i < poly->edges.size(); ++i) {
- const poly::Polyhedron::edge_t &src = poly->edges[i];
- size_t v1i = poly->vertexToIndex_fast(src.v1);
- size_t v2i = poly->vertexToIndex_fast(src.v2);
-
- std::list<edge_t *> &efwd = vertex_to_edge[std::make_pair(v1i, v2i)];
- std::list<edge_t *> &erev = vertex_to_edge[std::make_pair(v2i, v1i)];
-
- const std::vector<const poly::Polyhedron::face_t *> &facepairs = poly->connectivity.edge_to_face[i];
- for (size_t j = 0; j < facepairs.size(); j += 2) {
- const poly::Polyhedron::face_t *fa, *fb;
- fa = facepairs[j];
- fb = facepairs[j+1];
- if (!fa || !fb) continue;
- CARVE_ASSERT(fa->manifold_id == fb->manifold_id);
- if (manifold_id != -1 && fa->manifold_id != manifold_id) continue;
-
- std::list<edge_t *>::iterator efwdi, erevi;
- for (efwdi = efwd.begin(); efwdi != efwd.end() && (*efwdi)->face->id != (size_t)fa->manifold_id; ++efwdi);
- for (erevi = erev.begin(); erevi != erev.end() && (*erevi)->face->id != (size_t)fa->manifold_id; ++erevi);
- CARVE_ASSERT(efwdi != efwd.end() && erevi != erev.end());
-
- (*efwdi)->rev = (*erevi);
- (*erevi)->rev = (*efwdi);
- }
- }
-
- std::vector<mesh_t *> meshes;
- meshes.reserve(faces.size());
- for (size_t i = 0; i < faces.size(); ++i) {
- if (faces[i].size()) {
- meshes.push_back(new mesh_t(faces[i]));
- }
- }
-
- return new meshset_t(vertex_storage, meshes);
- }
-
-
-
- static void copyMeshFaces(const mesh::Mesh<3> *mesh,
- size_t manifold_id,
- const mesh::Vertex<3> *Vbase,
- poly::Polyhedron *poly,
- std::unordered_map<std::pair<size_t, size_t>, std::list<mesh::Edge<3> *> > &edges,
- std::unordered_map<const mesh::Face<3> *, size_t> &face_map) {
- std::vector<const poly::Polyhedron::vertex_t *> vert_ptr;
- for (size_t f = 0; f < mesh->faces.size(); ++f) {
- mesh::Face<3> *src = mesh->faces[f];
- vert_ptr.clear();
- vert_ptr.reserve(src->nVertices());
- mesh::Edge<3> *e = src->edge;
- do {
- vert_ptr.push_back(&poly->vertices[e->vert - Vbase]);
- edges[std::make_pair(e->v1() - Vbase, e->v2() - Vbase)].push_back(e);
- e = e->next;
- } while (e != src->edge);
-
- face_map[src] = poly->faces.size();;
-
- poly->faces.push_back(poly::Polyhedron::face_t(vert_ptr));
- poly->faces.back().manifold_id = manifold_id;
- poly->faces.back().owner = poly;
- }
- }
-
-
-
- // construct a Polyhedron from a MeshSet
- poly::Polyhedron *polyhedronFromMesh(const mesh::MeshSet<3> *mesh, int manifold_id) {
- typedef poly::Polyhedron::vertex_t vertex_t;
- typedef poly::Polyhedron::edge_t edge_t;
- typedef poly::Polyhedron::face_t face_t;
-
- poly::Polyhedron *poly = new poly::Polyhedron();
- const mesh::Vertex<3> *Vbase = &mesh->vertex_storage[0];
-
- poly->vertices.reserve(mesh->vertex_storage.size());
- for (size_t i = 0; i < mesh->vertex_storage.size(); ++i) {
- poly->vertices.push_back(vertex_t(mesh->vertex_storage[i].v));
- poly->vertices.back().owner = poly;
- }
-
- size_t n_faces = 0;
- if (manifold_id == -1) {
- poly->manifold_is_closed.resize(mesh->meshes.size());
- poly->manifold_is_negative.resize(mesh->meshes.size());
- for (size_t m = 0; m < mesh->meshes.size(); ++m) {
- n_faces += mesh->meshes[m]->faces.size();
- poly->manifold_is_closed[m] = mesh->meshes[m]->isClosed();
- poly->manifold_is_negative[m] = mesh->meshes[m]->isNegative();
- }
- } else {
- poly->manifold_is_closed.resize(1);
- poly->manifold_is_negative.resize(1);
- n_faces = mesh->meshes[manifold_id]->faces.size();
- poly->manifold_is_closed[manifold_id] = mesh->meshes[manifold_id]->isClosed();
- poly->manifold_is_negative[manifold_id] = mesh->meshes[manifold_id]->isNegative();
- }
-
- std::unordered_map<std::pair<size_t, size_t>, std::list<mesh::Edge<3> *> > edges;
- std::unordered_map<const mesh::Face<3> *, size_t> face_map;
- poly->faces.reserve(n_faces);
-
- if (manifold_id == -1) {
- for (size_t m = 0; m < mesh->meshes.size(); ++m) {
- copyMeshFaces(mesh->meshes[m], m, Vbase, poly, edges, face_map);
- }
- } else {
- copyMeshFaces(mesh->meshes[manifold_id], 0, Vbase, poly, edges, face_map);
- }
-
- size_t n_edges = 0;
- for (std::unordered_map<std::pair<size_t, size_t>, std::list<mesh::Edge<3> *> >::iterator i = edges.begin(); i != edges.end(); ++i) {
- if ((*i).first.first < (*i).first.second || edges.find(std::make_pair((*i).first.second, (*i).first.first)) == edges.end()) {
- n_edges++;
- }
- }
-
- poly->edges.reserve(n_edges);
- for (std::unordered_map<std::pair<size_t, size_t>, std::list<mesh::Edge<3> *> >::iterator i = edges.begin(); i != edges.end(); ++i) {
- if ((*i).first.first < (*i).first.second ||
- edges.find(std::make_pair((*i).first.second, (*i).first.first)) == edges.end()) {
- poly->edges.push_back(edge_t(&poly->vertices[(*i).first.first],
- &poly->vertices[(*i).first.second],
- poly));
- }
- }
-
- poly->initVertexConnectivity();
-
- // build edge entries for face.
- for (size_t f = 0; f < poly->faces.size(); ++f) {
- face_t &face = poly->faces[f];
- size_t N = face.nVertices();
- for (size_t v = 0; v < N; ++v) {
- size_t v1i = poly->vertexToIndex_fast(face.vertex(v));
- size_t v2i = poly->vertexToIndex_fast(face.vertex((v+1)%N));
- std::vector<const edge_t *> found_edge;
- std::set_intersection(poly->connectivity.vertex_to_edge[v1i].begin(), poly->connectivity.vertex_to_edge[v1i].end(),
- poly->connectivity.vertex_to_edge[v2i].begin(), poly->connectivity.vertex_to_edge[v2i].end(),
- std::back_inserter(found_edge));
- CARVE_ASSERT(found_edge.size() == 1);
- face.edge(v) = found_edge[0];
- }
- }
-
- poly->connectivity.edge_to_face.resize(poly->edges.size());
-
- for (size_t i = 0; i < poly->edges.size(); ++i) {
- size_t v1i = poly->vertexToIndex_fast(poly->edges[i].v1);
- size_t v2i = poly->vertexToIndex_fast(poly->edges[i].v2);
- std::list<mesh::Edge<3> *> &efwd = edges[std::make_pair(v1i, v2i)];
- std::list<mesh::Edge<3> *> &erev = edges[std::make_pair(v1i, v2i)];
-
- for (std::list<mesh::Edge<3> *>::iterator j = efwd.begin(); j != efwd.end(); ++j) {
- mesh::Edge<3> *edge = *j;
- if (face_map.find(edge->face) != face_map.end()) {
- poly->connectivity.edge_to_face[i].push_back(&poly->faces[face_map[edge->face]]);
- if (edge->rev == NULL) {
- poly->connectivity.edge_to_face[i].push_back(NULL);
- } else {
- poly->connectivity.edge_to_face[i].push_back(&poly->faces[face_map[edge->rev->face]]);
- }
- }
- }
- for (std::list<mesh::Edge<3> *>::iterator j = erev.begin(); j != erev.end(); ++j) {
- mesh::Edge<3> *edge = *j;
- if (face_map.find(edge->face) != face_map.end()) {
- if (edge->rev == NULL) {
- poly->connectivity.edge_to_face[i].push_back(NULL);
- poly->connectivity.edge_to_face[i].push_back(&poly->faces[face_map[edge->face]]);
- }
- }
- }
-
- }
-
- poly->initSpatialIndex();
-
- // XXX: at this point, manifold_is_negative is not set up. This
- // info should be computed/stored in Mesh instances.
-
- return poly;
- }
-
-
-
-}
-
-
-
-// explicit instantiation for 2D case.
-// XXX: do not compile because of a missing definition for fitPlane in the 2d case.
-
-// template class carve::mesh::Vertex<2>;
-// template class carve::mesh::Edge<2>;
-// template class carve::mesh::Face<2>;
-// template class carve::mesh::Mesh<2>;
-// template class carve::mesh::MeshSet<2>;
-
-// explicit instantiation for 3D case.
-template class carve::mesh::Vertex<3>;
-template class carve::mesh::Edge<3>;
-template class carve::mesh::Face<3>;
-template class carve::mesh::Mesh<3>;
-template class carve::mesh::MeshSet<3>;
-
-
-
-carve::PointClass carve::mesh::classifyPoint(
- const carve::mesh::MeshSet<3> *meshset,
- const carve::geom::RTreeNode<3, carve::mesh::Face<3> *> *face_rtree,
- const carve::geom::vector<3> &v,
- bool even_odd,
- const carve::mesh::Mesh<3> *mesh,
- const carve::mesh::Face<3> **hit_face) {
-
- if (hit_face) *hit_face = NULL;
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{containsVertex " << v << "}" << std::endl;
-#endif
-
- if (!face_rtree->bbox.containsPoint(v)) {
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{final:OUT(aabb short circuit)}" << std::endl;
-#endif
- // XXX: if the top level manifolds are negative, this should be POINT_IN.
- // for the moment, this only works for a single manifold.
- if (meshset->meshes.size() == 1 && meshset->meshes[0]->isNegative()) {
- return POINT_IN;
- }
- return POINT_OUT;
- }
-
- std::vector<carve::mesh::Face<3> *> near_faces;
- face_rtree->search(v, std::back_inserter(near_faces));
-
- for (size_t i = 0; i < near_faces.size(); i++) {
- if (mesh != NULL && mesh != near_faces[i]->mesh) continue;
-
- // XXX: Do allow the tested vertex to be ON an open
- // manifold. This was here originally because of the
- // possibility of an open manifold contained within a closed
- // manifold.
-
- // if (!near_faces[i]->mesh->isClosed()) continue;
-
- if (near_faces[i]->containsPoint(v)) {
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{final:ON(hits face " << near_faces[i] << ")}" << std::endl;
-#endif
- if (hit_face) *hit_face = near_faces[i];
- return POINT_ON;
- }
- }
-
- double ray_len = face_rtree->bbox.extent.length() * 2;
-
-
- std::vector<std::pair<const carve::mesh::Face<3> *, carve::geom::vector<3> > > manifold_intersections;
-
- for (;;) {
- double a1 = random() / double(RAND_MAX) * M_TWOPI;
- double a2 = random() / double(RAND_MAX) * M_TWOPI;
-
- carve::geom3d::Vector ray_dir = carve::geom::VECTOR(sin(a1) * sin(a2), cos(a1) * sin(a2), cos(a2));
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{testing ray: " << ray_dir << "}" << std::endl;
-#endif
-
- carve::geom::vector<3> v2 = v + ray_dir * ray_len;
-
- bool failed = false;
- carve::geom::linesegment<3> line(v, v2);
- carve::geom::vector<3> intersection;
-
- near_faces.clear();
- manifold_intersections.clear();
- face_rtree->search(line, std::back_inserter(near_faces));
-
- for (unsigned i = 0; !failed && i < near_faces.size(); i++) {
- if (mesh != NULL && mesh != near_faces[i]->mesh) continue;
-
- if (!near_faces[i]->mesh->isClosed()) continue;
-
- switch (near_faces[i]->lineSegmentIntersection(line, intersection)) {
- case INTERSECT_FACE: {
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{intersects face: " << near_faces[i]
- << " dp: " << dot(ray_dir, near_faces[i]->plane.N) << "}" << std::endl;
-#endif
-
- if (!even_odd && fabs(dot(ray_dir, near_faces[i]->plane.N)) < EPSILON) {
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{failing(small dot product)}" << std::endl;
-#endif
-
- failed = true;
- break;
- }
- manifold_intersections.push_back(std::make_pair(near_faces[i], intersection));
- break;
- }
- case INTERSECT_NONE: {
- break;
- }
- default: {
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{failing(degenerate intersection)}" << std::endl;
-#endif
- failed = true;
- break;
- }
- }
- }
-
- if (!failed) {
- if (even_odd) {
- return (manifold_intersections.size() & 1) ? POINT_IN : POINT_OUT;
- }
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{intersections ok [count:"
- << manifold_intersections.size()
- << "], sorting}"
- << std::endl;
-#endif
-
- carve::geom3d::sortInDirectionOfRay(ray_dir,
- manifold_intersections.begin(),
- manifold_intersections.end(),
- carve::geom3d::vec_adapt_pair_second());
-
- std::map<const carve::mesh::Mesh<3> *, int> crossings;
-
- for (size_t i = 0; i < manifold_intersections.size(); ++i) {
- const carve::mesh::Face<3> *f = manifold_intersections[i].first;
- if (dot(ray_dir, f->plane.N) < 0.0) {
- crossings[f->mesh]++;
- } else {
- crossings[f->mesh]--;
- }
- }
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- for (std::map<const carve::mesh::Mesh<3> *, int>::const_iterator i = crossings.begin(); i != crossings.end(); ++i) {
- std::cerr << "{mesh " << (*i).first << " crossing count: " << (*i).second << "}" << std::endl;
- }
-#endif
-
- for (size_t i = 0; i < manifold_intersections.size(); ++i) {
- const carve::mesh::Face<3> *f = manifold_intersections[i].first;
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{intersection at "
- << manifold_intersections[i].second
- << " mesh: "
- << f->mesh
- << " count: "
- << crossings[f->mesh]
- << "}"
- << std::endl;
-#endif
-
- if (crossings[f->mesh] < 0) {
- // inside this manifold.
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{final:IN}" << std::endl;
-#endif
-
- return POINT_IN;
- } else if (crossings[f->mesh] > 0) {
- // outside this manifold, but it's an infinite manifold. (for instance, an inverted cube)
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{final:OUT}" << std::endl;
-#endif
-
- return POINT_OUT;
- }
- }
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{final:OUT(default)}" << std::endl;
-#endif
-
- return POINT_OUT;
- }
- }
-}
-
-
-
diff --git a/extern/carve/lib/octree.cpp b/extern/carve/lib/octree.cpp
deleted file mode 100644
index b866b0ce2be..00000000000
--- a/extern/carve/lib/octree.cpp
+++ /dev/null
@@ -1,399 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/octree_decl.hpp>
-#include <carve/octree_impl.hpp>
-
-#include <carve/poly_decl.hpp>
-
-namespace carve {
- namespace csg {
-
- Octree::Node::Node(const carve::geom3d::Vector &newMin, const carve::geom3d::Vector &newMax) :
- parent(NULL), is_leaf(true), min(newMin), max(newMax) {
- for (int i = 0; i < 8; ++i) children[i] = NULL;
- aabb = Octree::makeAABB(this);
- }
-
- Octree::Node::Node(Node *p, double x1, double y1, double z1, double x2, double y2, double z2) :
- parent(p), is_leaf(true), min(carve::geom::VECTOR(x1, y1, z1)), max(carve::geom::VECTOR(x2, y2, z2)) {
- for (int i = 0; i < 8; ++i) children[i] = NULL;
- aabb = Octree::makeAABB(this);
- }
-
- Octree::Node::~Node() {
- for (int i = 0; i < 8; ++i) {
- if (children[i] != NULL) {
- (*children[i]).~Node();
- }
- }
- if (children[0] != NULL) {
- char *ptr = (char*)children[0];
- delete[] ptr;
- }
- }
-
- bool Octree::Node::mightContain(const carve::poly::Face<3> &face) {
- if (face.nVertices() == 3) {
- return aabb.intersects(carve::geom::tri<3>(face.vertex(0)->v, face.vertex(1)->v, face.vertex(2)->v));
- } else {
- return aabb.intersects(face.aabb) && aabb.intersects(face.plane_eqn);
- }
- }
-
- bool Octree::Node::mightContain(const carve::poly::Edge<3> &edge) {
- return aabb.intersectsLineSegment(edge.v1->v, edge.v2->v);
- }
-
- bool Octree::Node::mightContain(const carve::poly::Vertex<3> &p) {
- return aabb.containsPoint(p.v);
- }
-
- bool Octree::Node::hasChildren() {
- return !is_leaf;
- }
-
- bool Octree::Node::split() {
- if (is_leaf && hasGeometry()) {
-
- carve::geom3d::Vector mid = 0.5 * (min + max);
- char *ptr = new char[sizeof(Node)*8];
- children[0] = new (ptr + sizeof(Node) * 0) Node(this, min.x, min.y, min.z, mid.x, mid.y, mid.z);
- children[1] = new (ptr + sizeof(Node) * 1) Node(this, mid.x, min.y, min.z, max.x, mid.y, mid.z);
- children[2] = new (ptr + sizeof(Node) * 2) Node(this, min.x, mid.y, min.z, mid.x, max.y, mid.z);
- children[3] = new (ptr + sizeof(Node) * 3) Node(this, mid.x, mid.y, min.z, max.x, max.y, mid.z);
- children[4] = new (ptr + sizeof(Node) * 4) Node(this, min.x, min.y, mid.z, mid.x, mid.y, max.z);
- children[5] = new (ptr + sizeof(Node) * 5) Node(this, mid.x, min.y, mid.z, max.x, mid.y, max.z);
- children[6] = new (ptr + sizeof(Node) * 6) Node(this, min.x, mid.y, mid.z, mid.x, max.y, max.z);
- children[7] = new (ptr + sizeof(Node) * 7) Node(this, mid.x, mid.y, mid.z, max.x, max.y, max.z);
-
- for (int i = 0; i < 8; ++i) {
- putInside(faces, children[i], children[i]->faces);
- putInside(edges, children[i], children[i]->edges);
- putInside(vertices, children[i], children[i]->vertices);
- }
-
- faces.clear();
- edges.clear();
- vertices.clear();
- is_leaf = false;
- }
- return is_leaf;
- }
-
- template <class T>
- void Octree::Node::putInside(const T &input, Node *child, T &output) {
- for (typename T::const_iterator it = input.begin(), e = input.end(); it != e; ++it) {
- if (child->mightContain(**it)) {
- output.push_back(*it);
- }
- }
- }
-
- bool Octree::Node::hasGeometry() {
- return faces.size() > 0 || edges.size() > 0 || vertices.size() > 0;
- }
-
- Octree::Octree() {
- root = NULL;
- }
-
- Octree::~Octree() {
- if (root) delete root;
- }
-
- void Octree::setBounds(const carve::geom3d::Vector &min, const carve::geom3d::Vector &max) {
- if (root) delete root;
- root = new Node(min, max);
- }
-
- void Octree::setBounds(carve::geom3d::AABB aabb) {
- if (root) delete root;
- aabb.extent = 1.1 * aabb.extent;
- root = new Node(aabb.min(), aabb.max());
- }
-
- void Octree::addEdges(const std::vector<carve::poly::Edge<3> > &e) {
- root->edges.reserve(root->edges.size() + e.size());
- for (size_t i = 0; i < e.size(); ++i) {
- root->edges.push_back(&e[i]);
- }
- }
-
- void Octree::addFaces(const std::vector<carve::poly::Face<3> > &f) {
- root->faces.reserve(root->faces.size() + f.size());
- for (size_t i = 0; i < f.size(); ++i) {
- root->faces.push_back(&f[i]);
- }
- }
-
- void Octree::addVertices(const std::vector<const carve::poly::Vertex<3> *> &p) {
- root->vertices.insert(root->vertices.end(), p.begin(), p.end());
- }
-
- carve::geom3d::AABB Octree::makeAABB(const Node *node) {
- carve::geom3d::Vector centre = 0.5 * (node->min + node->max);
- carve::geom3d::Vector size = SLACK_FACTOR * 0.5 * (node->max - node->min);
- return carve::geom3d::AABB(centre, size);
- }
-
- void Octree::doFindEdges(const carve::geom::aabb<3> &aabb,
- Node *node,
- std::vector<const carve::poly::Edge<3> *> &out,
- unsigned depth) const {
- if (node == NULL) {
- return;
- }
-
- if (node->aabb.intersects(aabb)) {
- if (node->hasChildren()) {
- for (int i = 0; i < 8; ++i) {
- doFindEdges(aabb, node->children[i], out, depth + 1);
- }
- } else {
- if (depth < MAX_SPLIT_DEPTH && node->edges.size() > EDGE_SPLIT_THRESHOLD) {
- if (!node->split()) {
- for (int i = 0; i < 8; ++i) {
- doFindEdges(aabb, node->children[i], out, depth + 1);
- }
- return;
- }
- }
- for (std::vector<const carve::poly::Edge<3>*>::const_iterator it = node->edges.begin(), e = node->edges.end(); it != e; ++it) {
- if ((*it)->tag_once()) {
- out.push_back(*it);
- }
- }
- }
- }
- }
-
- void Octree::doFindEdges(const carve::geom3d::LineSegment &l,
- Node *node,
- std::vector<const carve::poly::Edge<3> *> &out,
- unsigned depth) const {
- if (node == NULL) {
- return;
- }
-
- if (node->aabb.intersectsLineSegment(l.v1, l.v2)) {
- if (node->hasChildren()) {
- for (int i = 0; i < 8; ++i) {
- doFindEdges(l, node->children[i], out, depth + 1);
- }
- } else {
- if (depth < MAX_SPLIT_DEPTH && node->edges.size() > EDGE_SPLIT_THRESHOLD) {
- if (!node->split()) {
- for (int i = 0; i < 8; ++i) {
- doFindEdges(l, node->children[i], out, depth + 1);
- }
- return;
- }
- }
- for (std::vector<const carve::poly::Edge<3>*>::const_iterator it = node->edges.begin(), e = node->edges.end(); it != e; ++it) {
- if ((*it)->tag_once()) {
- out.push_back(*it);
- }
- }
- }
- }
- }
-
- void Octree::doFindEdges(const carve::geom3d::Vector &v,
- Node *node,
- std::vector<const carve::poly::Edge<3> *> &out,
- unsigned depth) const {
- if (node == NULL) {
- return;
- }
-
- if (node->aabb.containsPoint(v)) {
- if (node->hasChildren()) {
- for (int i = 0; i < 8; ++i) {
- doFindEdges(v, node->children[i], out, depth + 1);
- }
- } else {
- if (depth < MAX_SPLIT_DEPTH && node->edges.size() > EDGE_SPLIT_THRESHOLD) {
- if (!node->split()) {
- for (int i = 0; i < 8; ++i) {
- doFindEdges(v, node->children[i], out, depth + 1);
- }
- return;
- }
- }
- for (std::vector<const carve::poly::Edge<3>*>::const_iterator
- it = node->edges.begin(), e = node->edges.end(); it != e; ++it) {
- if ((*it)->tag_once()) {
- out.push_back(*it);
- }
- }
- }
- }
- }
-
- void Octree::doFindFaces(const carve::geom::aabb<3> &aabb,
- Node *node,
- std::vector<const carve::poly::Face<3>*> &out,
- unsigned depth) const {
- if (node == NULL) {
- return;
- }
-
- if (node->aabb.intersects(aabb)) {
- if (node->hasChildren()) {
- for (int i = 0; i < 8; ++i) {
- doFindFaces(aabb, node->children[i], out, depth + 1);
- }
- } else {
- if (depth < MAX_SPLIT_DEPTH && node->faces.size() > FACE_SPLIT_THRESHOLD) {
- if (!node->split()) {
- for (int i = 0; i < 8; ++i) {
- doFindFaces(aabb, node->children[i], out, depth + 1);
- }
- return;
- }
- }
- for (std::vector<const carve::poly::Face<3>*>::const_iterator it = node->faces.begin(), e = node->faces.end(); it != e; ++it) {
- if ((*it)->tag_once()) {
- out.push_back(*it);
- }
- }
- }
- }
- }
-
- void Octree::doFindFaces(const carve::geom3d::LineSegment &l,
- Node *node,
- std::vector<const carve::poly::Face<3>*> &out,
- unsigned depth) const {
- if (node == NULL) {
- return;
- }
-
- if (node->aabb.intersectsLineSegment(l.v1, l.v2)) {
- if (node->hasChildren()) {
- for (int i = 0; i < 8; ++i) {
- doFindFaces(l, node->children[i], out, depth + 1);
- }
- } else {
- if (depth < MAX_SPLIT_DEPTH && node->faces.size() > FACE_SPLIT_THRESHOLD) {
- if (!node->split()) {
- for (int i = 0; i < 8; ++i) {
- doFindFaces(l, node->children[i], out, depth + 1);
- }
- return;
- }
- }
- for (std::vector<const carve::poly::Face<3>*>::const_iterator it = node->faces.begin(), e = node->faces.end(); it != e; ++it) {
- if ((*it)->tag_once()) {
- out.push_back(*it);
- }
- }
- }
- }
- }
-
- void Octree::doFindVerticesAllowDupes(const carve::geom3d::Vector &v, Node *node, std::vector<const carve::poly::Vertex<3> *> &out, unsigned depth) const {
- if (node == NULL) {
- return;
- }
-
- if (node->aabb.containsPoint(v)) {
- if (node->hasChildren()) {
- for (int i = 0; i < 8; ++i) {
- doFindVerticesAllowDupes(v, node->children[i], out, depth + 1);
- }
- } else {
- if (depth < MAX_SPLIT_DEPTH && node->vertices.size() > POINT_SPLIT_THRESHOLD) {
- if (!node->split()) {
- for (int i = 0; i < 8; ++i) {
- doFindVerticesAllowDupes(v, node->children[i], out, depth + 1);
- }
- return;
- }
- }
- for (std::vector<const carve::poly::Vertex<3> *>::const_iterator it = node->vertices.begin(), e = node->vertices.end(); it != e; ++it) {
- out.push_back(*it);
- }
- }
- }
- }
-
- void Octree::findEdgesNear(const carve::geom::aabb<3> &aabb, std::vector<const carve::poly::Edge<3>*> &out) const {
- tagable::tag_begin();
- doFindEdges(aabb, root, out, 0);
- }
-
- void Octree::findEdgesNear(const carve::geom3d::LineSegment &l, std::vector<const carve::poly::Edge<3>*> &out) const {
- tagable::tag_begin();
- doFindEdges(l, root, out, 0);
- }
-
- void Octree::findEdgesNear(const carve::poly::Edge<3> &e, std::vector<const carve::poly::Edge<3>*> &out) const {
- tagable::tag_begin();
- doFindEdges(carve::geom3d::LineSegment(e.v1->v, e.v2->v), root, out, 0);
- }
-
- void Octree::findEdgesNear(const carve::geom3d::Vector &v, std::vector<const carve::poly::Edge<3>*> &out) const {
- tagable::tag_begin();
- doFindEdges(v, root, out, 0);
- }
-
- void Octree::findFacesNear(const carve::geom::aabb<3> &aabb, std::vector<const carve::poly::Face<3>*> &out) const {
- tagable::tag_begin();
- doFindFaces(aabb, root, out, 0);
- }
-
- void Octree::findFacesNear(const carve::geom3d::LineSegment &l, std::vector<const carve::poly::Face<3>*> &out) const {
- tagable::tag_begin();
- doFindFaces(l, root, out, 0);
- }
-
- void Octree::findFacesNear(const carve::poly::Edge<3> &e, std::vector<const carve::poly::Face<3>*> &out) const {
- tagable::tag_begin();
- doFindFaces(carve::geom3d::LineSegment(e.v1->v, e.v2->v), root, out, 0);
- }
-
- void Octree::findVerticesNearAllowDupes(const carve::geom3d::Vector &v, std::vector<const carve::poly::Vertex<3> *> &out) const {
- tagable::tag_begin();
- doFindVerticesAllowDupes(v, root, out, 0);
- }
-
- void Octree::doSplit(int maxSplit, Node *node) {
- // Don't split down any further than 4 levels.
- if (maxSplit <= 0 || (node->edges.size() < 5 && node->faces.size() < 5)) {
- return;
- }
-
- if (!node->split()) {
- for (int i = 0; i < 8; ++i) {
- doSplit(maxSplit - 1, node->children[i]);
- }
- }
- }
-
- void Octree::splitTree() {
- // initially split 4 levels
- doSplit(0, root);
- }
-
- }
-}
diff --git a/extern/carve/lib/pointset.cpp b/extern/carve/lib/pointset.cpp
deleted file mode 100644
index 77ba922c04a..00000000000
--- a/extern/carve/lib/pointset.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/geom.hpp>
-#include <carve/pointset.hpp>
-
-namespace carve {
- namespace point {
-
- PointSet::PointSet(const std::vector<carve::geom3d::Vector> &points) {
- vertices.resize(points.size());
- for (size_t i = 0; i < points.size(); ++i) {
- vertices[i].v = points[i];
- }
- aabb.fit(points.begin(), points.end());
- }
-
- void PointSet::sortVertices(const carve::geom3d::Vector &axis) {
- std::vector<std::pair<double, size_t> > temp;
- temp.reserve(vertices.size());
- for (size_t i = 0; i < vertices.size(); ++i) {
- temp.push_back(std::make_pair(dot(axis, vertices[i].v), i));
- }
- std::sort(temp.begin(), temp.end());
-
- std::vector<Vertex> vnew;
- vnew.reserve(vertices.size());
-
- // std::vector<int> revmap;
- // revmap.resize(vertices.size());
-
- for (size_t i = 0; i < vertices.size(); ++i) {
- vnew.push_back(vertices[temp[i].second]);
- // revmap[temp[i].second] = i;
- }
-
- vertices.swap(vnew);
- }
-
- }
-}
diff --git a/extern/carve/lib/polyhedron.cpp b/extern/carve/lib/polyhedron.cpp
deleted file mode 100644
index d402fce36df..00000000000
--- a/extern/carve/lib/polyhedron.cpp
+++ /dev/null
@@ -1,1107 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#if defined(CARVE_DEBUG)
-#define DEBUG_CONTAINS_VERTEX
-#endif
-
-#include <carve/djset.hpp>
-
-#include <carve/geom.hpp>
-#include <carve/poly.hpp>
-
-#include <carve/octree_impl.hpp>
-
-#include <carve/timing.hpp>
-
-#include <algorithm>
-
-#include <carve/mesh.hpp>
-
-#ifdef HAVE_BOOST_LIBRARY
-# include BOOST_INCLUDE(random.hpp)
-#else
-# include <carve/random/random.h>
-#endif
-
-namespace {
- bool emb_test(carve::poly::Polyhedron *poly,
- std::map<int, std::set<int> > &embedding,
- carve::geom3d::Vector v,
- int m_id) {
-
- std::map<int, carve::PointClass> result;
-#if defined(CARVE_DEBUG)
- std::cerr << "test " << v << " (m_id:" << m_id << ")" << std::endl;
-#endif
- poly->testVertexAgainstClosedManifolds(v, result, true);
- std::set<int> inside;
- for (std::map<int, carve::PointClass>::iterator j = result.begin();
- j != result.end();
- ++j) {
- if ((*j).first == m_id) continue;
- if ((*j).second == carve::POINT_IN) inside.insert((*j).first);
- else if ((*j).second == carve::POINT_ON) {
-#if defined(CARVE_DEBUG)
- std::cerr << " FAIL" << std::endl;
-#endif
- return false;
- }
- }
-#if defined(CARVE_DEBUG)
- std::cerr << " OK (inside.size()==" << inside.size() << ")" << std::endl;
-#endif
- embedding[m_id] = inside;
- return true;
- }
-
-
-
- struct order_faces {
- bool operator()(const carve::poly::Polyhedron::face_t * const &a,
- const carve::poly::Polyhedron::face_t * const &b) const {
- return std::lexicographical_compare(a->vbegin(), a->vend(), b->vbegin(), b->vend());
- }
- };
-
-
-
-}
-
-
-
-namespace carve {
- namespace poly {
-
-
-
- bool Polyhedron::initSpatialIndex() {
- static carve::TimingName FUNC_NAME("Polyhedron::initSpatialIndex()");
- carve::TimingBlock block(FUNC_NAME);
-
- octree.setBounds(aabb);
- octree.addFaces(faces);
- octree.addEdges(edges);
- octree.splitTree();
-
- return true;
- }
-
-
-
- void Polyhedron::invertAll() {
- for (size_t i = 0; i < faces.size(); ++i) {
- faces[i].invert();
- }
-
- for (size_t i = 0; i < edges.size(); ++i) {
- std::vector<const face_t *> &f = connectivity.edge_to_face[i];
- for (size_t j = 0; j < (f.size() & ~1U); j += 2) {
- std::swap(f[j], f[j+1]);
- }
- }
-
- for (size_t i = 0; i < manifold_is_negative.size(); ++i) {
- manifold_is_negative[i] = !manifold_is_negative[i];
- }
- }
-
-
-
- void Polyhedron::invert(const std::vector<bool> &selected_manifolds) {
- bool altered = false;
- for (size_t i = 0; i < faces.size(); ++i) {
- if (faces[i].manifold_id >= 0 &&
- (unsigned)faces[i].manifold_id < selected_manifolds.size() &&
- selected_manifolds[faces[i].manifold_id]) {
- altered = true;
- faces[i].invert();
- }
- }
-
- if (altered) {
- for (size_t i = 0; i < edges.size(); ++i) {
- std::vector<const face_t *> &f = connectivity.edge_to_face[i];
- for (size_t j = 0; j < (f.size() & ~1U); j += 2) {
- int m_id = -1;
- if (f[j]) m_id = f[j]->manifold_id;
- if (f[j+1]) m_id = f[j+1]->manifold_id;
- if (m_id >= 0 && (unsigned)m_id < selected_manifolds.size() && selected_manifolds[m_id]) {
- std::swap(f[j], f[j+1]);
- }
- }
- }
-
- for (size_t i = 0; i < std::min(selected_manifolds.size(), manifold_is_negative.size()); ++i) {
- manifold_is_negative[i] = !manifold_is_negative[i];
- }
- }
- }
-
-
-
- void Polyhedron::initVertexConnectivity() {
- static carve::TimingName FUNC_NAME("static Polyhedron initVertexConnectivity()");
- carve::TimingBlock block(FUNC_NAME);
-
- // allocate space for connectivity info.
- connectivity.vertex_to_edge.resize(vertices.size());
- connectivity.vertex_to_face.resize(vertices.size());
-
- std::vector<size_t> vertex_face_count;
-
- vertex_face_count.resize(vertices.size());
-
- // work out how many faces/edges each vertex is connected to, in
- // order to save on array reallocs.
- for (unsigned i = 0; i < faces.size(); ++i) {
- face_t &f = faces[i];
- for (unsigned j = 0; j < f.nVertices(); j++) {
- vertex_face_count[vertexToIndex_fast(f.vertex(j))]++;
- }
- }
-
- for (size_t i = 0; i < vertices.size(); ++i) {
- connectivity.vertex_to_edge[i].reserve(vertex_face_count[i]);
- connectivity.vertex_to_face[i].reserve(vertex_face_count[i]);
- }
-
- // record connectivity from vertex to edges.
- for (size_t i = 0; i < edges.size(); ++i) {
- size_t v1i = vertexToIndex_fast(edges[i].v1);
- size_t v2i = vertexToIndex_fast(edges[i].v2);
-
- connectivity.vertex_to_edge[v1i].push_back(&edges[i]);
- connectivity.vertex_to_edge[v2i].push_back(&edges[i]);
- }
-
- // record connectivity from vertex to faces.
- for (size_t i = 0; i < faces.size(); ++i) {
- face_t &f = faces[i];
- for (unsigned j = 0; j < f.nVertices(); j++) {
- size_t vi = vertexToIndex_fast(f.vertex(j));
- connectivity.vertex_to_face[vi].push_back(&f);
- }
- }
- }
-
-
-
- bool Polyhedron::initConnectivity() {
- static carve::TimingName FUNC_NAME("Polyhedron::initConnectivity()");
- carve::TimingBlock block(FUNC_NAME);
-
- // temporary measure: initialize connectivity by creating a
- // half-edge mesh, and then converting back.
-
- std::vector<mesh::Vertex<3> > vertex_storage;
- vertex_storage.reserve(vertices.size());
- for (size_t i = 0; i < vertices.size(); ++i) {
- vertex_storage.push_back(mesh::Vertex<3>(vertices[i].v));
- }
-
- std::vector<mesh::Face<3> *> mesh_faces;
- std::unordered_map<const mesh::Face<3> *, size_t> face_map;
- {
- std::vector<mesh::Vertex<3> *> vert_ptrs;
- for (size_t i = 0; i < faces.size(); ++i) {
- const face_t &src = faces[i];
- vert_ptrs.clear();
- vert_ptrs.reserve(src.nVertices());
- for (size_t j = 0; j < src.nVertices(); ++j) {
- size_t vi = vertexToIndex_fast(src.vertex(j));
- vert_ptrs.push_back(&vertex_storage[vi]);
- }
- mesh::Face<3> *face = new mesh::Face<3>(vert_ptrs.begin(), vert_ptrs.end());
- mesh_faces.push_back(face);
- face_map[face] = i;
- }
- }
-
- std::vector<mesh::Mesh<3> *> meshes;
- mesh::Mesh<3>::create(mesh_faces.begin(), mesh_faces.end(), meshes, mesh::MeshOptions());
- mesh::MeshSet<3> *meshset = new mesh::MeshSet<3>(vertex_storage, meshes);
-
- manifold_is_closed.resize(meshset->meshes.size());
- manifold_is_negative.resize(meshset->meshes.size());
-
- std::unordered_map<std::pair<size_t, size_t>, std::list<mesh::Edge<3> *> > edge_map;
-
- if (meshset->vertex_storage.size()) {
- mesh::Vertex<3> *Vbase = &meshset->vertex_storage[0];
- for (size_t m = 0; m < meshset->meshes.size(); ++m) {
- mesh::Mesh<3> *mesh = meshset->meshes[m];
- manifold_is_closed[m] = mesh->isClosed();
- for (size_t f = 0; f < mesh->faces.size(); ++f) {
- mesh::Face<3> *src = mesh->faces[f];
- mesh::Edge<3> *e = src->edge;
- faces[face_map[src]].manifold_id = m;
- do {
- edge_map[std::make_pair(e->v1() - Vbase, e->v2() - Vbase)].push_back(e);
- e = e->next;
- } while (e != src->edge);
- }
- }
- }
-
- size_t n_edges = 0;
- for (std::unordered_map<std::pair<size_t, size_t>, std::list<mesh::Edge<3> *> >::iterator i = edge_map.begin(); i != edge_map.end(); ++i) {
- if ((*i).first.first < (*i).first.second || edge_map.find(std::make_pair((*i).first.second, (*i).first.first)) == edge_map.end()) {
- n_edges++;
- }
- }
-
- edges.clear();
- edges.reserve(n_edges);
- for (std::unordered_map<std::pair<size_t, size_t>, std::list<mesh::Edge<3> *> >::iterator i = edge_map.begin(); i != edge_map.end(); ++i) {
- if ((*i).first.first < (*i).first.second || edge_map.find(std::make_pair((*i).first.second, (*i).first.first)) == edge_map.end()) {
- edges.push_back(edge_t(&vertices[(*i).first.first], &vertices[(*i).first.second], this));
- }
- }
-
- initVertexConnectivity();
-
- for (size_t f = 0; f < faces.size(); ++f) {
- face_t &face = faces[f];
- size_t N = face.nVertices();
- for (size_t v = 0; v < N; ++v) {
- size_t v1i = vertexToIndex_fast(face.vertex(v));
- size_t v2i = vertexToIndex_fast(face.vertex((v+1)%N));
- std::vector<const edge_t *> found_edge;
-
- CARVE_ASSERT(carve::is_sorted(connectivity.vertex_to_edge[v1i].begin(), connectivity.vertex_to_edge[v1i].end()));
- CARVE_ASSERT(carve::is_sorted(connectivity.vertex_to_edge[v2i].begin(), connectivity.vertex_to_edge[v2i].end()));
-
- std::set_intersection(connectivity.vertex_to_edge[v1i].begin(), connectivity.vertex_to_edge[v1i].end(),
- connectivity.vertex_to_edge[v2i].begin(), connectivity.vertex_to_edge[v2i].end(),
- std::back_inserter(found_edge));
-
- CARVE_ASSERT(found_edge.size() == 1);
-
- face.edge(v) = found_edge[0];
- }
- }
-
- connectivity.edge_to_face.resize(edges.size());
-
- for (size_t i = 0; i < edges.size(); ++i) {
- size_t v1i = vertexToIndex_fast(edges[i].v1);
- size_t v2i = vertexToIndex_fast(edges[i].v2);
- std::list<mesh::Edge<3> *> &efwd = edge_map[std::make_pair(v1i, v2i)];
- std::list<mesh::Edge<3> *> &erev = edge_map[std::make_pair(v1i, v2i)];
-
- for (std::list<mesh::Edge<3> *>::iterator j = efwd.begin(); j != efwd.end(); ++j) {
- mesh::Edge<3> *edge = *j;
- if (face_map.find(edge->face) != face_map.end()) {
- connectivity.edge_to_face[i].push_back(&faces[face_map[edge->face]]);
- if (edge->rev == NULL) {
- connectivity.edge_to_face[i].push_back(NULL);
- } else {
- connectivity.edge_to_face[i].push_back(&faces[face_map[edge->rev->face]]);
- }
- }
- }
- for (std::list<mesh::Edge<3> *>::iterator j = erev.begin(); j != erev.end(); ++j) {
- mesh::Edge<3> *edge = *j;
- if (face_map.find(edge->face) != face_map.end()) {
- if (edge->rev == NULL) {
- connectivity.edge_to_face[i].push_back(NULL);
- connectivity.edge_to_face[i].push_back(&faces[face_map[edge->face]]);
- }
- }
- }
- }
-
- delete meshset;
-
- return true;
- }
-
-
-
- bool Polyhedron::calcManifoldEmbedding() {
- // this could be significantly sped up using bounding box tests
- // to work out what pairs of manifolds are embedding candidates.
- // A per-manifold AABB could also be used to speed up
- // testVertexAgainstClosedManifolds().
-
- static carve::TimingName FUNC_NAME("Polyhedron::calcManifoldEmbedding()");
- static carve::TimingName CME_V("Polyhedron::calcManifoldEmbedding() (vertices)");
- static carve::TimingName CME_E("Polyhedron::calcManifoldEmbedding() (edges)");
- static carve::TimingName CME_F("Polyhedron::calcManifoldEmbedding() (faces)");
-
- carve::TimingBlock block(FUNC_NAME);
-
- const unsigned MCOUNT = manifoldCount();
- if (MCOUNT < 2) return true;
-
- std::set<int> vertex_manifolds;
- std::map<int, std::set<int> > embedding;
-
- carve::Timing::start(CME_V);
- for (size_t i = 0; i < vertices.size(); ++i) {
- vertex_manifolds.clear();
- if (vertexManifolds(&vertices[i], set_inserter(vertex_manifolds)) != 1) continue;
- int m_id = *vertex_manifolds.begin();
- if (embedding.find(m_id) == embedding.end()) {
- if (emb_test(this, embedding, vertices[i].v, m_id) && embedding.size() == MCOUNT) {
- carve::Timing::stop();
- goto done;
- }
- }
- }
- carve::Timing::stop();
-
- carve::Timing::start(CME_E);
- for (size_t i = 0; i < edges.size(); ++i) {
- if (connectivity.edge_to_face[i].size() == 2) {
- int m_id;
- const face_t *f1 = connectivity.edge_to_face[i][0];
- const face_t *f2 = connectivity.edge_to_face[i][1];
- if (f1) m_id = f1->manifold_id;
- if (f2) m_id = f2->manifold_id;
- if (embedding.find(m_id) == embedding.end()) {
- if (emb_test(this, embedding, (edges[i].v1->v + edges[i].v2->v) / 2, m_id) && embedding.size() == MCOUNT) {
- carve::Timing::stop();
- goto done;
- }
- }
- }
- }
- carve::Timing::stop();
-
- carve::Timing::start(CME_F);
- for (size_t i = 0; i < faces.size(); ++i) {
- int m_id = faces[i].manifold_id;
- if (embedding.find(m_id) == embedding.end()) {
- carve::geom2d::P2 pv;
- if (!carve::geom2d::pickContainedPoint(faces[i].projectedVertices(), pv)) continue;
- carve::geom3d::Vector v = carve::poly::face::unproject(faces[i], pv);
- if (emb_test(this, embedding, v, m_id) && embedding.size() == MCOUNT) {
- carve::Timing::stop();
- goto done;
- }
- }
- }
- carve::Timing::stop();
-
- CARVE_FAIL("could not find test points");
-
- // std::cerr << "could not find test points!!!" << std::endl;
- // return true;
- done:;
- for (std::map<int, std::set<int> >::iterator i = embedding.begin(); i != embedding.end(); ++i) {
-#if defined(CARVE_DEBUG)
- std::cerr << (*i).first << " : ";
- std::copy((*i).second.begin(), (*i).second.end(), std::ostream_iterator<int>(std::cerr, ","));
- std::cerr << std::endl;
-#endif
- (*i).second.insert(-1);
- }
- std::set<int> parents, new_parents;
- parents.insert(-1);
-
- while (embedding.size()) {
- new_parents.clear();
- for (std::map<int, std::set<int> >::iterator i = embedding.begin(); i != embedding.end(); ++i) {
- if ((*i).second.size() == 1) {
- if (parents.find(*(*i).second.begin()) != parents.end()) {
- new_parents.insert((*i).first);
-#if defined(CARVE_DEBUG)
- std::cerr << "parent(" << (*i).first << "): " << *(*i).second.begin() << std::endl;
-#endif
- } else {
-#if defined(CARVE_DEBUG)
- std::cerr << "no parent: " << (*i).first << " (looking for: " << *(*i).second.begin() << ")" << std::endl;
-#endif
- }
- }
- }
- for (std::set<int>::const_iterator i = new_parents.begin(); i != new_parents.end(); ++i) {
- embedding.erase(*i);
- }
- for (std::map<int, std::set<int> >::iterator i = embedding.begin(); i != embedding.end(); ++i) {
- size_t n = 0;
- for (std::set<int>::const_iterator j = parents.begin(); j != parents.end(); ++j) {
- n += (*i).second.erase((*j));
- }
- CARVE_ASSERT(n != 0);
- }
- parents.swap(new_parents);
- }
-
- return true;
- }
-
-
-
- bool Polyhedron::init() {
- static carve::TimingName FUNC_NAME("Polyhedron::init()");
- carve::TimingBlock block(FUNC_NAME);
-
- aabb.fit(vertices.begin(), vertices.end(), vec_adapt_vertex_ref());
-
- connectivity.vertex_to_edge.clear();
- connectivity.vertex_to_face.clear();
- connectivity.edge_to_face.clear();
-
- if (!initConnectivity()) return false;
- if (!initSpatialIndex()) return false;
-
- return true;
- }
-
-
-
- void Polyhedron::faceRecalc() {
- for (size_t i = 0; i < faces.size(); ++i) {
- if (!faces[i].recalc()) {
- std::ostringstream out;
- out << "face " << i << " recalc failed";
- throw carve::exception(out.str());
- }
- }
- }
-
-
-
- Polyhedron::Polyhedron(const Polyhedron &poly) {
- faces.reserve(poly.faces.size());
-
- for (size_t i = 0; i < poly.faces.size(); ++i) {
- const face_t &src = poly.faces[i];
- faces.push_back(src);
- }
- commonFaceInit(false); // calls setFaceAndVertexOwner() and init()
- }
-
-
-
- Polyhedron::Polyhedron(const Polyhedron &poly, const std::vector<bool> &selected_manifolds) {
- size_t n_faces = 0;
-
- for (size_t i = 0; i < poly.faces.size(); ++i) {
- const face_t &src = poly.faces[i];
- if (src.manifold_id >= 0 &&
- (unsigned)src.manifold_id < selected_manifolds.size() &&
- selected_manifolds[src.manifold_id]) {
- n_faces++;
- }
- }
-
- faces.reserve(n_faces);
-
- for (size_t i = 0; i < poly.faces.size(); ++i) {
- const face_t &src = poly.faces[i];
- if (src.manifold_id >= 0 &&
- (unsigned)src.manifold_id < selected_manifolds.size() &&
- selected_manifolds[src.manifold_id]) {
- faces.push_back(src);
- }
- }
-
- commonFaceInit(false); // calls setFaceAndVertexOwner() and init()
- }
-
-
-
- Polyhedron::Polyhedron(const Polyhedron &poly, int m_id) {
- size_t n_faces = 0;
-
- for (size_t i = 0; i < poly.faces.size(); ++i) {
- const face_t &src = poly.faces[i];
- if (src.manifold_id == m_id) n_faces++;
- }
-
- faces.reserve(n_faces);
-
- for (size_t i = 0; i < poly.faces.size(); ++i) {
- const face_t &src = poly.faces[i];
- if (src.manifold_id == m_id) faces.push_back(src);
- }
-
- commonFaceInit(false); // calls setFaceAndVertexOwner() and init()
- }
-
-
-
- Polyhedron::Polyhedron(const std::vector<carve::geom3d::Vector> &_vertices,
- int n_faces,
- const std::vector<int> &face_indices) {
- // The polyhedron is defined by a vector of vertices, which we
- // want to copy, and a face index list, from which we need to
- // generate a set of Faces.
-
- vertices.clear();
- vertices.resize(_vertices.size());
- for (size_t i = 0; i < _vertices.size(); ++i) {
- vertices[i].v = _vertices[i];
- }
-
- faces.reserve(n_faces);
-
- std::vector<int>::const_iterator iter = face_indices.begin();
- std::vector<const vertex_t *> v;
- for (int i = 0; i < n_faces; ++i) {
- int vertexCount = *iter++;
-
- v.clear();
-
- while (vertexCount--) {
- CARVE_ASSERT(*iter >= 0);
- CARVE_ASSERT((unsigned)*iter < vertices.size());
- v.push_back(&vertices[*iter++]);
- }
- faces.push_back(face_t(v));
- }
-
- setFaceAndVertexOwner();
-
- if (!init()) {
- throw carve::exception("polyhedron creation failed");
- }
- }
-
-
-
- Polyhedron::Polyhedron(std::vector<face_t> &_faces,
- std::vector<vertex_t> &_vertices,
- bool _recalc) {
- faces.swap(_faces);
- vertices.swap(_vertices);
-
- setFaceAndVertexOwner();
-
- if (_recalc) faceRecalc();
-
- if (!init()) {
- throw carve::exception("polyhedron creation failed");
- }
- }
-
-
-
- Polyhedron::Polyhedron(std::vector<face_t> &_faces,
- bool _recalc) {
- faces.swap(_faces);
- commonFaceInit(_recalc); // calls setFaceAndVertexOwner() and init()
- }
-
-
-
- Polyhedron::Polyhedron(std::list<face_t> &_faces,
- bool _recalc) {
- faces.reserve(_faces.size());
- std::copy(_faces.begin(), _faces.end(), std::back_inserter(faces));
- commonFaceInit(_recalc); // calls setFaceAndVertexOwner() and init()
- }
-
-
-
- void Polyhedron::collectFaceVertices(std::vector<face_t> &faces,
- std::vector<vertex_t> &vertices,
- std::unordered_map<const vertex_t *, const vertex_t *> &vmap) {
- // Given a set of faces, copy all referenced vertices into a
- // single vertex array and update the faces to point into that
- // array. On exit, vmap contains a mapping from old pointer to
- // new pointer.
-
- vertices.clear();
- vmap.clear();
-
- for (size_t i = 0, il = faces.size(); i != il; ++i) {
- face_t &f = faces[i];
-
- for (size_t j = 0, jl = f.nVertices(); j != jl; ++j) {
- vmap[f.vertex(j)] = NULL;
- }
- }
-
- vertices.reserve(vmap.size());
-
- for (std::unordered_map<const vertex_t *, const vertex_t *>::iterator i = vmap.begin(),
- e = vmap.end();
- i != e;
- ++i) {
- vertices.push_back(*(*i).first);
- (*i).second = &vertices.back();
- }
-
- for (size_t i = 0, il = faces.size(); i != il; ++i) {
- face_t &f = faces[i];
-
- for (size_t j = 0, jl = f.nVertices(); j != jl; ++j) {
- f.vertex(j) = vmap[f.vertex(j)];
- }
- }
- }
-
-
-
- void Polyhedron::collectFaceVertices(std::vector<face_t> &faces,
- std::vector<vertex_t> &vertices) {
- std::unordered_map<const vertex_t *, const vertex_t *> vmap;
- collectFaceVertices(faces, vertices, vmap);
- }
-
-
-
- void Polyhedron::setFaceAndVertexOwner() {
- for (size_t i = 0; i < vertices.size(); ++i) vertices[i].owner = this;
- for (size_t i = 0; i < faces.size(); ++i) faces[i].owner = this;
- }
-
-
-
- void Polyhedron::commonFaceInit(bool _recalc) {
- collectFaceVertices(faces, vertices);
- setFaceAndVertexOwner();
- if (_recalc) faceRecalc();
-
- if (!init()) {
- throw carve::exception("polyhedron creation failed");
- }
- }
-
-
-
- Polyhedron::~Polyhedron() {
- }
-
-
-
- void Polyhedron::testVertexAgainstClosedManifolds(const carve::geom3d::Vector &v,
- std::map<int, PointClass> &result,
- bool ignore_orientation) const {
-
- for (size_t i = 0; i < faces.size(); i++) {
- if (!manifold_is_closed[faces[i].manifold_id]) continue; // skip open manifolds
- if (faces[i].containsPoint(v)) {
- result[faces[i].manifold_id] = POINT_ON;
- }
- }
-
- double ray_len = aabb.extent.length() * 2;
-
- std::vector<const face_t *> possible_faces;
-
- std::vector<std::pair<const face_t *, carve::geom3d::Vector> > manifold_intersections;
-
- boost::mt19937 rng;
- boost::uniform_on_sphere<double> distrib(3);
- boost::variate_generator<boost::mt19937 &, boost::uniform_on_sphere<double> > gen(rng, distrib);
-
- for (;;) {
- carve::geom3d::Vector ray_dir;
- ray_dir = gen();
-
- carve::geom3d::Vector v2 = v + ray_dir * ray_len;
-
- bool failed = false;
- carve::geom3d::LineSegment line(v, v2);
- carve::geom3d::Vector intersection;
-
- possible_faces.clear();
- manifold_intersections.clear();
- octree.findFacesNear(line, possible_faces);
-
- for (unsigned i = 0; !failed && i < possible_faces.size(); i++) {
- if (!manifold_is_closed[possible_faces[i]->manifold_id]) continue; // skip open manifolds
- if (result.find(possible_faces[i]->manifold_id) != result.end()) continue; // already ON
-
- switch (possible_faces[i]->lineSegmentIntersection(line, intersection)) {
- case INTERSECT_FACE: {
- manifold_intersections.push_back(std::make_pair(possible_faces[i], intersection));
- break;
- }
- case INTERSECT_NONE: {
- break;
- }
- default: {
- failed = true;
- break;
- }
- }
- }
-
- if (!failed) break;
- }
-
- std::vector<int> crossings(manifold_is_closed.size(), 0);
-
- for (size_t i = 0; i < manifold_intersections.size(); ++i) {
- const face_t *f = manifold_intersections[i].first;
- crossings[f->manifold_id]++;
- }
-
- for (size_t i = 0; i < crossings.size(); ++i) {
-#if defined(CARVE_DEBUG)
- std::cerr << "crossing: " << i << " = " << crossings[i] << " is_negative = " << manifold_is_negative[i] << std::endl;
-#endif
- if (!manifold_is_closed[i]) continue;
- if (result.find(i) != result.end()) continue;
- PointClass pc = (crossings[i] & 1) ? POINT_IN : POINT_OUT;
- if (!ignore_orientation && manifold_is_negative[i]) pc = (PointClass)-pc;
- result[i] = pc;
- }
- }
-
-
-
- PointClass Polyhedron::containsVertex(const carve::geom3d::Vector &v,
- const face_t **hit_face,
- bool even_odd,
- int manifold_id) const {
- if (hit_face) *hit_face = NULL;
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{containsVertex " << v << "}" << std::endl;
-#endif
-
- if (!aabb.containsPoint(v)) {
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{final:OUT(aabb short circuit)}" << std::endl;
-#endif
- // XXX: if the top level manifolds are negative, this should be POINT_IN.
- // for the moment, this only works for a single manifold.
- if (manifold_is_negative.size() == 1 && manifold_is_negative[0]) return POINT_IN;
- return POINT_OUT;
- }
-
- for (size_t i = 0; i < faces.size(); i++) {
- if (manifold_id != -1 && manifold_id != faces[i].manifold_id) continue;
-
- // XXX: Do allow the tested vertex to be ON an open
- // manifold. This was here originally because of the
- // possibility of an open manifold contained within a closed
- // manifold.
-
- // if (!manifold_is_closed[faces[i].manifold_id]) continue;
-
- if (faces[i].containsPoint(v)) {
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{final:ON(hits face " << &faces[i] << ")}" << std::endl;
-#endif
- if (hit_face) *hit_face = &faces[i];
- return POINT_ON;
- }
- }
-
- double ray_len = aabb.extent.length() * 2;
-
- std::vector<const face_t *> possible_faces;
-
- std::vector<std::pair<const face_t *, carve::geom3d::Vector> > manifold_intersections;
-
- for (;;) {
- double a1 = random() / double(RAND_MAX) * M_TWOPI;
- double a2 = random() / double(RAND_MAX) * M_TWOPI;
-
- carve::geom3d::Vector ray_dir = carve::geom::VECTOR(sin(a1) * sin(a2), cos(a1) * sin(a2), cos(a2));
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{testing ray: " << ray_dir << "}" << std::endl;
-#endif
-
- carve::geom3d::Vector v2 = v + ray_dir * ray_len;
-
- bool failed = false;
- carve::geom3d::LineSegment line(v, v2);
- carve::geom3d::Vector intersection;
-
- possible_faces.clear();
- manifold_intersections.clear();
- octree.findFacesNear(line, possible_faces);
-
- for (unsigned i = 0; !failed && i < possible_faces.size(); i++) {
- if (manifold_id != -1 && manifold_id != faces[i].manifold_id) continue;
-
- if (!manifold_is_closed[possible_faces[i]->manifold_id]) continue;
-
- switch (possible_faces[i]->lineSegmentIntersection(line, intersection)) {
- case INTERSECT_FACE: {
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{intersects face: " << possible_faces[i]
- << " dp: " << dot(ray_dir, possible_faces[i]->plane_eqn.N) << "}" << std::endl;
-#endif
-
- if (!even_odd && fabs(dot(ray_dir, possible_faces[i]->plane_eqn.N)) < EPSILON) {
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{failing(small dot product)}" << std::endl;
-#endif
-
- failed = true;
- break;
- }
- manifold_intersections.push_back(std::make_pair(possible_faces[i], intersection));
- break;
- }
- case INTERSECT_NONE: {
- break;
- }
- default: {
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{failing(degenerate intersection)}" << std::endl;
-#endif
- failed = true;
- break;
- }
- }
- }
-
- if (!failed) {
- if (even_odd) {
- return (manifold_intersections.size() & 1) ? POINT_IN : POINT_OUT;
- }
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{intersections ok [count:"
- << manifold_intersections.size()
- << "], sorting}"
- << std::endl;
-#endif
-
- carve::geom3d::sortInDirectionOfRay(ray_dir,
- manifold_intersections.begin(),
- manifold_intersections.end(),
- carve::geom3d::vec_adapt_pair_second());
-
- std::vector<int> crossings(manifold_is_closed.size(), 0);
-
- for (size_t i = 0; i < manifold_intersections.size(); ++i) {
- const face_t *f = manifold_intersections[i].first;
- if (dot(ray_dir, f->plane_eqn.N) < 0.0) {
- crossings[f->manifold_id]++;
- } else {
- crossings[f->manifold_id]--;
- }
- }
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- for (size_t i = 0; i < crossings.size(); ++i) {
- std::cerr << "{manifold " << i << " crossing count: " << crossings[i] << "}" << std::endl;
- }
-#endif
-
- for (size_t i = 0; i < manifold_intersections.size(); ++i) {
- const face_t *f = manifold_intersections[i].first;
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{intersection at "
- << manifold_intersections[i].second
- << " id: "
- << f->manifold_id
- << " count: "
- << crossings[f->manifold_id]
- << "}"
- << std::endl;
-#endif
-
- if (crossings[f->manifold_id] < 0) {
- // inside this manifold.
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{final:IN}" << std::endl;
-#endif
-
- return POINT_IN;
- } else if (crossings[f->manifold_id] > 0) {
- // outside this manifold, but it's an infinite manifold. (for instance, an inverted cube)
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{final:OUT}" << std::endl;
-#endif
-
- return POINT_OUT;
- }
- }
-
-#if defined(DEBUG_CONTAINS_VERTEX)
- std::cerr << "{final:OUT(default)}" << std::endl;
-#endif
-
- return POINT_OUT;
- }
- }
- }
-
-
-
- void Polyhedron::findEdgesNear(const carve::geom::aabb<3> &aabb,
- std::vector<const edge_t *> &outEdges) const {
- outEdges.clear();
- octree.findEdgesNear(aabb, outEdges);
- }
-
-
-
- void Polyhedron::findEdgesNear(const carve::geom3d::LineSegment &line,
- std::vector<const edge_t *> &outEdges) const {
- outEdges.clear();
- octree.findEdgesNear(line, outEdges);
- }
-
-
-
- void Polyhedron::findEdgesNear(const carve::geom3d::Vector &v,
- std::vector<const edge_t *> &outEdges) const {
- outEdges.clear();
- octree.findEdgesNear(v, outEdges);
- }
-
-
-
- void Polyhedron::findEdgesNear(const face_t &face,
- std::vector<const edge_t *> &edges) const {
- edges.clear();
- octree.findEdgesNear(face, edges);
- }
-
-
-
- void Polyhedron::findEdgesNear(const edge_t &edge,
- std::vector<const edge_t *> &outEdges) const {
- outEdges.clear();
- octree.findEdgesNear(edge, outEdges);
- }
-
-
-
- void Polyhedron::findFacesNear(const carve::geom3d::LineSegment &line,
- std::vector<const face_t *> &outFaces) const {
- outFaces.clear();
- octree.findFacesNear(line, outFaces);
- }
-
-
-
- void Polyhedron::findFacesNear(const carve::geom::aabb<3> &aabb,
- std::vector<const face_t *> &outFaces) const {
- outFaces.clear();
- octree.findFacesNear(aabb, outFaces);
- }
-
-
-
- void Polyhedron::findFacesNear(const edge_t &edge,
- std::vector<const face_t *> &outFaces) const {
- outFaces.clear();
- octree.findFacesNear(edge, outFaces);
- }
-
-
-
- void Polyhedron::transform(const carve::math::Matrix &xform) {
- for (size_t i = 0; i < vertices.size(); i++) {
- vertices[i].v = xform * vertices[i].v;
- }
- for (size_t i = 0; i < faces.size(); i++) {
- faces[i].recalc();
- }
- init();
- }
-
-
-
- void Polyhedron::print(std::ostream &o) const {
- o << "Polyhedron@" << this << " {" << std::endl;
- for (std::vector<vertex_t >::const_iterator
- i = vertices.begin(), e = vertices.end(); i != e; ++i) {
- o << " V@" << &(*i) << " " << (*i).v << std::endl;
- }
- for (std::vector<edge_t >::const_iterator
- i = edges.begin(), e = edges.end(); i != e; ++i) {
- o << " E@" << &(*i) << " {" << std::endl;
- o << " V@" << (*i).v1 << " - " << "V@" << (*i).v2 << std::endl;
- const std::vector<const face_t *> &faces = connectivity.edge_to_face[edgeToIndex_fast(&(*i))];
- for (size_t j = 0; j < (faces.size() & ~1U); j += 2) {
- o << " fp: F@" << faces[j] << ", F@" << faces[j+1] << std::endl;
- }
- o << " }" << std::endl;
- }
- for (std::vector<face_t >::const_iterator
- i = faces.begin(), e = faces.end(); i != e; ++i) {
- o << " F@" << &(*i) << " {" << std::endl;
- o << " vertices {" << std::endl;
- for (face_t::const_vertex_iter_t j = (*i).vbegin(), je = (*i).vend(); j != je; ++j) {
- o << " V@" << (*j) << std::endl;
- }
- o << " }" << std::endl;
- o << " edges {" << std::endl;
- for (face_t::const_edge_iter_t j = (*i).ebegin(), je = (*i).eend(); j != je; ++j) {
- o << " E@" << (*j) << std::endl;
- }
- carve::geom::plane<3> p = (*i).plane_eqn;
- o << " }" << std::endl;
- o << " normal " << (*i).plane_eqn.N << std::endl;
- o << " aabb " << (*i).aabb << std::endl;
- o << " plane_eqn ";
- carve::geom::operator<< <3>(o, p);
- o << std::endl;
- o << " }" << std::endl;
- }
-
- o << "}" << std::endl;
- }
-
-
-
- void Polyhedron::canonicalize() {
- orderVertices();
- for (size_t i = 0; i < faces.size(); i++) {
- face_t &f = faces[i];
- size_t j = std::distance(f.vbegin(),
- std::min_element(f.vbegin(),
- f.vend()));
- if (j) {
- {
- std::vector<const vertex_t *> temp;
- temp.reserve(f.nVertices());
- std::copy(f.vbegin() + j, f.vend(), std::back_inserter(temp));
- std::copy(f.vbegin(), f.vbegin() + j, std::back_inserter(temp));
- std::copy(temp.begin(), temp.end(), f.vbegin());
- }
- {
- std::vector<const edge_t *> temp;
- temp.reserve(f.nEdges());
- std::copy(f.ebegin() + j, f.eend(), std::back_inserter(temp));
- std::copy(f.ebegin(), f.ebegin() + j, std::back_inserter(temp));
- std::copy(temp.begin(), temp.end(), f.ebegin());
- }
- }
- }
-
- std::vector<face_t *> face_ptrs;
- face_ptrs.reserve(faces.size());
- for (size_t i = 0; i < faces.size(); ++i) face_ptrs.push_back(&faces[i]);
- std::sort(face_ptrs.begin(), face_ptrs.end(), order_faces());
- std::vector<face_t> sorted_faces;
- sorted_faces.reserve(faces.size());
- for (size_t i = 0; i < faces.size(); ++i) sorted_faces.push_back(*face_ptrs[i]);
- std::swap(faces, sorted_faces);
- }
-
- }
-}
-
diff --git a/extern/carve/lib/polyline.cpp b/extern/carve/lib/polyline.cpp
deleted file mode 100644
index 999d3f506c2..00000000000
--- a/extern/carve/lib/polyline.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/geom.hpp>
-#include <carve/vector.hpp>
-#include <carve/polyline.hpp>
-
-namespace carve {
- namespace line {
- carve::geom3d::AABB Polyline::aabb() const {
- return carve::geom3d::AABB(vbegin(), vend(), vec_adapt_vertex_ptr());
- }
-
- PolylineSet::PolylineSet(const std::vector<carve::geom3d::Vector> &points) {
- vertices.resize(points.size());
- for (size_t i = 0; i < points.size(); ++i) vertices[i].v = points[i];
- aabb.fit(points.begin(), points.end(), carve::geom3d::vec_adapt_ident());
- }
-
- void PolylineSet::sortVertices(const carve::geom3d::Vector &axis) {
- std::vector<std::pair<double, size_t> > temp;
- temp.reserve(vertices.size());
- for (size_t i = 0; i < vertices.size(); ++i) {
- temp.push_back(std::make_pair(dot(axis, vertices[i].v), i));
- }
- std::sort(temp.begin(), temp.end());
- std::vector<Vertex> vnew;
- std::vector<int> revmap;
- vnew.reserve(vertices.size());
- revmap.resize(vertices.size());
-
- for (size_t i = 0; i < vertices.size(); ++i) {
- vnew.push_back(vertices[temp[i].second]);
- revmap[temp[i].second] = i;
- }
-
- for (line_iter i = lines.begin(); i != lines.end(); ++i) {
- Polyline &l = *(*i);
- for (size_t j = 0; j < l.edges.size(); ++j) {
- PolylineEdge &e = *l.edges[j];
- if (e.v1) e.v1 = &vnew[revmap[vertexToIndex_fast(e.v1)]];
- if (e.v2) e.v2 = &vnew[revmap[vertexToIndex_fast(e.v2)]];
- }
- }
- vertices.swap(vnew);
- }
-
- }
-}
diff --git a/extern/carve/lib/tag.cpp b/extern/carve/lib/tag.cpp
deleted file mode 100644
index a7a9ab3c80d..00000000000
--- a/extern/carve/lib/tag.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/tag.hpp>
-
-int carve::tagable::s_count = 0;
diff --git a/extern/carve/lib/timing.cpp b/extern/carve/lib/timing.cpp
deleted file mode 100644
index 510dc48f6ad..00000000000
--- a/extern/carve/lib/timing.cpp
+++ /dev/null
@@ -1,436 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if CARVE_USE_TIMINGS
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/timing.hpp>
-
-#include <cstring>
-#include <list>
-#include <stack>
-#include <vector>
-#include <map>
-#include <iostream>
-#include <string>
-#include <algorithm>
-
-#ifdef WIN32
-#include <windows.h>
-#else
-#include <time.h>
-#include <sys/time.h>
-#endif
-
-#ifndef CARVE_USE_GLOBAL_NEW_DELETE
-#define CARVE_USE_GLOBAL_NEW_DELETE 0
-#endif
-
-namespace carve {
- static uint64_t memoryCurr = 0;
- static uint64_t memoryTotal = 0;
- unsigned blkCntCurr[32] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
- unsigned blkCntTotal[32] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
-
- void addBlk(unsigned size) {
- unsigned i = 0;
- while (i < 31 && (1U<<i) < size) ++i;
- blkCntCurr[i]++;
- blkCntTotal[i]++;
- }
- void remBlk(unsigned size) {
- unsigned i = 0;
- while (i < 31 && (1<<i) < size) ++i;
- blkCntCurr[i]--;
- }
-}
-
-// lets provide a global new and delete as well
-
-#if CARVE_USE_GLOBAL_NEW_DELETE
-
-#if defined(__APPLE__)
-
-#include <stdlib.h>
-#include <malloc/malloc.h>
-
-void* carve_alloc(size_t size) {
- void *p = malloc(size);
- if (p == 0) throw std::bad_alloc(); // ANSI/ISO compliant behavior
-
- unsigned sz = malloc_size(p);
- carve::memoryCurr += sz;
- carve::memoryTotal += sz;
- carve::addBlk(sz);
- return p;
-}
-
-void carve_free(void *p) {
- unsigned sz = malloc_size(p);
- carve::memoryCurr -= sz;
- carve::remBlk(sz);
- free(p);
-}
-
-#else
-
-void* carve_alloc(size_t size) {
- void *p = malloc(size + 4);
- if (p == 0) throw std::bad_alloc(); // ANSI/ISO compliant behavior
-
- int *sizePtr = (int*)p;
- *sizePtr = size;
- ++sizePtr;
- carve::memoryCurr += size;
- carve::memoryTotal += size;
- carve::addBlk(size);
- return sizePtr;
-}
-
-void carve_free(void *p) {
- // our memory block is actually a size of an int behind this pointer.
- int *sizePtr = (int*)p;
-
- --sizePtr;
-
- carve::memoryCurr -= *sizePtr;
- int size = *sizePtr;
- carve::remBlk(size);
- free(sizePtr);
-}
-
-#endif
-
-
-void* operator new (size_t size) {
- return carve_alloc(size);
-}
-
-void* operator new[](size_t size) {
- return carve_alloc(size);
-}
-
-
-void operator delete (void *p) {
- carve_free(p);
-}
-
-void operator delete[](void *p) {
- carve_free(p);
-}
-
-#endif
-
-namespace carve {
-
-
-
-#ifdef WIN32
-
- typedef __int64 precise_time_t;
-
- precise_time_t g_frequency;
-
- void initTime() {
- ::QueryPerformanceFrequency((LARGE_INTEGER*)&g_frequency);
- }
-
- void getTime(precise_time_t &t) {
- ::QueryPerformanceCounter((LARGE_INTEGER*)&t);
- }
-
- double diffTime(precise_time_t from, precise_time_t to) {
- return (double)(to - from) / (double)g_frequency;
- }
-
-#else
-
- typedef double precise_time_t;
-
- void initTime() {
- }
-
- void getTime(precise_time_t &t) {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- t = tv.tv_sec + tv.tv_usec / 1000000.0;
- }
-
- double diffTime(precise_time_t from, precise_time_t to) {
- return to - from;
- }
-
-#endif
-
- struct Entry {
- Entry(int _id) {
- id = _id;
- time = 0;
- parent = NULL;
- }
- int id;
- double time;
- int64_t memoryDiff;
- int64_t allocTotal;
- int delta_blk_cnt_curr[32];
- int delta_blk_cnt_total[32];
- Entry *parent;
- std::vector<Entry *> children;
- };
-
- struct Timer {
- struct cmp {
- bool operator()(const std::pair<int, double> &a, const std::pair<int, double> &b) const {
- return b.second < a.second;
- }
- bool operator()(const Entry * const &a, const Entry * const &b) const {
- return b->time < a->time;
- }
- };
-
- Timer() {
- initTime();
- }
-
- struct Snapshot {
- precise_time_t time;
- uint64_t memory_curr;
- uint64_t memory_total;
- unsigned blk_cnt_curr[32];
- unsigned blk_cnt_total[32];
- };
-
- static void getSnapshot(Snapshot &snapshot) {
- getTime(snapshot.time);
- snapshot.memory_curr = carve::memoryCurr;
- snapshot.memory_total = carve::memoryTotal;
- std::memcpy(snapshot.blk_cnt_curr, carve::blkCntCurr, sizeof(carve::blkCntCurr));
- std::memcpy(snapshot.blk_cnt_total, carve::blkCntTotal, sizeof(carve::blkCntTotal));
- }
-
- static void compareSnapshot(const Snapshot &from, const Snapshot &to, Entry *entry) {
- entry->time = diffTime(from.time, to.time);
- entry->memoryDiff = to.memory_curr - from.memory_curr;
- entry->allocTotal = to.memory_total - from.memory_total;
- for (int i = 0; i < 32; i++) {
- entry->delta_blk_cnt_curr[i] = to.blk_cnt_curr[i] - from.blk_cnt_curr[i];
- entry->delta_blk_cnt_total[i] = to.blk_cnt_total[i] - from.blk_cnt_total[i];
- }
- }
-
- std::stack<std::pair<Entry*, Snapshot> > currentTimers;
-
- void startTiming(int id) {
- entries.push_back(Entry(id));
- currentTimers.push(std::make_pair(&entries.back(), Snapshot()));
- getSnapshot(currentTimers.top().second);
- }
-
- double endTiming() {
- Snapshot end;
- getSnapshot(end);
-
- Entry *entry = currentTimers.top().first;
- compareSnapshot(currentTimers.top().second, end, entry);
-
- currentTimers.pop();
- if (!currentTimers.empty()) {
- entry->parent = currentTimers.top().first;
- entry->parent->children.push_back(entry);
- } else {
- root_entries.push_back(entry);
- }
- //std::sort(entry->children.begin(), entry->children.end(), cmp());
- return entry->time;
- }
-
- typedef std::list<Entry> EntryList;
- EntryList entries;
- std::vector<Entry *> root_entries;
-
- std::map<int, std::string> names;
-
- static std::string formatMemory(int64_t value) {
-
- std::ostringstream result;
-
- result << (value >= 0 ? "+" : "-");
- if (value < 0) {
- value = -value;
- }
-
- int power = 1;
- while (value > pow(10.0, power)) {
- power++;
- }
-
- for (power--; power >= 0; power--) {
- int64_t base = pow(10.0, power);
- int64_t amount = value / base;
- result <<
-#if defined(_MSC_VER) && _MSC_VER < 1300
- (long)
-#endif
- amount;
- if (power > 0 && (power % 3) == 0) {
- result << ",";
- }
- value -= amount * base;
- }
-
- result << " bytes";
-
- return result.str();
- }
-
- void printEntries(std::ostream &o, const std::vector<Entry *> &entries, const std::string &indent, double parent_time) {
- if (parent_time <= 0.0) {
- parent_time = 0.0;
- for (size_t i = 0; i < entries.size(); ++i) {
- parent_time += entries[i]->time;
- }
- }
- double t_tot = 0.0;
- for (size_t i = 0; i < entries.size(); ++i) {
- const Entry *entry = entries[i];
-
- std::ostringstream r;
- r << indent;
- std::string str = names[entry->id];
- if (str.empty()) {
- r << "(" << entry->id << ")";
- } else {
- r << str;
- }
- r << " ";
- std::string pad(r.str().size(), ' ');
- r << " - exectime: " << entry->time << "s (" << (entry->time * 100.0 / parent_time) << "%)" << std::endl;
- if (entry->allocTotal || entry->memoryDiff) {
- r << pad << " - alloc: " << formatMemory(entry->allocTotal) << " delta: " << formatMemory(entry->memoryDiff) << std::endl;
- r << pad << " - alloc blks:";
- for (int i = 0; i < 32; i++) { if (entry->delta_blk_cnt_total[i]) r << ' ' << ((1 << (i - 1)) + 1) << '-' << (1 << i) << ':' << entry->delta_blk_cnt_total[i]; }
- r << std::endl;
- r << pad << " - delta blks:";
- for (int i = 0; i < 32; i++) { if (entry->delta_blk_cnt_curr[i]) r << ' ' << ((1 << (i - 1)) + 1) << '-' << (1 << i) << ':' << entry->delta_blk_cnt_curr[i]; }
- r << std::endl;
- }
- o << r.str();
- t_tot += entry->time;
- if (entry->children.size()) printEntries(o, entry->children, indent + " ", entry->time);
- }
- if (t_tot < parent_time) {
- o << indent << "*** unaccounted: " << (parent_time - t_tot) << "s (" << (100.0 - t_tot * 100.0 / parent_time) << "%)" << std::endl;
- }
- }
-
- void print() {
- std::map<int, double> totals;
- std::cerr << "Timings: " << std::endl;
- // print out all the entries.
-
- //std::sort(root_entries.begin(), root_entries.end(), cmp());
-
- printEntries(std::cerr, root_entries, " ", -1.0);
-
- for (EntryList::const_iterator it = entries.begin(); it != entries.end(); ++it) {
- totals[(*it).id] += (*it).time;
- }
-
- std::cerr << std::endl;
- std::cerr << "Totals: " << std::endl;
-
- std::vector<std::pair<int, double> > sorted_totals;
- sorted_totals.reserve(totals.size());
- for (std::map<int,double>::iterator it = totals.begin(); it != totals.end(); ++it) {
- sorted_totals.push_back(*it);
- }
-
- std::sort(sorted_totals.begin(), sorted_totals.end(), cmp());
-
- for (std::vector<std::pair<int,double> >::iterator it = sorted_totals.begin(); it != sorted_totals.end(); ++it) {
- std::cerr << " ";
- std::string str = names[it->first];
- if (str.empty()) {
- std::cerr << "(" << it->first << ")";
- } else {
- std::cerr << str;
- }
- std::cerr << " - " << it->second << "s " << std::endl;
- }
- }
- void registerID(int id, const char *name) {
- names[id] = name;
- }
- int registerID(const char *name) {
- int id = names.size() + 1;
- names[id] = name;
- return id;
- }
-
- };
-
- Timer timer;
-
-
- TimingBlock::TimingBlock(int id) {
-#if CARVE_USE_TIMINGS
- timer.startTiming(id);
-#endif
- }
-
- TimingBlock::TimingBlock(const TimingName &name) {
-#if CARVE_USE_TIMINGS
- timer.startTiming(name.id);
-#endif
- }
-
-
- TimingBlock::~TimingBlock() {
-#if CARVE_USE_TIMINGS
- timer.endTiming();
-#endif
- }
- void Timing::start(int id) {
-#if CARVE_USE_TIMINGS
- timer.startTiming(id);
-#endif
- }
-
- double Timing::stop() {
-#if CARVE_USE_TIMINGS
- return timer.endTiming();
-#endif
- }
-
- void Timing::printTimings() {
- timer.print();
- }
-
- void Timing::registerID(int id, const char *name) {
- timer.registerID(id, name);
- }
-
- TimingName::TimingName(const char *name) {
- id = timer.registerID(name);
- }
-
-}
-
-#endif
diff --git a/extern/carve/lib/triangulator.cpp b/extern/carve/lib/triangulator.cpp
deleted file mode 100644
index a48a9ccfa45..00000000000
--- a/extern/carve/lib/triangulator.cpp
+++ /dev/null
@@ -1,1200 +0,0 @@
-// Begin License:
-// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
-// All rights reserved.
-//
-// This file is part of the Carve CSG Library (http://carve-csg.com/)
-//
-// This file may be used under the terms of either the GNU General
-// Public License version 2 or 3 (at your option) as published by the
-// Free Software Foundation and appearing in the files LICENSE.GPL2
-// and LICENSE.GPL3 included in the packaging of this file.
-//
-// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE.
-// End:
-
-
-#if defined(HAVE_CONFIG_H)
-# include <carve_config.h>
-#endif
-
-#include <carve/csg.hpp>
-#include <carve/triangulator.hpp>
-
-#include <fstream>
-#include <sstream>
-
-#include <algorithm>
-
-namespace {
- // private code related to hole patching.
-
- class order_h_loops_2d {
- order_h_loops_2d &operator=(const order_h_loops_2d &);
-
- const std::vector<std::vector<carve::geom2d::P2> > &poly;
- int axis;
- public:
-
- order_h_loops_2d(const std::vector<std::vector<carve::geom2d::P2> > &_poly, int _axis) :
- poly(_poly), axis(_axis) {
- }
-
- bool operator()(const std::pair<size_t, size_t> &a,
- const std::pair<size_t, size_t> &b) const {
- return carve::triangulate::detail::axisOrdering(poly[a.first][a.second], poly[b.first][b.second], axis);
- }
- };
-
- class heap_ordering_2d {
- heap_ordering_2d &operator=(const heap_ordering_2d &);
-
- const std::vector<std::vector<carve::geom2d::P2> > &poly;
- const std::vector<std::pair<size_t, size_t> > &loop;
- const carve::geom2d::P2 p;
- int axis;
-
- public:
-
- heap_ordering_2d(const std::vector<std::vector<carve::geom2d::P2> > &_poly,
- const std::vector<std::pair<size_t, size_t> > &_loop,
- const carve::geom2d::P2 _p,
- int _axis) : poly(_poly), loop(_loop), p(_p), axis(_axis) {
- }
-
- bool operator()(size_t a, size_t b) const {
- double da = carve::geom::distance2(p, poly[loop[a].first][loop[a].second]);
- double db = carve::geom::distance2(p, poly[loop[b].first][loop[b].second]);
- if (da > db) return true;
- if (da < db) return false;
- return carve::triangulate::detail::axisOrdering(poly[loop[a].first][loop[a].second], poly[loop[b].first][loop[b].second], axis);
- }
- };
-
- static inline void patchHoleIntoPolygon_2d(std::vector<std::pair<size_t, size_t> > &f_loop,
- size_t f_loop_attach,
- size_t h_loop,
- size_t h_loop_attach,
- size_t h_loop_size) {
- f_loop.insert(f_loop.begin() + f_loop_attach + 1, h_loop_size + 2, std::make_pair(h_loop, 0));
- size_t f = f_loop_attach + 1;
-
- for (size_t h = h_loop_attach; h != h_loop_size; ++h) {
- f_loop[f++].second = h;
- }
-
- for (size_t h = 0; h <= h_loop_attach; ++h) {
- f_loop[f++].second = h;
- }
-
- f_loop[f] = f_loop[f_loop_attach];
- }
-
- static inline const carve::geom2d::P2 &pvert(const std::vector<std::vector<carve::geom2d::P2> > &poly, const std::pair<size_t, size_t> &idx) {
- return poly[idx.first][idx.second];
- }
-}
-
-
-namespace {
- // private code related to triangulation.
-
- using carve::triangulate::detail::vertex_info;
-
- struct vertex_info_ordering {
- bool operator()(const vertex_info *a, const vertex_info *b) const {
- return a->score < b->score;
- }
- };
-
- struct vertex_info_l2norm_inc_ordering {
- const vertex_info *v;
- vertex_info_l2norm_inc_ordering(const vertex_info *_v) : v(_v) {
- }
- bool operator()(const vertex_info *a, const vertex_info *b) const {
- return carve::geom::distance2(v->p, a->p) > carve::geom::distance2(v->p, b->p);
- }
- };
-
- class EarQueue {
- std::vector<vertex_info *> queue;
-
- void checkheap() {
-#if defined(HAVE_IS_HEAP)
- CARVE_ASSERT(std::__is_heap(queue.begin(), queue.end(), vertex_info_ordering()));
-#endif
- }
-
- public:
- EarQueue() {
- }
-
- size_t size() const {
- return queue.size();
- }
-
- void push(vertex_info *v) {
-#if defined(CARVE_DEBUG)
- checkheap();
-#endif
- queue.push_back(v);
- std::push_heap(queue.begin(), queue.end(), vertex_info_ordering());
- }
-
- vertex_info *pop() {
-#if defined(CARVE_DEBUG)
- checkheap();
-#endif
- std::pop_heap(queue.begin(), queue.end(), vertex_info_ordering());
- vertex_info *v = queue.back();
- queue.pop_back();
- return v;
- }
-
- void remove(vertex_info *v) {
-#if defined(CARVE_DEBUG)
- checkheap();
-#endif
- CARVE_ASSERT(std::find(queue.begin(), queue.end(), v) != queue.end());
- double score = v->score;
- if (v != queue[0]) {
- v->score = queue[0]->score + 1;
- std::make_heap(queue.begin(), queue.end(), vertex_info_ordering());
- }
- CARVE_ASSERT(v == queue[0]);
- std::pop_heap(queue.begin(), queue.end(), vertex_info_ordering());
- CARVE_ASSERT(queue.back() == v);
- queue.pop_back();
- v->score = score;
- }
-
- void changeScore(vertex_info *v, double score) {
-#if defined(CARVE_DEBUG)
- checkheap();
-#endif
- CARVE_ASSERT(std::find(queue.begin(), queue.end(), v) != queue.end());
- if (v->score != score) {
- v->score = score;
- std::make_heap(queue.begin(), queue.end(), vertex_info_ordering());
- }
- }
-
- // 39% of execution time
- void updateVertex(vertex_info *v) {
- double spre = v->score;
- bool qpre = v->isCandidate();
- v->recompute();
- bool qpost = v->isCandidate();
- double spost = v->score;
-
- v->score = spre;
-
- if (qpre) {
- if (qpost) {
- if (v->score != spre) {
- changeScore(v, spost);
- }
- } else {
- remove(v);
- }
- } else {
- if (qpost) {
- push(v);
- }
- }
- }
- };
-
-
-
- int windingNumber(vertex_info *begin, const carve::geom2d::P2 &point) {
- int wn = 0;
-
- vertex_info *v = begin;
- do {
- if (v->p.y <= point.y) {
- if (v->next->p.y > point.y && carve::geom2d::orient2d(v->p, v->next->p, point) > 0.0) {
- ++wn;
- }
- } else {
- if (v->next->p.y <= point.y && carve::geom2d::orient2d(v->p, v->next->p, point) < 0.0) {
- --wn;
- }
- }
- v = v->next;
- } while (v != begin);
-
- return wn;
- }
-
-
-
- bool internalToAngle(const vertex_info *a,
- const vertex_info *b,
- const vertex_info *c,
- const carve::geom2d::P2 &p) {
- return carve::geom2d::internalToAngle(a->p, b->p, c->p, p);
- }
-
-
-
- bool findDiagonal(vertex_info *begin, vertex_info *&v1, vertex_info *&v2) {
- vertex_info *t;
- std::vector<vertex_info *> heap;
-
- v1 = begin;
- do {
- heap.clear();
-
- for (v2 = v1->next->next; v2 != v1->prev; v2 = v2->next) {
- if (!internalToAngle(v1->next, v1, v1->prev, v2->p) ||
- !internalToAngle(v2->next, v2, v2->prev, v1->p)) continue;
-
- heap.push_back(v2);
- std::push_heap(heap.begin(), heap.end(), vertex_info_l2norm_inc_ordering(v1));
- }
-
- while (heap.size()) {
- std::pop_heap(heap.begin(), heap.end(), vertex_info_l2norm_inc_ordering(v1));
- v2 = heap.back(); heap.pop_back();
-
-#if defined(CARVE_DEBUG)
- std::cerr << "testing: " << v1 << " - " << v2 << std::endl;
- std::cerr << " length = " << (v2->p - v1->p).length() << std::endl;
- std::cerr << " pos: " << v1->p << " - " << v2->p << std::endl;
-#endif
- // test whether v1-v2 is a valid diagonal.
- double v_min_x = std::min(v1->p.x, v2->p.x);
- double v_max_x = std::max(v1->p.x, v2->p.x);
-
- bool intersected = false;
-
- for (t = v1->next; !intersected && t != v1->prev; t = t->next) {
- vertex_info *u = t->next;
- if (t == v2 || u == v2) continue;
-
- double l1 = carve::geom2d::orient2d(v1->p, v2->p, t->p);
- double l2 = carve::geom2d::orient2d(v1->p, v2->p, u->p);
-
- if ((l1 > 0.0 && l2 > 0.0) || (l1 < 0.0 && l2 < 0.0)) {
- // both on the same side; no intersection
- continue;
- }
-
- double dx13 = v1->p.x - t->p.x;
- double dy13 = v1->p.y - t->p.y;
- double dx43 = u->p.x - t->p.x;
- double dy43 = u->p.y - t->p.y;
- double dx21 = v2->p.x - v1->p.x;
- double dy21 = v2->p.y - v1->p.y;
- double ua_n = dx43 * dy13 - dy43 * dx13;
- double ub_n = dx21 * dy13 - dy21 * dx13;
- double u_d = dy43 * dx21 - dx43 * dy21;
-
- if (carve::math::ZERO(u_d)) {
- // parallel
- if (carve::math::ZERO(ua_n)) {
- // colinear
- if (std::max(t->p.x, u->p.x) >= v_min_x && std::min(t->p.x, u->p.x) <= v_max_x) {
- // colinear and intersecting
- intersected = true;
- }
- }
- } else {
- // not parallel
- double ua = ua_n / u_d;
- double ub = ub_n / u_d;
-
- if (0.0 <= ua && ua <= 1.0 && 0.0 <= ub && ub <= 1.0) {
- intersected = true;
- }
- }
-#if defined(CARVE_DEBUG)
- if (intersected) {
- std::cerr << " failed on edge: " << t << " - " << u << std::endl;
- std::cerr << " pos: " << t->p << " - " << u->p << std::endl;
- }
-#endif
- }
-
- if (!intersected) {
- // test whether midpoint winding == 1
-
- carve::geom2d::P2 mid = (v1->p + v2->p) / 2;
- if (windingNumber(begin, mid) == 1) {
- // this diagonal is ok
- return true;
- }
- }
- }
-
- // couldn't find a diagonal from v1 that was ok.
- v1 = v1->next;
- } while (v1 != begin);
- return false;
- }
-
-
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- void dumpPoly(const std::vector<carve::geom2d::P2> &points,
- const std::vector<carve::triangulate::tri_idx> &result) {
- static int step = 0;
- std::ostringstream filename;
- filename << "poly_" << step++ << ".svg";
- std::cerr << "dumping to " << filename.str() << std::endl;
- std::ofstream out(filename.str().c_str());
-
- double minx = points[0].x, maxx = points[0].x;
- double miny = points[0].y, maxy = points[0].y;
-
- for (size_t i = 1; i < points.size(); ++i) {
- minx = std::min(points[i].x, minx); maxx = std::max(points[i].x, maxx);
- miny = std::min(points[i].y, miny); maxy = std::max(points[i].y, maxy);
- }
- double scale = 100 / std::max(maxx-minx, maxy-miny);
-
- maxx *= scale; minx *= scale;
- maxy *= scale; miny *= scale;
-
- double width = maxx - minx + 10;
- double height = maxy - miny + 10;
-
- out << "\
-<?xml version=\"1.0\"?>\n\
-<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n\
-<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"" << width << "\" height=\"" << height << "\">\n";
-
- out << "<polygon fill=\"rgb(0,0,0)\" stroke=\"blue\" stroke-width=\"0.1\" points=\"";
- for (size_t i = 0; i < points.size(); ++i) {
- if (i) out << ' ';
- double x, y;
- x = scale * (points[i].x) - minx + 5;
- y = scale * (points[i].y) - miny + 5;
- out << x << ',' << y;
- }
- out << "\" />" << std::endl;
-
- for (size_t i = 0; i < result.size(); ++i) {
- out << "<polygon fill=\"rgb(255,255,255)\" stroke=\"black\" stroke-width=\"0.1\" points=\"";
- double x, y;
- x = scale * (points[result[i].a].x) - minx + 5;
- y = scale * (points[result[i].a].y) - miny + 5;
- out << x << ',' << y << ' ';
- x = scale * (points[result[i].b].x) - minx + 5;
- y = scale * (points[result[i].b].y) - miny + 5;
- out << x << ',' << y << ' ';
- x = scale * (points[result[i].c].x) - minx + 5;
- y = scale * (points[result[i].c].y) - miny + 5;
- out << x << ',' << y;
- out << "\" />" << std::endl;
- }
-
- out << "</svg>" << std::endl;
- }
-#endif
-}
-
-
-
-double carve::triangulate::detail::vertex_info::triScore(const vertex_info *p, const vertex_info *v, const vertex_info *n) {
-
- // different scoring functions.
-#if 0
- bool convex = isLeft(p, v, n);
- if (!convex) return -1e-5;
-
- double a1 = carve::geom2d::atan2(p->p - v->p) - carve::geom2d::atan2(n->p - v->p);
- double a2 = carve::geom2d::atan2(v->p - n->p) - carve::geom2d::atan2(p->p - n->p);
- if (a1 < 0) a1 += M_PI * 2;
- if (a2 < 0) a2 += M_PI * 2;
-
- return std::min(a1, std::min(a2, M_PI - a1 - a2)) / (M_PI / 3);
-#endif
-
-#if 1
- // range: 0 - 1
- double a, b, c;
-
- bool convex = isLeft(p, v, n);
- if (!convex) return -1e-5;
-
- a = (n->p - v->p).length();
- b = (p->p - n->p).length();
- c = (v->p - p->p).length();
-
- if (a < 1e-10 || b < 1e-10 || c < 1e-10) return 0.0;
-
- return std::max(std::min((a+b)/c, std::min((a+c)/b, (b+c)/a)) - 1.0, 0.0);
-#endif
-}
-
-
-
-double carve::triangulate::detail::vertex_info::calcScore() const {
-
-#if 0
- // examine only this triangle.
- double this_tri = triScore(prev, this, next);
- return this_tri;
-#endif
-
-#if 1
- // attempt to look ahead in the neighbourhood to attempt to clip ears that have good neighbours.
- double this_tri = triScore(prev, this, next);
- double next_tri = triScore(prev, next, next->next);
- double prev_tri = triScore(prev->prev, prev, next);
-
- return this_tri + std::max(next_tri, prev_tri) * .2;
-#endif
-
-#if 0
- // attempt to penalise ears that will require producing a sliver triangle.
- double score = triScore(prev, this, next);
-
- double a1, a2;
- a1 = carve::geom2d::atan2(prev->p - next->p);
- a2 = carve::geom2d::atan2(next->next->p - next->p);
- if (fabs(a1 - a2) < 1e-5) score -= .5;
-
- a1 = carve::geom2d::atan2(next->p - prev->p);
- a2 = carve::geom2d::atan2(prev->prev->p - prev->p);
- if (fabs(a1 - a2) < 1e-5) score -= .5;
-
- return score;
-#endif
-}
-
-
-
-bool carve::triangulate::detail::vertex_info::isClipable() const {
- for (const vertex_info *v_test = next->next; v_test != prev; v_test = v_test->next) {
- if (v_test->convex) {
- continue;
- }
-
- if (v_test->p == prev->p ||
- v_test->p == next->p) {
- continue;
- }
-
- if (v_test->p == p) {
- if (v_test->next->p == prev->p &&
- v_test->prev->p == next->p) {
- return false;
- }
- if (v_test->next->p == prev->p ||
- v_test->prev->p == next->p) {
- continue;
- }
- }
-
- if (pointInTriangle(prev, this, next, v_test)) {
- return false;
- }
- }
- return true;
-}
-
-
-
-size_t carve::triangulate::detail::removeDegeneracies(vertex_info *&begin, std::vector<carve::triangulate::tri_idx> &result) {
- vertex_info *v;
- vertex_info *n;
- size_t count = 0;
- size_t remain = 0;
-
- v = begin;
- do {
- v = v->next;
- ++remain;
- } while (v != begin);
-
- v = begin;
- do {
- if (remain < 4) break;
-
- bool remove = false;
- if (v->p == v->next->p) {
- remove = true;
- } else if (v->p == v->next->next->p) {
- if (v->next->p == v->next->next->next->p) {
- // a 'z' in the loop: z (a) b a b c -> remove a-b-a -> z (a) a b c -> remove a-a-b (next loop) -> z a b c
- // z --(a)-- b
- // /
- // /
- // a -- b -- d
- remove = true;
- } else {
- // a 'shard' in the loop: z (a) b a c d -> remove a-b-a -> z (a) a b c d -> remove a-a-b (next loop) -> z a b c d
- // z --(a)-- b
- // /
- // /
- // a -- c -- d
- // n.b. can only do this if the shard is pointing out of the polygon. i.e. b is outside z-a-c
- remove = !internalToAngle(v->next->next->next, v, v->prev, v->next->p);
- }
- }
-
- if (remove) {
- result.push_back(carve::triangulate::tri_idx(v->idx, v->next->idx, v->next->next->idx));
- n = v->next;
- if (n == begin) begin = n->next;
- n->remove();
- count++;
- remain--;
- delete n;
- } else {
- v = v->next;
- }
- } while (v != begin);
- return count;
-}
-
-
-
-bool carve::triangulate::detail::splitAndResume(vertex_info *begin, std::vector<carve::triangulate::tri_idx> &result) {
- vertex_info *v1, *v2;
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- {
- std::vector<carve::triangulate::tri_idx> dummy;
- std::vector<carve::geom2d::P2> dummy_p;
- vertex_info *v = begin;
- do {
- dummy_p.push_back(v->p);
- v = v->next;
- } while (v != begin);
- std::cerr << "input to splitAndResume:" << std::endl;
- dumpPoly(dummy_p, dummy);
- }
-#endif
-
-
- if (!findDiagonal(begin, v1, v2)) return false;
-
- vertex_info *v1_copy = new vertex_info(*v1);
- vertex_info *v2_copy = new vertex_info(*v2);
-
- v1->next = v2;
- v2->prev = v1;
-
- v1_copy->next->prev = v1_copy;
- v2_copy->prev->next = v2_copy;
-
- v1_copy->prev = v2_copy;
- v2_copy->next = v1_copy;
-
- bool r1 = doTriangulate(v1, result);
- bool r2 = doTriangulate(v1_copy, result);
- return r1 && r2;
-}
-
-
-
-bool carve::triangulate::detail::doTriangulate(vertex_info *begin, std::vector<carve::triangulate::tri_idx> &result) {
-#if defined(CARVE_DEBUG)
- std::cerr << "entering doTriangulate" << std::endl;
-#endif
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- {
- std::vector<carve::triangulate::tri_idx> dummy;
- std::vector<carve::geom2d::P2> dummy_p;
- vertex_info *v = begin;
- do {
- dummy_p.push_back(v->p);
- v = v->next;
- } while (v != begin);
- dumpPoly(dummy_p, dummy);
- }
-#endif
-
- EarQueue vq;
-
- vertex_info *v = begin;
- size_t remain = 0;
- do {
- if (v->isCandidate()) vq.push(v);
- v = v->next;
- remain++;
- } while (v != begin);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "remain = " << remain << std::endl;
-#endif
-
- while (remain > 3 && vq.size()) {
- vertex_info *v = vq.pop();
- if (!v->isClipable()) {
- v->failed = true;
- continue;
- }
-
- continue_clipping:
- vertex_info *n = v->next;
- vertex_info *p = v->prev;
-
- result.push_back(carve::triangulate::tri_idx(v->prev->idx, v->idx, v->next->idx));
-
-#if defined(CARVE_DEBUG)
- {
- std::vector<carve::geom2d::P2> temp;
- temp.push_back(v->prev->p);
- temp.push_back(v->p);
- temp.push_back(v->next->p);
- std::cerr << "clip " << v << " idx = " << v->idx << " score = " << v->score << " area = " << carve::geom2d::signedArea(temp) << " " << temp[0] << " " << temp[1] << " " << temp[2] << std::endl;
- }
-#endif
-
- v->remove();
- if (v == begin) begin = v->next;
- delete v;
-
- if (--remain == 3) break;
-
- vq.updateVertex(n);
- vq.updateVertex(p);
-
- if (n->score < p->score) { std::swap(n, p); }
-
- if (n->score > 0.25 && n->isCandidate() && n->isClipable()) {
- vq.remove(n);
- v = n;
-#if defined(CARVE_DEBUG)
- std::cerr << " continue clipping (n), score = " << n->score << std::endl;
-#endif
- goto continue_clipping;
- }
-
- if (p->score > 0.25 && p->isCandidate() && p->isClipable()) {
- vq.remove(p);
- v = p;
-#if defined(CARVE_DEBUG)
- std::cerr << " continue clipping (p), score = " << n->score << std::endl;
-#endif
- goto continue_clipping;
- }
-
-#if defined(CARVE_DEBUG)
- std::cerr << "looking for new start point" << std::endl;
- std::cerr << "remain = " << remain << std::endl;
-#endif
- }
-
-#if defined(CARVE_DEBUG)
- std::cerr << "doTriangulate complete; remain=" << remain << std::endl;
-#endif
-
- if (remain > 3) {
-#if defined(CARVE_DEBUG)
- std::cerr << "before removeDegeneracies: remain=" << remain << std::endl;
-#endif
- remain -= removeDegeneracies(begin, result);
-#if defined(CARVE_DEBUG)
- std::cerr << "after removeDegeneracies: remain=" << remain << std::endl;
-#endif
-
- if (remain > 3) {
- return splitAndResume(begin, result);
- }
- }
-
- if (remain == 3) {
- result.push_back(carve::triangulate::tri_idx(begin->idx, begin->next->idx, begin->next->next->idx));
- }
-
- vertex_info *d = begin;
- do {
- vertex_info *n = d->next;
- delete d;
- d = n;
- } while (d != begin);
-
- return true;
-}
-
-
-
-static bool testCandidateAttachment(const std::vector<std::vector<carve::geom2d::P2> > &poly,
- std::vector<std::pair<size_t, size_t> > &current_f_loop,
- size_t curr,
- carve::geom2d::P2 hole_min) {
- const size_t SZ = current_f_loop.size();
-
- if (!carve::geom2d::internalToAngle(pvert(poly, current_f_loop[(curr+1) % SZ]),
- pvert(poly, current_f_loop[curr]),
- pvert(poly, current_f_loop[(curr+SZ-1) % SZ]),
- hole_min)) {
- return false;
- }
-
- if (hole_min == pvert(poly, current_f_loop[curr])) {
- return true;
- }
-
- carve::geom2d::LineSegment2 test(hole_min, pvert(poly, current_f_loop[curr]));
-
- size_t v1 = current_f_loop.size() - 1;
- size_t v2 = 0;
- double v1_side = carve::geom2d::orient2d(test.v1, test.v2, pvert(poly, current_f_loop[v1]));
- double v2_side = 0;
-
- while (v2 != current_f_loop.size()) {
- v2_side = carve::geom2d::orient2d(test.v1, test.v2, pvert(poly, current_f_loop[v2]));
-
- if (v1_side != v2_side) {
- // XXX: need to test vertices, not indices, because they may
- // be duplicated.
- if (pvert(poly, current_f_loop[v1]) != pvert(poly, current_f_loop[curr]) &&
- pvert(poly, current_f_loop[v2]) != pvert(poly, current_f_loop[curr])) {
- carve::geom2d::LineSegment2 test2(pvert(poly, current_f_loop[v1]), pvert(poly, current_f_loop[v2]));
- if (carve::geom2d::lineSegmentIntersection_simple(test, test2)) {
- // intersection; failed.
- return false;
- }
- }
- }
-
- v1 = v2;
- v1_side = v2_side;
- ++v2;
- }
- return true;
-}
-
-
-
-void
-carve::triangulate::incorporateHolesIntoPolygon(
- const std::vector<std::vector<carve::geom2d::P2> > &poly,
- std::vector<std::pair<size_t, size_t> > &result,
- size_t poly_loop,
- const std::vector<size_t> &hole_loops) {
- typedef std::vector<carve::geom2d::P2> loop_t;
-
- size_t N = poly[poly_loop].size();
-
- // work out how much space to reserve for the patched in holes.
- for (size_t i = 0; i < hole_loops.size(); i++) {
- N += 2 + poly[hole_loops[i]].size();
- }
-
- // this is the vector that we will build the result in.
- result.clear();
- result.reserve(N);
-
- // this is a heap of result indices that defines the vertex test order.
- std::vector<size_t> f_loop_heap;
- f_loop_heap.reserve(N);
-
- // add the poly loop to result.
- for (size_t i = 0; i < poly[poly_loop].size(); ++i) {
- result.push_back(std::make_pair((size_t)poly_loop, i));
- }
-
- if (hole_loops.size() == 0) {
- return;
- }
-
- std::vector<std::pair<size_t, size_t> > h_loop_min_vertex;
-
- h_loop_min_vertex.reserve(hole_loops.size());
-
- // find the major axis for the holes - this is the axis that we
- // will sort on for finding vertices on the polygon to join
- // holes up to.
- //
- // it might also be nice to also look for whether it is better
- // to sort ascending or descending.
- //
- // another trick that could be used is to modify the projection
- // by 90 degree rotations or flipping about an axis. just as
- // long as we keep the carve::geom3d::Vector pointers for the
- // real data in sync, everything should be ok. then we wouldn't
- // need to accomodate axes or sort order in the main loop.
-
- // find the bounding box of all the holes.
- carve::geom2d::P2 h_min, h_max;
- h_min = h_max = poly[hole_loops[0]][0];
- for (size_t i = 0; i < hole_loops.size(); ++i) {
- const loop_t &hole = poly[hole_loops[i]];
- for (size_t j = 0; j < hole.size(); ++j) {
- assign_op(h_min, h_min, hole[j], carve::util::min_functor());
- assign_op(h_max, h_max, hole[j], carve::util::max_functor());
- }
- }
- // choose the axis for which the bbox is largest.
- int axis = (h_max.x - h_min.x) > (h_max.y - h_min.y) ? 0 : 1;
-
- // for each hole, find the minimum vertex in the chosen axis.
- for (size_t i = 0; i < hole_loops.size(); ++i) {
- const loop_t &hole = poly[hole_loops[i]];
- size_t best, curr;
- best = 0;
- for (curr = 1; curr != hole.size(); ++curr) {
- if (detail::axisOrdering(hole[curr], hole[best], axis)) {
- best = curr;
- }
- }
- h_loop_min_vertex.push_back(std::make_pair(hole_loops[i], best));
- }
-
- // sort the holes by the minimum vertex.
- std::sort(h_loop_min_vertex.begin(), h_loop_min_vertex.end(), order_h_loops_2d(poly, axis));
-
- // now, for each hole, find a vertex in the current polygon loop that it can be joined to.
- for (unsigned i = 0; i < h_loop_min_vertex.size(); ++i) {
- // the index of the vertex in the hole to connect.
- size_t hole_i = h_loop_min_vertex[i].first;
- size_t hole_i_connect = h_loop_min_vertex[i].second;
-
- carve::geom2d::P2 hole_min = poly[hole_i][hole_i_connect];
-
- f_loop_heap.clear();
- // we order polygon loop vertices that may be able to be connected
- // to the hole vertex by their distance to the hole vertex
- heap_ordering_2d _heap_ordering(poly, result, hole_min, axis);
-
- const size_t SZ = result.size();
- for (size_t j = 0; j < SZ; ++j) {
- // it is guaranteed that there exists a polygon vertex with
- // coord < the min hole coord chosen, which can be joined to
- // the min hole coord without crossing the polygon
- // boundary. also, because we merge holes in ascending
- // order, it is also true that this join can never cross
- // another hole (and that doesn't need to be tested for).
- if (pvert(poly, result[j]).v[axis] <= hole_min.v[axis]) {
- f_loop_heap.push_back(j);
- std::push_heap(f_loop_heap.begin(), f_loop_heap.end(), _heap_ordering);
- }
- }
-
- // we are going to test each potential (according to the
- // previous test) polygon vertex as a candidate join. we order
- // by closeness to the hole vertex, so that the join we make
- // is as small as possible. to test, we need to check the
- // joining line segment does not cross any other line segment
- // in the current polygon loop (excluding those that have the
- // vertex that we are attempting to join with as an endpoint).
- size_t attachment_point = result.size();
-
- while (f_loop_heap.size()) {
- std::pop_heap(f_loop_heap.begin(), f_loop_heap.end(), _heap_ordering);
- size_t curr = f_loop_heap.back();
- f_loop_heap.pop_back();
- // test the candidate join from result[curr] to hole_min
-
- if (!testCandidateAttachment(poly, result, curr, hole_min)) {
- continue;
- }
-
- attachment_point = curr;
- break;
- }
-
- if (attachment_point == result.size()) {
- CARVE_FAIL("didn't manage to link up hole!");
- }
-
- patchHoleIntoPolygon_2d(result, attachment_point, hole_i, hole_i_connect, poly[hole_i].size());
- }
-}
-
-
-
-std::vector<std::pair<size_t, size_t> >
-carve::triangulate::incorporateHolesIntoPolygon(const std::vector<std::vector<carve::geom2d::P2> > &poly) {
-#if 1
- std::vector<std::pair<size_t, size_t> > result;
- std::vector<size_t> hole_indices;
- hole_indices.reserve(poly.size() - 1);
- for (size_t i = 1; i < poly.size(); ++i) {
- hole_indices.push_back(i);
- }
-
- incorporateHolesIntoPolygon(poly, result, 0, hole_indices);
-
- return result;
-
-#else
- typedef std::vector<carve::geom2d::P2> loop_t;
- size_t N = poly[0].size();
- //
- // work out how much space to reserve for the patched in holes.
- for (size_t i = 0; i < poly.size(); i++) {
- N += 2 + poly[i].size();
- }
-
- // this is the vector that we will build the result in.
- std::vector<std::pair<size_t, size_t> > current_f_loop;
- current_f_loop.reserve(N);
-
- // this is a heap of current_f_loop indices that defines the vertex test order.
- std::vector<size_t> f_loop_heap;
- f_loop_heap.reserve(N);
-
- // add the poly loop to current_f_loop.
- for (size_t i = 0; i < poly[0].size(); ++i) {
- current_f_loop.push_back(std::make_pair((size_t)0, i));
- }
-
- if (poly.size() == 1) {
- return current_f_loop;
- }
-
- std::vector<std::pair<size_t, size_t> > h_loop_min_vertex;
-
- h_loop_min_vertex.reserve(poly.size() - 1);
-
- // find the major axis for the holes - this is the axis that we
- // will sort on for finding vertices on the polygon to join
- // holes up to.
- //
- // it might also be nice to also look for whether it is better
- // to sort ascending or descending.
- //
- // another trick that could be used is to modify the projection
- // by 90 degree rotations or flipping about an axis. just as
- // long as we keep the carve::geom3d::Vector pointers for the
- // real data in sync, everything should be ok. then we wouldn't
- // need to accomodate axes or sort order in the main loop.
-
- // find the bounding box of all the holes.
- double min_x, min_y, max_x, max_y;
- min_x = max_x = poly[1][0].x;
- min_y = max_y = poly[1][0].y;
- for (size_t i = 1; i < poly.size(); ++i) {
- const loop_t &hole = poly[i];
- for (size_t j = 0; j < hole.size(); ++j) {
- min_x = std::min(min_x, hole[j].x);
- min_y = std::min(min_y, hole[j].y);
- max_x = std::max(max_x, hole[j].x);
- max_y = std::max(max_y, hole[j].y);
- }
- }
-
- // choose the axis for which the bbox is largest.
- int axis = (max_x - min_x) > (max_y - min_y) ? 0 : 1;
-
- // for each hole, find the minimum vertex in the chosen axis.
- for (size_t i = 1; i < poly.size(); ++i) {
- const loop_t &hole = poly[i];
- size_t best, curr;
- best = 0;
- for (curr = 1; curr != hole.size(); ++curr) {
- if (detail::axisOrdering(hole[curr], hole[best], axis)) {
- best = curr;
- }
- }
- h_loop_min_vertex.push_back(std::make_pair(i, best));
- }
-
- // sort the holes by the minimum vertex.
- std::sort(h_loop_min_vertex.begin(), h_loop_min_vertex.end(), order_h_loops_2d(poly, axis));
-
- // now, for each hole, find a vertex in the current polygon loop that it can be joined to.
- for (unsigned i = 0; i < h_loop_min_vertex.size(); ++i) {
- // the index of the vertex in the hole to connect.
- size_t hole_i = h_loop_min_vertex[i].first;
- size_t hole_i_connect = h_loop_min_vertex[i].second;
-
- carve::geom2d::P2 hole_min = poly[hole_i][hole_i_connect];
-
- f_loop_heap.clear();
- // we order polygon loop vertices that may be able to be connected
- // to the hole vertex by their distance to the hole vertex
- heap_ordering_2d _heap_ordering(poly, current_f_loop, hole_min, axis);
-
- const size_t SZ = current_f_loop.size();
- for (size_t j = 0; j < SZ; ++j) {
- // it is guaranteed that there exists a polygon vertex with
- // coord < the min hole coord chosen, which can be joined to
- // the min hole coord without crossing the polygon
- // boundary. also, because we merge holes in ascending
- // order, it is also true that this join can never cross
- // another hole (and that doesn't need to be tested for).
- if (pvert(poly, current_f_loop[j]).v[axis] <= hole_min.v[axis]) {
- f_loop_heap.push_back(j);
- std::push_heap(f_loop_heap.begin(), f_loop_heap.end(), _heap_ordering);
- }
- }
-
- // we are going to test each potential (according to the
- // previous test) polygon vertex as a candidate join. we order
- // by closeness to the hole vertex, so that the join we make
- // is as small as possible. to test, we need to check the
- // joining line segment does not cross any other line segment
- // in the current polygon loop (excluding those that have the
- // vertex that we are attempting to join with as an endpoint).
- size_t attachment_point = current_f_loop.size();
-
- while (f_loop_heap.size()) {
- std::pop_heap(f_loop_heap.begin(), f_loop_heap.end(), _heap_ordering);
- size_t curr = f_loop_heap.back();
- f_loop_heap.pop_back();
- // test the candidate join from current_f_loop[curr] to hole_min
-
- if (!testCandidateAttachment(poly, current_f_loop, curr, hole_min)) {
- continue;
- }
-
- attachment_point = curr;
- break;
- }
-
- if (attachment_point == current_f_loop.size()) {
- CARVE_FAIL("didn't manage to link up hole!");
- }
-
- patchHoleIntoPolygon_2d(current_f_loop, attachment_point, hole_i, hole_i_connect, poly[hole_i].size());
- }
-
- return current_f_loop;
-#endif
-}
-
-
-
-std::vector<std::vector<std::pair<size_t, size_t> > >
-carve::triangulate::mergePolygonsAndHoles(const std::vector<std::vector<carve::geom2d::P2> > &poly) {
- std::vector<size_t> poly_indices, hole_indices;
-
- poly_indices.reserve(poly.size());
- hole_indices.reserve(poly.size());
-
- for (size_t i = 0; i < poly.size(); ++i) {
- if (carve::geom2d::signedArea(poly[i]) < 0) {
- poly_indices.push_back(i);
- } else {
- hole_indices.push_back(i);
- }
- }
-
- std::vector<std::vector<std::pair<size_t, size_t> > > result;
- result.resize(poly_indices.size());
-
- if (hole_indices.size() == 0) {
- for (size_t i = 0; i < poly.size(); ++i) {
- result[i].resize(poly[i].size());
- for (size_t j = 0; j < poly[i].size(); ++j) {
- result[i].push_back(std::make_pair(i, j));
- }
- }
- return result;
- }
-
- if (poly_indices.size() == 1) {
- incorporateHolesIntoPolygon(poly, result[0], poly_indices[0], hole_indices);
-
- return result;
- }
-
- throw carve::exception("not implemented");
-}
-
-
-
-void carve::triangulate::triangulate(const std::vector<carve::geom2d::P2> &poly,
- std::vector<carve::triangulate::tri_idx> &result) {
- std::vector<detail::vertex_info *> vinfo;
- const size_t N = poly.size();
-
-#if defined(CARVE_DEBUG)
- std::cerr << "TRIANGULATION BEGINS" << std::endl;
-#endif
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- dumpPoly(poly, result);
-#endif
-
- result.clear();
- if (N < 3) {
- return;
- }
-
- result.reserve(poly.size() - 2);
-
- if (N == 3) {
- result.push_back(tri_idx(0, 1, 2));
- return;
- }
-
- vinfo.resize(N);
-
- vinfo[0] = new detail::vertex_info(poly[0], 0);
- for (size_t i = 1; i < N-1; ++i) {
- vinfo[i] = new detail::vertex_info(poly[i], i);
- vinfo[i]->prev = vinfo[i-1];
- vinfo[i-1]->next = vinfo[i];
- }
- vinfo[N-1] = new detail::vertex_info(poly[N-1], N-1);
- vinfo[N-1]->prev = vinfo[N-2];
- vinfo[N-1]->next = vinfo[0];
- vinfo[0]->prev = vinfo[N-1];
- vinfo[N-2]->next = vinfo[N-1];
-
- for (size_t i = 0; i < N; ++i) {
- vinfo[i]->recompute();
- }
-
- detail::vertex_info *begin = vinfo[0];
-
- removeDegeneracies(begin, result);
- doTriangulate(begin, result);
-
-#if defined(CARVE_DEBUG)
- std::cerr << "TRIANGULATION ENDS" << std::endl;
-#endif
-
-#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
- dumpPoly(poly, result);
-#endif
-}
-
-
-
-void carve::triangulate::detail::tri_pair_t::flip(vert_edge_t &old_edge,
- vert_edge_t &new_edge,
- vert_edge_t perim[4]) {
- unsigned ai, bi;
- unsigned cross_ai, cross_bi;
-
- findSharedEdge(ai, bi);
- old_edge = ordered_vert_edge_t(a->v[ai], b->v[bi]);
-
- cross_ai = P(ai);
- cross_bi = P(bi);
- new_edge = ordered_vert_edge_t(a->v[cross_ai], b->v[cross_bi]);
-
- score = -score;
-
- a->v[N(ai)] = b->v[cross_bi];
- b->v[N(bi)] = a->v[cross_ai];
-
- perim[0] = ordered_vert_edge_t(a->v[P(ai)], a->v[ai]);
- perim[1] = ordered_vert_edge_t(a->v[N(ai)], a->v[ai]); // this edge was a b-edge
-
- perim[2] = ordered_vert_edge_t(b->v[P(bi)], b->v[bi]);
- perim[3] = ordered_vert_edge_t(b->v[N(bi)], b->v[bi]); // this edge was an a-edge
-}
-
-
-
-void carve::triangulate::detail::tri_pairs_t::insert(unsigned a, unsigned b, carve::triangulate::tri_idx *t) {
- tri_pair_t *tp;
- if (a < b) {
- tp = storage[vert_edge_t(a,b)];
- if (!tp) {
- tp = storage[vert_edge_t(a,b)] = new tri_pair_t;
- }
- tp->a = t;
- } else {
- tp = storage[vert_edge_t(b,a)];
- if (!tp) {
- tp = storage[vert_edge_t(b,a)] = new tri_pair_t;
- }
- tp->b = t;
- }
-}
diff --git a/extern/carve/mkfiles.sh b/extern/carve/mkfiles.sh
deleted file mode 100755
index bd022666418..00000000000
--- a/extern/carve/mkfiles.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-
-find ./include/ -type f | sed -r 's/^\.\///' | grep -v /config.h > files.txt
-find ./lib/ -type f | sed -r 's/^\.\///' >> files.txt
diff --git a/extern/carve/patches/clang_is_heap_fix.patch b/extern/carve/patches/clang_is_heap_fix.patch
deleted file mode 100644
index 524a8e0420c..00000000000
--- a/extern/carve/patches/clang_is_heap_fix.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-diff -r e82d852e4fb0 include/carve/mesh_ops.hpp
---- a/include/carve/mesh_ops.hpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/include/carve/mesh_ops.hpp Fri Mar 28 14:34:04 2014 +0600
-@@ -580,7 +580,7 @@
- std::vector<VertexInfo *> queue;
-
- void checkheap() {
--#ifdef __GNUC__
-+#if defined(HAVE_IS_HEAP)
- CARVE_ASSERT(std::__is_heap(queue.begin(), queue.end(), order_by_score()));
- #endif
- }
-diff -r e82d852e4fb0 lib/triangulator.cpp
---- a/lib/triangulator.cpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/lib/triangulator.cpp Fri Mar 28 14:34:04 2014 +0600
-@@ -27,7 +27,6 @@
-
- #include <algorithm>
-
--
- namespace {
- // private code related to hole patching.
-
-@@ -122,7 +121,7 @@
- std::vector<vertex_info *> queue;
-
- void checkheap() {
--#ifdef __GNUC__
-+#if defined(HAVE_IS_HEAP)
- CARVE_ASSERT(std::__is_heap(queue.begin(), queue.end(), vertex_info_ordering()));
- #endif
- }
diff --git a/extern/carve/patches/face_hole_merge_workaround.patch b/extern/carve/patches/face_hole_merge_workaround.patch
deleted file mode 100644
index 834e03a4b12..00000000000
--- a/extern/carve/patches/face_hole_merge_workaround.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-diff -r e82d852e4fb0 lib/intersect_face_division.cpp
---- a/lib/intersect_face_division.cpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/lib/intersect_face_division.cpp Thu Mar 13 15:39:26 2014 +0600
-@@ -719,6 +719,10 @@
- unassigned--;
- }
- }
-+
-+ if (!removed.size())
-+ throw carve::exception("Failed to merge holes");
-+
- for (std::set<int>::iterator f = removed.begin(); f != removed.end(); ++f) {
- for (unsigned i = 0; i < containing_faces.size(); ++i) {
- containing_faces[i].erase(std::remove(containing_faces[i].begin(),
diff --git a/extern/carve/patches/files/config.h b/extern/carve/patches/files/config.h
deleted file mode 100644
index 3533c1a6710..00000000000
--- a/extern/carve/patches/files/config.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#define CARVE_VERSION "2.0.0a"
-
-#undef CARVE_DEBUG
-#undef CARVE_DEBUG_WRITE_PLY_DATA
-
-#if defined(__GNUC__)
-# if !defined(HAVE_BOOST_UNORDERED_COLLECTIONS)
-# define HAVE_TR1_UNORDERED_COLLECTIONS
-# endif
-
-# define HAVE_STDINT_H
-#endif
-
-// Support for latest Clang/LLVM on FreeBSD which does have different libcxx.
-//
-// TODO(sergey): Move it some some more generic header with platform-specific
-// declarations.
-
-// Indicates whether __is_heap is available
-#undef HAVE_IS_HEAP
-
-#ifdef __GNUC__
-// NeyBSD doesn't have __is_heap
-# ifndef __NetBSD__
-# define HAVE_IS_HEAP
-# ifdef _LIBCPP_VERSION
-# define __is_heap is_heap
-# endif // _LIBCPP_VERSION
-# endif // !__NetBSD__
-#endif // __GNUC__
diff --git a/extern/carve/patches/files/random.h b/extern/carve/patches/files/random.h
deleted file mode 100644
index 634063cb90c..00000000000
--- a/extern/carve/patches/files/random.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <cassert>
-#include <cmath>
-#include <vector>
-
-namespace boost {
-#if __cplusplus > 199711L
-# include <random>
-typedef std::mt19937 mt19937;
-#else
-# include <stdlib.h>
-struct mt19937 {
- int operator()() {
- return rand();
- }
-
- int max() {
- return RAND_MAX;
- }
-};
-#endif
-
-template<typename T>
-struct uniform_on_sphere {
- typedef std::vector<T> result_type;
-
- uniform_on_sphere(int dimension) {
- assert(dimension == 3);
- }
-
- std::vector<T>
- operator()(float u1, float u2) {
- T z = 1.0 - 2.0*u1;
- T r = std::sqrt(std::max(0.0, 1.0 - z*z));
- T phi = 2.0*M_PI*u2;
- T x = r*std::cos(phi);
- T y = r*std::sin(phi);
- std::vector<T> result;
- result.push_back(x);
- result.push_back(y);
- result.push_back(z);
- return result;
- }
-};
-
-template<typename RNG, typename DISTR>
-struct variate_generator {
-
- variate_generator(RNG rng, DISTR distr)
- : rng_(rng), distr_(distr) {}
-
- typename DISTR::result_type
- operator()() {
- float rng_max_inv = 1.0 / rng_.max();
- return distr_(rng_() * rng_max_inv, rng_() * rng_max_inv);
- }
-
- RNG rng_;
- DISTR distr_;
-};
-
-}
diff --git a/extern/carve/patches/gcc46.patch b/extern/carve/patches/gcc46.patch
deleted file mode 100644
index a8384dcdab8..00000000000
--- a/extern/carve/patches/gcc46.patch
+++ /dev/null
@@ -1,11 +0,0 @@
-diff -r 525472fb477a include/carve/polyline_iter.hpp
---- a/include/carve/polyline_iter.hpp Sun Jan 15 23:07:40 2012 -0500
-+++ b/include/carve/polyline_iter.hpp Wed Jan 18 00:41:13 2012 +0600
-@@ -20,6 +20,7 @@
- #include <list>
- #include <iterator>
- #include <limits>
-+#include <cstddef>
-
- #include <carve/polyline_decl.hpp>
-
diff --git a/extern/carve/patches/includes.patch b/extern/carve/patches/includes.patch
deleted file mode 100644
index bdf97c846e7..00000000000
--- a/extern/carve/patches/includes.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-diff -r c8cbec41cd35 include/carve/exact.hpp
---- a/include/carve/exact.hpp Thu Dec 01 15:51:44 2011 -0500
-+++ b/include/carve/exact.hpp Wed Jan 11 18:48:16 2012 +0600
-@@ -21,7 +21,7 @@
-
- #include <vector>
- #include <numeric>
--
-+#include <algorithm>
-
-
- namespace carve {
-diff -r c8cbec41cd35 include/carve/geom2d.hpp
---- a/include/carve/geom2d.hpp Thu Dec 01 15:51:44 2011 -0500
-+++ b/include/carve/geom2d.hpp Wed Jan 11 18:48:16 2012 +0600
-@@ -25,6 +25,7 @@
- #include <carve/geom.hpp>
-
- #include <vector>
-+#include <algorithm>
-
- #include <math.h>
-
-diff -r c8cbec41cd35 include/carve/mesh_impl.hpp
---- a/include/carve/mesh_impl.hpp Thu Dec 01 15:51:44 2011 -0500
-+++ b/include/carve/mesh_impl.hpp Wed Jan 11 18:48:16 2012 +0600
-@@ -24,6 +24,8 @@
- #include <iostream>
- #include <deque>
-
-+#include <stddef.h>
-+
- namespace carve {
- namespace mesh {
-
-diff -r c8cbec41cd35 include/carve/polyhedron_base.hpp
---- a/include/carve/polyhedron_base.hpp Thu Dec 01 15:51:44 2011 -0500
-+++ b/include/carve/polyhedron_base.hpp Wed Jan 11 18:48:16 2012 +0600
-@@ -25,6 +25,8 @@
- #include <carve/edge_decl.hpp>
- #include <carve/face_decl.hpp>
-
-+#include <stddef.h>
-+
- namespace carve {
- namespace poly {
-
-diff -r c8cbec41cd35 include/carve/rtree.hpp
---- a/include/carve/rtree.hpp Thu Dec 01 15:51:44 2011 -0500
-+++ b/include/carve/rtree.hpp Wed Jan 11 18:48:16 2012 +0600
-@@ -27,6 +27,10 @@
- #include <cmath>
- #include <limits>
-
-+#if defined(HAVE_STDINT_H)
-+# include <stdint.h>
-+#endif
-+
- namespace carve {
- namespace geom {
-
-diff -r c8cbec41cd35 include/carve/vector.hpp
---- a/include/carve/vector.hpp Thu Dec 01 15:51:44 2011 -0500
-+++ b/include/carve/vector.hpp Wed Jan 11 18:48:16 2012 +0600
-@@ -24,6 +24,7 @@
- #include <carve/geom3d.hpp>
-
- #include <sstream>
-+#include <algorithm>
-
- #include <math.h>
-
-diff -r c8cbec41cd35 src/extrude.cpp
---- a/src/extrude.cpp Thu Dec 01 15:51:44 2011 -0500
-+++ b/src/extrude.cpp Wed Jan 11 18:48:16 2012 +0600
-@@ -34,6 +34,8 @@
- #include <cctype>
- #include <stdexcept>
-
-+#include <stdexcept>
-+
- template<unsigned ndim>
- carve::geom::vector<ndim> lerp(
- double t,
diff --git a/extern/carve/patches/interpolator_reorder.patch b/extern/carve/patches/interpolator_reorder.patch
deleted file mode 100644
index 867297fef7d..00000000000
--- a/extern/carve/patches/interpolator_reorder.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -r e82d852e4fb0 include/carve/interpolator.hpp
---- a/include/carve/interpolator.hpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/include/carve/interpolator.hpp Fri Jan 31 18:55:05 2014 +0600
-@@ -219,7 +219,7 @@
- interpolator->edgeDivision(csg, orig_edge, orig_edge_idx, v1, v2);
- }
-
-- Hook(Interpolator *_interpolator, const carve::csg::CSG &_csg) : interpolator(_interpolator), csg(_csg) {
-+ Hook(Interpolator *_interpolator, const carve::csg::CSG &_csg) : csg(_csg), interpolator(_interpolator) {
- }
-
- virtual ~Hook() {
diff --git a/extern/carve/patches/memory_leak_fix.patch b/extern/carve/patches/memory_leak_fix.patch
deleted file mode 100644
index c6aff1bf837..00000000000
--- a/extern/carve/patches/memory_leak_fix.patch
+++ /dev/null
@@ -1,11 +0,0 @@
-diff -r e82d852e4fb0 include/carve/csg_triangulator.hpp
---- a/include/carve/csg_triangulator.hpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/include/carve/csg_triangulator.hpp Wed Mar 05 14:43:56 2014 +0600
-@@ -426,6 +426,7 @@
- findPerimeter(grp_tris, vloop, grp_perim);
- out_faces.push_back(face->create(grp_perim.begin(), grp_perim.end(), false));
- }
-+ delete face;
- }
- std::swap(faces, out_faces);
- }
diff --git a/extern/carve/patches/mesh_iterator.patch b/extern/carve/patches/mesh_iterator.patch
deleted file mode 100644
index 1b9e12866bf..00000000000
--- a/extern/carve/patches/mesh_iterator.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-diff -r c8cbec41cd35 include/carve/mesh.hpp
---- a/include/carve/mesh.hpp Thu Dec 01 15:51:44 2011 -0500
-+++ b/include/carve/mesh.hpp Thu Jan 12 00:19:58 2012 +0600
-@@ -719,13 +719,13 @@
- void rev(size_t n);
- void adv(int n);
-
-- FaceIter operator++(int) { FaceIter tmp = *this; fwd(1); return tmp; }
-- FaceIter operator+(int v) { FaceIter tmp = *this; adv(v); return tmp; }
-+ FaceIter operator++(int) { FaceIter tmp = *this; tmp.fwd(1); return tmp; }
-+ FaceIter operator+(int v) { FaceIter tmp = *this; tmp.adv(v); return tmp; }
- FaceIter &operator++() { fwd(1); return *this; }
- FaceIter &operator+=(int v) { adv(v); return *this; }
-
-- FaceIter operator--(int) { FaceIter tmp = *this; rev(1); return tmp; }
-- FaceIter operator-(int v) { FaceIter tmp = *this; adv(-v); return tmp; }
-+ FaceIter operator--(int) { FaceIter tmp = *this; tmp.rev(1); return tmp; }
-+ FaceIter operator-(int v) { FaceIter tmp = *this; tmp.adv(-v); return tmp; }
- FaceIter &operator--() { rev(1); return *this; }
- FaceIter &operator-=(int v) { adv(-v); return *this; }
-
diff --git a/extern/carve/patches/mesh_simplify_dissolve_edges.patch b/extern/carve/patches/mesh_simplify_dissolve_edges.patch
deleted file mode 100644
index 27406a4912a..00000000000
--- a/extern/carve/patches/mesh_simplify_dissolve_edges.patch
+++ /dev/null
@@ -1,64 +0,0 @@
-diff -r e82d852e4fb0 include/carve/mesh_simplify.hpp
---- a/include/carve/mesh_simplify.hpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/include/carve/mesh_simplify.hpp Fri Feb 28 19:09:02 2014 +0600
-@@ -32,8 +32,6 @@
- #include <algorithm>
- #include <vector>
-
--#include "write_ply.hpp"
--
-
- namespace carve {
- namespace mesh {
-@@ -1184,6 +1182,33 @@
- return modifications;
- }
-
-+ void dissolveMeshEdges(mesh_t *mesh, std::unordered_set<edge_t *> dissolve_edges) {
-+ while (dissolve_edges.size()) {
-+ MeshSet<3>::edge_t *edge = *dissolve_edges.begin();
-+ if (edge->face == edge->rev->face) {
-+ dissolve_edges.erase(edge);
-+ continue;
-+ }
-+
-+ MeshSet<3>::edge_t *removed = edge->mergeFaces();
-+ if (removed == NULL) {
-+ dissolve_edges.erase(edge);
-+ } else {
-+ MeshSet<3>::edge_t *e = removed;
-+ do {
-+ MeshSet<3>::edge_t *n = e->next;
-+ dissolve_edges.erase(std::min(e, e->rev));
-+ delete e->rev;
-+ delete e;
-+ e = n;
-+ } while (e != removed);
-+ }
-+ }
-+
-+ removeRemnantFaces(mesh);
-+ cleanFaceEdges(mesh);
-+ mesh->cacheEdges();
-+ }
-
-
- size_t improveMesh(meshset_t *meshset,
-@@ -1445,7 +1470,7 @@
- heapval_t last;
- std::vector<heapval_t> heap;
-
-- point_enumerator_t(vector_t _origin, int _base, int _n_dp) : origin(_origin), rounding_fac(pow(_base, _n_dp)), last(-1.0, _origin), heap() {
-+ point_enumerator_t(vector_t _origin, int _base, int _n_dp) : origin(_origin), rounding_fac(pow((double)_base, _n_dp)), last(-1.0, _origin), heap() {
- for (size_t i = 0; i < (1 << 3); ++i) {
- vector_t t = origin;
- for (size_t j = 0; j < 3; ++j) {
-@@ -1502,7 +1527,7 @@
- }
-
- aabb_t getAABB() const {
-- std::set<face_t *>::iterator i = faces.begin();
-+ std::set<face_t *>::const_iterator i = faces.begin();
- aabb_t aabb = (*i)->getAABB();
- while (++i != faces.end()) {
- aabb.unionAABB((*i)->getAABB());
diff --git a/extern/carve/patches/mesh_simplify_uninitialized_var.patch b/extern/carve/patches/mesh_simplify_uninitialized_var.patch
deleted file mode 100644
index 592c6db0b68..00000000000
--- a/extern/carve/patches/mesh_simplify_uninitialized_var.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -r e82d852e4fb0 include/carve/mesh_simplify.hpp
---- a/include/carve/mesh_simplify.hpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/include/carve/mesh_simplify.hpp Wed Jun 11 13:13:09 2014 +0600
-@@ -1414,7 +1414,7 @@
-
-
- size_t removeLowVolumeManifolds(meshset_t *meshset, double min_abs_volume) {
-- size_t n_removed;
-+ size_t n_removed = 0;
- for (size_t i = 0; i < meshset->meshes.size(); ++i) {
- if (fabs(meshset->meshes[i]->volume()) < min_abs_volume) {
- delete meshset->meshes[i];
diff --git a/extern/carve/patches/msvc_fix.patch b/extern/carve/patches/msvc_fix.patch
deleted file mode 100644
index 67431ecac75..00000000000
--- a/extern/carve/patches/msvc_fix.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-diff -r e82d852e4fb0 lib/intersect_face_division.cpp
---- a/lib/intersect_face_division.cpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/lib/intersect_face_division.cpp Wed Mar 12 23:09:19 2014 +0600
-@@ -1121,7 +1121,9 @@
- }
-
- // copy up to the end of the path.
-- std::copy(base_loop.begin() + pos, base_loop.begin() + e1_1, std::back_inserter(out));
-+ if (pos < e1_1) {
-+ std::copy(base_loop.begin() + pos, base_loop.begin() + e1_1, std::back_inserter(out));
-+ }
-
- CARVE_ASSERT(base_loop[e1_1] == p1.back());
- std::copy(p1.rbegin(), p1.rend() - 1, std::back_inserter(out));
diff --git a/extern/carve/patches/random.patch b/extern/carve/patches/random.patch
deleted file mode 100644
index 36cc8d10430..00000000000
--- a/extern/carve/patches/random.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-diff -r 9a85d733a43d lib/polyhedron.cpp
---- a/lib/polyhedron.cpp Tue Jun 24 11:15:23 2014 +1000
-+++ b/lib/polyhedron.cpp Thu Nov 13 17:36:06 2014 +0500
-@@ -36,7 +36,11 @@
-
- #include <carve/mesh.hpp>
-
--#include BOOST_INCLUDE(random.hpp)
-+#ifdef HAVE_BOOST_LIBRARY
-+# include BOOST_INCLUDE(random.hpp)
-+#else
-+# include <carve/random/random.h>
-+#endif
-
- namespace {
- bool emb_test(carve::poly::Polyhedron *poly,
diff --git a/extern/carve/patches/series b/extern/carve/patches/series
deleted file mode 100644
index c5c5fd766b8..00000000000
--- a/extern/carve/patches/series
+++ /dev/null
@@ -1,13 +0,0 @@
-includes.patch
-win32.patch
-mesh_iterator.patch
-gcc46.patch
-clang_is_heap_fix.patch
-strict_flags.patch
-interpolator_reorder.patch
-mesh_simplify_dissolve_edges.patch
-mesh_simplify_uninitialized_var.patch
-memory_leak_fix.patch
-msvc_fix.patch
-face_hole_merge_workaround.patch
-random.patch
diff --git a/extern/carve/patches/strict_flags.patch b/extern/carve/patches/strict_flags.patch
deleted file mode 100644
index a40eecb25a4..00000000000
--- a/extern/carve/patches/strict_flags.patch
+++ /dev/null
@@ -1,439 +0,0 @@
-diff -r e82d852e4fb0 lib/csg_collector.cpp
---- a/lib/csg_collector.cpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/lib/csg_collector.cpp Mon Jan 27 17:01:46 2014 +0600
-@@ -21,6 +21,7 @@
-
- #include <carve/csg.hpp>
- #include <iostream>
-+#include "csg_collector.hpp"
- #include "intersect_debug.hpp"
-
- #if defined(CARVE_DEBUG_WRITE_PLY_DATA)
-diff -r e82d852e4fb0 lib/face.cpp
---- a/lib/face.cpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/lib/face.cpp Mon Jan 27 17:01:46 2014 +0600
-@@ -21,61 +21,69 @@
-
- #include <carve/poly.hpp>
-
--double CALC_X(const carve::geom::plane<3> &p, double y, double z) { return -(p.d + p.N.y * y + p.N.z * z) / p.N.x; }
--double CALC_Y(const carve::geom::plane<3> &p, double x, double z) { return -(p.d + p.N.x * x + p.N.z * z) / p.N.y; }
--double CALC_Z(const carve::geom::plane<3> &p, double x, double y) { return -(p.d + p.N.x * x + p.N.y * y) / p.N.z; }
-+namespace {
-+
-+ double CALC_X(const carve::geom::plane<3> &p, double y, double z) { return -(p.d + p.N.y * y + p.N.z * z) / p.N.x; }
-+ double CALC_Y(const carve::geom::plane<3> &p, double x, double z) { return -(p.d + p.N.x * x + p.N.z * z) / p.N.y; }
-+ double CALC_Z(const carve::geom::plane<3> &p, double x, double y) { return -(p.d + p.N.x * x + p.N.y * y) / p.N.z; }
-+
-+} // namespace
-
- namespace carve {
- namespace poly {
-
-- carve::geom2d::P2 _project_1(const carve::geom3d::Vector &v) {
-- return carve::geom::VECTOR(v.z, v.y);
-- }
-+ namespace {
-
-- carve::geom2d::P2 _project_2(const carve::geom3d::Vector &v) {
-- return carve::geom::VECTOR(v.x, v.z);
-- }
-+ carve::geom2d::P2 _project_1(const carve::geom3d::Vector &v) {
-+ return carve::geom::VECTOR(v.z, v.y);
-+ }
-
-- carve::geom2d::P2 _project_3(const carve::geom3d::Vector &v) {
-- return carve::geom::VECTOR(v.y, v.x);
-- }
-+ carve::geom2d::P2 _project_2(const carve::geom3d::Vector &v) {
-+ return carve::geom::VECTOR(v.x, v.z);
-+ }
-
-- carve::geom2d::P2 _project_4(const carve::geom3d::Vector &v) {
-- return carve::geom::VECTOR(v.y, v.z);
-- }
-+ carve::geom2d::P2 _project_3(const carve::geom3d::Vector &v) {
-+ return carve::geom::VECTOR(v.y, v.x);
-+ }
-
-- carve::geom2d::P2 _project_5(const carve::geom3d::Vector &v) {
-- return carve::geom::VECTOR(v.z, v.x);
-- }
-+ carve::geom2d::P2 _project_4(const carve::geom3d::Vector &v) {
-+ return carve::geom::VECTOR(v.y, v.z);
-+ }
-
-- carve::geom2d::P2 _project_6(const carve::geom3d::Vector &v) {
-- return carve::geom::VECTOR(v.x, v.y);
-- }
-+ carve::geom2d::P2 _project_5(const carve::geom3d::Vector &v) {
-+ return carve::geom::VECTOR(v.z, v.x);
-+ }
-
-+ carve::geom2d::P2 _project_6(const carve::geom3d::Vector &v) {
-+ return carve::geom::VECTOR(v.x, v.y);
-+ }
-
-- carve::geom3d::Vector _unproject_1(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-- return carve::geom::VECTOR(CALC_X(plane_eqn, p.y, p.x), p.y, p.x);
-- }
-
-- carve::geom3d::Vector _unproject_2(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-- return carve::geom::VECTOR(p.x, CALC_Y(plane_eqn, p.x, p.y), p.y);
-- }
-+ carve::geom3d::Vector _unproject_1(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-+ return carve::geom::VECTOR(CALC_X(plane_eqn, p.y, p.x), p.y, p.x);
-+ }
-
-- carve::geom3d::Vector _unproject_3(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-- return carve::geom::VECTOR(p.y, p.x, CALC_Z(plane_eqn, p.y, p.x));
-- }
-+ carve::geom3d::Vector _unproject_2(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-+ return carve::geom::VECTOR(p.x, CALC_Y(plane_eqn, p.x, p.y), p.y);
-+ }
-
-- carve::geom3d::Vector _unproject_4(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-- return carve::geom::VECTOR(CALC_X(plane_eqn, p.x, p.y), p.x, p.y);
-- }
-+ carve::geom3d::Vector _unproject_3(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-+ return carve::geom::VECTOR(p.y, p.x, CALC_Z(plane_eqn, p.y, p.x));
-+ }
-
-- carve::geom3d::Vector _unproject_5(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-- return carve::geom::VECTOR(p.y, CALC_Y(plane_eqn, p.y, p.x), p.x);
-- }
-+ carve::geom3d::Vector _unproject_4(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-+ return carve::geom::VECTOR(CALC_X(plane_eqn, p.x, p.y), p.x, p.y);
-+ }
-
-- carve::geom3d::Vector _unproject_6(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-- return carve::geom::VECTOR(p.x, p.y, CALC_Z(plane_eqn, p.x, p.y));
-- }
-+ carve::geom3d::Vector _unproject_5(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-+ return carve::geom::VECTOR(p.y, CALC_Y(plane_eqn, p.y, p.x), p.x);
-+ }
-+
-+ carve::geom3d::Vector _unproject_6(const carve::geom2d::P2 &p, const carve::geom3d::Plane &plane_eqn) {
-+ return carve::geom::VECTOR(p.x, p.y, CALC_Z(plane_eqn, p.x, p.y));
-+ }
-+
-+ } // namespace
-
- static carve::geom2d::P2 (*project_tab[2][3])(const carve::geom3d::Vector &) = {
- { &_project_1, &_project_2, &_project_3 },
-diff -r e82d852e4fb0 lib/geom2d.cpp
---- a/lib/geom2d.cpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/lib/geom2d.cpp Mon Jan 27 17:01:46 2014 +0600
-@@ -157,9 +157,9 @@
- return pointInPoly(points, p2_adapt_ident(), p);
- }
-
-- int lineSegmentPolyIntersections(const P2Vector &points,
-- LineSegment2 line,
-- std::vector<PolyIntersectionInfo> &out) {
-+ static int lineSegmentPolyIntersections(const P2Vector &points,
-+ LineSegment2 line,
-+ std::vector<PolyIntersectionInfo> &out) {
- int count = 0;
-
- if (line.v2 < line.v1) { line.flip(); }
-@@ -239,9 +239,9 @@
- }
- };
-
-- int sortedLineSegmentPolyIntersections(const P2Vector &points,
-- LineSegment2 line,
-- std::vector<PolyIntersectionInfo> &out) {
-+ static int sortedLineSegmentPolyIntersections(const P2Vector &points,
-+ LineSegment2 line,
-+ std::vector<PolyIntersectionInfo> &out) {
-
- bool swapped = line.v2 < line.v1;
-
-diff -r e82d852e4fb0 lib/intersect.cpp
---- a/lib/intersect.cpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/lib/intersect.cpp Mon Jan 27 17:01:46 2014 +0600
-@@ -1378,9 +1378,9 @@
- * @param result_list
- * @param shared_edge_ptr
- */
--void returnSharedEdges(carve::csg::V2Set &shared_edges,
-- std::list<carve::mesh::MeshSet<3> *> &result_list,
-- carve::csg::V2Set *shared_edge_ptr) {
-+static void returnSharedEdges(carve::csg::V2Set &shared_edges,
-+ std::list<carve::mesh::MeshSet<3> *> &result_list,
-+ carve::csg::V2Set *shared_edge_ptr) {
- // need to convert shared edges to point into result
- typedef std::map<carve::geom3d::Vector, carve::mesh::MeshSet<3>::vertex_t *> remap_type;
- remap_type remap;
-diff -r e82d852e4fb0 lib/intersect_face_division.cpp
---- a/lib/intersect_face_division.cpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/lib/intersect_face_division.cpp Mon Jan 27 17:01:46 2014 +0600
-@@ -1455,7 +1455,7 @@
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> base_loop;
- std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > hole_loops;
-
-- bool face_edge_intersected = assembleBaseLoop(face, data, base_loop, hooks);
-+ /*bool face_edge_intersected = */assembleBaseLoop(face, data, base_loop, hooks);
-
- detail::FV2SMap::const_iterator fse_iter = data.face_split_edges.find(face);
-
-diff -r e82d852e4fb0 lib/math.cpp
---- a/lib/math.cpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/lib/math.cpp Mon Jan 27 17:01:46 2014 +0600
-@@ -42,20 +42,21 @@
- Root(double r, int m) : root(r), multiplicity(m) {}
- };
-
-- void cplx_sqrt(double re, double im,
-- double &re_1, double &im_1,
-- double &re_2, double &im_2) {
-- if (re == 0.0 && im == 0.0) {
-- re_1 = re_2 = re;
-- im_1 = im_2 = im;
-- } else {
-- double d = sqrt(re * re + im * im);
-- re_1 = sqrt((d + re) / 2.0);
-- re_2 = re_1;
-- im_1 = fabs(sqrt((d - re) / 2.0));
-- im_2 = -im_1;
-+ namespace {
-+ void cplx_sqrt(double re, double im,
-+ double &re_1, double &im_1,
-+ double &re_2, double &im_2) {
-+ if (re == 0.0 && im == 0.0) {
-+ re_1 = re_2 = re;
-+ im_1 = im_2 = im;
-+ } else {
-+ double d = sqrt(re * re + im * im);
-+ re_1 = sqrt((d + re) / 2.0);
-+ re_2 = re_1;
-+ im_1 = fabs(sqrt((d - re) / 2.0));
-+ im_2 = -im_1;
-+ }
- }
-- }
-
- void cplx_cbrt(double re, double im,
- double &re_1, double &im_1,
-@@ -76,109 +77,110 @@
- }
- }
-
-- void add_root(std::vector<Root> &roots, double root) {
-- for (size_t i = 0; i < roots.size(); ++i) {
-- if (roots[i].root == root) {
-- roots[i].multiplicity++;
-+ void add_root(std::vector<Root> &roots, double root) {
-+ for (size_t i = 0; i < roots.size(); ++i) {
-+ if (roots[i].root == root) {
-+ roots[i].multiplicity++;
-+ return;
-+ }
-+ }
-+ roots.push_back(Root(root));
-+ }
-+
-+ void linear_roots(double c1, double c0, std::vector<Root> &roots) {
-+ roots.push_back(Root(c0 / c1));
-+ }
-+
-+ void quadratic_roots(double c2, double c1, double c0, std::vector<Root> &roots) {
-+ if (fabs(c2) < EPS) {
-+ linear_roots(c1, c0, roots);
- return;
- }
-- }
-- roots.push_back(Root(root));
-- }
-
-- void linear_roots(double c1, double c0, std::vector<Root> &roots) {
-- roots.push_back(Root(c0 / c1));
-- }
-+ double p = 0.5 * c1 / c2;
-+ double dis = p * p - c0 / c2;
-
-- void quadratic_roots(double c2, double c1, double c0, std::vector<Root> &roots) {
-- if (fabs(c2) < EPS) {
-- linear_roots(c1, c0, roots);
-- return;
-+ if (dis > 0.0) {
-+ dis = sqrt(dis);
-+ if (-p - dis != -p + dis) {
-+ roots.push_back(Root(-p - dis));
-+ roots.push_back(Root(-p + dis));
-+ } else {
-+ roots.push_back(Root(-p, 2));
-+ }
-+ }
- }
-
-- double p = 0.5 * c1 / c2;
-- double dis = p * p - c0 / c2;
-+ void cubic_roots(double c3, double c2, double c1, double c0, std::vector<Root> &roots) {
-+ int n_sol = 0;
-+ double _r[3];
-
-- if (dis > 0.0) {
-- dis = sqrt(dis);
-- if (-p - dis != -p + dis) {
-- roots.push_back(Root(-p - dis));
-- roots.push_back(Root(-p + dis));
-+ if (fabs(c3) < EPS) {
-+ quadratic_roots(c2, c1, c0, roots);
-+ return;
-+ }
-+
-+ if (fabs(c0) < EPS) {
-+ quadratic_roots(c3, c2, c1, roots);
-+ add_root(roots, 0.0);
-+ return;
-+ }
-+
-+ double xN = -c2 / (3.0 * c3);
-+ double yN = c0 + xN * (c1 + xN * (c2 + c3 * xN));
-+
-+ double delta_sq = (c2 * c2 - 3.0 * c3 * c1) / (9.0 * c3 * c3);
-+ double h_sq = 4.0 / 9.0 * (c2 * c2 - 3.0 * c3 * c1) * (delta_sq * delta_sq);
-+ double dis = yN * yN - h_sq;
-+
-+ if (dis > EPS) {
-+ // One real root, two complex roots.
-+
-+ double dis_sqrt = sqrt(dis);
-+ double r_p = yN - dis_sqrt;
-+ double r_q = yN + dis_sqrt;
-+ double p = cbrt(fabs(r_p)/(2.0 * c3));
-+ double q = cbrt(fabs(r_q)/(2.0 * c3));
-+
-+ if (r_p > 0.0) p = -p;
-+ if (r_q > 0.0) q = -q;
-+
-+ _r[0] = xN + p + q;
-+ n_sol = 1;
-+
-+ double re = xN - p * .5 - q * .5;
-+ double im = p * M_SQRT_3_4 - q * M_SQRT_3_4;
-+
-+ // root 2: xN + p * exp(M_2PI_3.i) + q * exp(-M_2PI_3.i);
-+ // root 3: complex conjugate of root 2
-+
-+ if (im < EPS) {
-+ _r[1] = _r[2] = re;
-+ n_sol += 2;
-+ }
-+ } else if (dis < -EPS) {
-+ // Three distinct real roots.
-+ double theta = acos(-yN / sqrt(h_sq)) / 3.0;
-+ double delta = sqrt(c2 * c2 - 3.0 * c3 * c1) / (3.0 * c3);
-+
-+ _r[0] = xN + (2.0 * delta) * cos(theta);
-+ _r[1] = xN + (2.0 * delta) * cos(M_2PI_3 - theta);
-+ _r[2] = xN + (2.0 * delta) * cos(M_2PI_3 + theta);
-+ n_sol = 3;
- } else {
-- roots.push_back(Root(-p, 2));
-+ // Three real roots (two or three equal).
-+ double r = yN / (2.0 * c3);
-+ double delta = cbrt(r);
-+
-+ _r[0] = xN + delta;
-+ _r[1] = xN + delta;
-+ _r[2] = xN - 2.0 * delta;
-+ n_sol = 3;
- }
-- }
-- }
-
-- void cubic_roots(double c3, double c2, double c1, double c0, std::vector<Root> &roots) {
-- int n_sol = 0;
-- double _r[3];
--
-- if (fabs(c3) < EPS) {
-- quadratic_roots(c2, c1, c0, roots);
-- return;
-- }
--
-- if (fabs(c0) < EPS) {
-- quadratic_roots(c3, c2, c1, roots);
-- add_root(roots, 0.0);
-- return;
-- }
--
-- double xN = -c2 / (3.0 * c3);
-- double yN = c0 + xN * (c1 + xN * (c2 + c3 * xN));
--
-- double delta_sq = (c2 * c2 - 3.0 * c3 * c1) / (9.0 * c3 * c3);
-- double h_sq = 4.0 / 9.0 * (c2 * c2 - 3.0 * c3 * c1) * (delta_sq * delta_sq);
-- double dis = yN * yN - h_sq;
--
-- if (dis > EPS) {
-- // One real root, two complex roots.
--
-- double dis_sqrt = sqrt(dis);
-- double r_p = yN - dis_sqrt;
-- double r_q = yN + dis_sqrt;
-- double p = cbrt(fabs(r_p)/(2.0 * c3));
-- double q = cbrt(fabs(r_q)/(2.0 * c3));
--
-- if (r_p > 0.0) p = -p;
-- if (r_q > 0.0) q = -q;
--
-- _r[0] = xN + p + q;
-- n_sol = 1;
--
-- double re = xN - p * .5 - q * .5;
-- double im = p * M_SQRT_3_4 - q * M_SQRT_3_4;
--
-- // root 2: xN + p * exp(M_2PI_3.i) + q * exp(-M_2PI_3.i);
-- // root 3: complex conjugate of root 2
--
-- if (im < EPS) {
-- _r[1] = _r[2] = re;
-- n_sol += 2;
-+ for (int i=0; i < n_sol; i++) {
-+ add_root(roots, _r[i]);
- }
-- } else if (dis < -EPS) {
-- // Three distinct real roots.
-- double theta = acos(-yN / sqrt(h_sq)) / 3.0;
-- double delta = sqrt(c2 * c2 - 3.0 * c3 * c1) / (3.0 * c3);
--
-- _r[0] = xN + (2.0 * delta) * cos(theta);
-- _r[1] = xN + (2.0 * delta) * cos(M_2PI_3 - theta);
-- _r[2] = xN + (2.0 * delta) * cos(M_2PI_3 + theta);
-- n_sol = 3;
-- } else {
-- // Three real roots (two or three equal).
-- double r = yN / (2.0 * c3);
-- double delta = cbrt(r);
--
-- _r[0] = xN + delta;
-- _r[1] = xN + delta;
-- _r[2] = xN - 2.0 * delta;
-- n_sol = 3;
-- }
--
-- for (int i=0; i < n_sol; i++) {
-- add_root(roots, _r[i]);
- }
- }
-
-diff -r e82d852e4fb0 lib/triangulator.cpp
---- a/lib/triangulator.cpp Wed Jan 15 13:16:14 2014 +1100
-+++ b/lib/triangulator.cpp Mon Jan 27 17:01:46 2014 +0600
-@@ -718,10 +718,10 @@
-
-
-
--bool testCandidateAttachment(const std::vector<std::vector<carve::geom2d::P2> > &poly,
-- std::vector<std::pair<size_t, size_t> > &current_f_loop,
-- size_t curr,
-- carve::geom2d::P2 hole_min) {
-+static bool testCandidateAttachment(const std::vector<std::vector<carve::geom2d::P2> > &poly,
-+ std::vector<std::pair<size_t, size_t> > &current_f_loop,
-+ size_t curr,
-+ carve::geom2d::P2 hole_min) {
- const size_t SZ = current_f_loop.size();
-
- if (!carve::geom2d::internalToAngle(pvert(poly, current_f_loop[(curr+1) % SZ]),
diff --git a/extern/carve/patches/win32.patch b/extern/carve/patches/win32.patch
deleted file mode 100644
index 1a5f9650532..00000000000
--- a/extern/carve/patches/win32.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-diff -r e82d852e4fb0 include/carve/win32.h
---- a/include/carve/win32.h Wed Jan 15 13:16:14 2014 +1100
-+++ b/include/carve/win32.h Fri Jan 31 15:32:01 2014 +0600
-@@ -32,17 +32,27 @@
-
- # if _MSC_VER < 1600
- // stdint.h is not available before VS2010
--typedef char int8_t;
--typedef short int16_t;
--typedef long int32_t;
-+#if defined(_WIN32)
-+/* The __intXX are built-in types of the visual complier! So we don't
-+ need to include anything else here.
-+ This typedefs should be in sync with types from MEM_sys_types.h */
-
--typedef unsigned char uint8_t;
--typedef unsigned short uint16_t;
--typedef unsigned long uint32_t;
-+typedef signed __int8 int8_t;
-+typedef signed __int16 int16_t;
-+typedef signed __int32 int32_t;
-
-+typedef unsigned __int8 uint8_t;
-+typedef unsigned __int16 uint16_t;
-+typedef unsigned __int32 uint32_t;
-+#endif
- typedef __int64 int64_t;
- typedef unsigned __int64 uint64_t;
- # else
- # include <stdint.h>
- # endif
- #endif
-+
-+#if defined(_MSC_VER)
-+# include <BaseTsd.h>
-+typedef SSIZE_T ssize_t;
-+#endif
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 599b7c943a4..32a1b3a771d 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -153,11 +153,6 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.row().prop(md, "offset_type", expand=True)
def BOOLEAN(self, layout, ob, md):
- solver = md.solver
- if not bpy.app.build_options.mod_boolean:
- if solver == 'CARVE':
- layout.label("Built without Carve solver")
-
split = layout.split()
col = split.column()
@@ -168,15 +163,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.label(text="Object:")
col.prop(md, "object", text="")
- split = layout.split()
- split.column().label(text="Solver:")
- split.column().prop(md, "solver", text="")
-
- if solver == 'BMESH':
- layout.prop(md, "double_threshold")
+ layout.prop(md, "double_threshold")
- if bpy.app.debug:
- layout.prop(md, "debug_options")
+ if bpy.app.debug:
+ layout.prop(md, "debug_options")
def BUILD(self, layout, ob, md):
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 72e453b7e23..283e801ea7a 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -655,8 +655,7 @@ typedef struct BooleanModifierData {
struct Object *object;
char operation;
- char solver;
- char pad;
+ char pad[2];
char bm_flag;
float double_threshold;
} BooleanModifierData;
@@ -667,11 +666,6 @@ typedef enum {
eBooleanModifierOp_Difference = 2,
} BooleanModifierOp;
-typedef enum {
- eBooleanModifierSolver_Carve = 0,
- eBooleanModifierSolver_BMesh = 1,
-} BooleanSolver;
-
/* bm_flag (only used when G_DEBUG) */
enum {
eBooleanModifierBMeshFlag_BMesh_Separate = (1 << 0),
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index b3ffbaa3b0d..99417ee7b1b 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1960,12 +1960,6 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static const EnumPropertyItem prop_solver_items[] = {
- {eBooleanModifierSolver_BMesh, "BMESH", 0, "BMesh", "Use the BMesh boolean solver"},
- {eBooleanModifierSolver_Carve, "CARVE", 0, "Carve", "Use the Carve boolean solver"},
- {0, NULL, 0, NULL, NULL}
- };
-
srna = RNA_def_struct(brna, "BooleanModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Boolean Modifier", "Boolean operations modifier");
RNA_def_struct_sdna(srna, "BooleanModifierData");
@@ -1982,11 +1976,6 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Operation", "");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
- prop = RNA_def_property(srna, "solver", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, prop_solver_items);
- RNA_def_property_ui_text(prop, "Solver", "");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
prop = RNA_def_property(srna, "double_threshold", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "double_threshold");
RNA_def_property_range(prop, 0, 1.0f);
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index d6a7b94505f..397a3263e22 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -107,7 +107,6 @@ set(SRC
intern/MOD_wireframe.c
MOD_modifiertypes.h
- intern/MOD_boolean_util.h
intern/MOD_fluidsim_util.h
intern/MOD_meshcache_util.h
intern/MOD_util.h
@@ -121,16 +120,6 @@ if(WITH_ALEMBIC)
)
endif()
-if(WITH_MOD_BOOLEAN)
- add_definitions(-DWITH_MOD_BOOLEAN)
- list(APPEND SRC
- intern/MOD_boolean_util.c
- )
- list(APPEND INC
- ../../../extern/carve
- )
-endif()
-
if(WITH_MOD_REMESH)
add_definitions(-DWITH_MOD_REMESH)
list(APPEND INC
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 0554fbb0317..7f79c941770 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -33,10 +33,6 @@
*/
// #ifdef DEBUG_TIME
-#define USE_BMESH
-#ifdef WITH_MOD_BOOLEAN
-# define USE_CARVE WITH_MOD_BOOLEAN
-#endif
#include <stdio.h>
@@ -49,11 +45,9 @@
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "MOD_boolean_util.h"
#include "MOD_util.h"
-#ifdef USE_BMESH
#include "BLI_alloca.h"
#include "BLI_math_geom.h"
#include "BKE_material.h"
@@ -63,18 +57,16 @@
#include "bmesh.h"
#include "bmesh_tools.h"
#include "tools/bmesh_intersect.h"
-#endif
#ifdef DEBUG_TIME
-#include "PIL_time.h"
-#include "PIL_time_utildefines.h"
+# include "PIL_time.h"
+# include "PIL_time_utildefines.h"
#endif
static void initData(ModifierData *md)
{
BooleanModifierData *bmd = (BooleanModifierData *)md;
- bmd->solver = eBooleanModifierSolver_BMesh;
bmd->double_threshold = 1e-6f;
}
@@ -118,8 +110,6 @@ static void updateDepsgraph(ModifierData *md,
DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Boolean Modifier");
}
-#if defined(USE_CARVE) || defined(USE_BMESH)
-
static DerivedMesh *get_quick_derivedMesh(
Object *ob_self, DerivedMesh *dm_self,
Object *ob_other, DerivedMesh *dm_other,
@@ -166,13 +156,7 @@ static DerivedMesh *get_quick_derivedMesh(
return result;
}
-#endif /* defined(USE_CARVE) || defined(USE_BMESH) */
-
-/* -------------------------------------------------------------------- */
-/* BMESH */
-
-#ifdef USE_BMESH
/* has no meaning for faces, do this so we can tell which face is which */
#define BM_FACE_TAG BM_ELEM_DRAW
@@ -185,8 +169,8 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0;
}
-static DerivedMesh *applyModifier_bmesh(
- ModifierData *md, Object *ob,
+static DerivedMesh *applyModifier(
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob,
DerivedMesh *dm,
ModifierApplyFlag flag)
{
@@ -354,66 +338,6 @@ static DerivedMesh *applyModifier_bmesh(
return dm;
}
-#endif /* USE_BMESH */
-
-
-/* -------------------------------------------------------------------- */
-/* CARVE */
-
-#ifdef USE_CARVE
-static DerivedMesh *applyModifier_carve(
- ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
- ModifierApplyFlag flag)
-{
- BooleanModifierData *bmd = (BooleanModifierData *) md;
- DerivedMesh *dm;
-
- if (!bmd->object)
- return derivedData;
-
- dm = get_dm_for_modifier(bmd->object, flag);
-
- if (dm) {
- DerivedMesh *result;
-
- /* when one of objects is empty (has got no faces) we could speed up
- * calculation a bit returning one of objects' derived meshes (or empty one)
- * Returning mesh is depended on modifiers operation (sergey) */
- result = get_quick_derivedMesh(ob, derivedData, bmd->object, dm, bmd->operation);
-
- if (result == NULL) {
-#ifdef DEBUG_TIME
- TIMEIT_START(boolean_carve);
-#endif
-
- result = NewBooleanDerivedMesh(dm, bmd->object, derivedData, ob,
- 1 + bmd->operation);
-#ifdef DEBUG_TIME
- TIMEIT_END(boolean_carve);
-#endif
- }
-
- /* if new mesh returned, return it; otherwise there was
- * an error, so delete the modifier object */
- if (result)
- return result;
- else
- modifier_setError(md, "Cannot execute boolean operation");
- }
-
- return derivedData;
-}
-#endif /* USE_CARVE */
-
-
-static DerivedMesh *applyModifier_nop(
- ModifierData *UNUSED(md), Object *UNUSED(ob),
- DerivedMesh *derivedData,
- ModifierApplyFlag UNUSED(flag))
-{
- return derivedData;
-}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md))
{
@@ -424,28 +348,6 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(
return dataMask;
}
-static DerivedMesh *applyModifier(
- ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
- Object *ob, DerivedMesh *derivedData,
- ModifierApplyFlag flag)
-{
- BooleanModifierData *bmd = (BooleanModifierData *)md;
-
- switch (bmd->solver) {
-#ifdef USE_CARVE
- case eBooleanModifierSolver_Carve:
- return applyModifier_carve(md, ob, derivedData, flag);
-#endif
-#ifdef USE_BMESH
- case eBooleanModifierSolver_BMesh:
- return applyModifier_bmesh(md, ob, derivedData, flag);
-#endif
- default:
- return applyModifier_nop(md, ob, derivedData, flag);
- }
-}
-
-
ModifierTypeInfo modifierType_Boolean = {
/* name */ "Boolean",
/* structName */ "BooleanModifierData",
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c
deleted file mode 100644
index 49010664aa8..00000000000
--- a/source/blender/modifiers/intern/MOD_boolean_util.c
+++ /dev/null
@@ -1,790 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation
- * All rights reserved.
- *
- * Contributor(s): Sergey Sharybin.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/modifiers/intern/MOD_boolean_util.c
- * \ingroup modifiers
- */
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_material_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-
-#include "BLI_utildefines.h"
-#include "BLI_alloca.h"
-#include "BLI_ghash.h"
-#include "BLI_math.h"
-
-#include "BKE_cdderivedmesh.h"
-#include "BKE_material.h"
-
-#include "MOD_boolean_util.h"
-
-#include "carve-capi.h"
-
-/* Adopted from BM_loop_interp_from_face(),
- *
- * Transform matrix is used in cases when target coordinate needs
- * to be converted to source space (namely when interpolating
- * boolean result loops from second operand).
- *
- * TODO(sergey): Consider making it a generic function in DerivedMesh.c.
- */
-static void DM_loop_interp_from_poly(DerivedMesh *source_dm,
- MVert *source_mverts,
- MLoop *source_mloops,
- MPoly *source_poly,
- DerivedMesh *target_dm,
- MVert *target_mverts,
- MLoop *target_mloop,
- float transform[4][4],
- int target_loop_index)
-{
- float (*cos_3d)[3] = BLI_array_alloca(cos_3d, source_poly->totloop);
- int *source_indices = BLI_array_alloca(source_indices, source_poly->totloop);
- float *weights = BLI_array_alloca(weights, source_poly->totloop);
- int i;
- int target_vert_index = target_mloop[target_loop_index].v;
- float coord[3];
-
- for (i = 0; i < source_poly->totloop; ++i) {
- MLoop *mloop = &source_mloops[source_poly->loopstart + i];
- source_indices[i] = source_poly->loopstart + i;
- copy_v3_v3(cos_3d[i], source_mverts[mloop->v].co);
- }
-
- if (transform) {
- mul_v3_m4v3(coord, transform, target_mverts[target_vert_index].co);
- }
- else {
- copy_v3_v3(coord, target_mverts[target_vert_index].co);
- }
-
- interp_weights_poly_v3(weights, cos_3d, source_poly->totloop, coord);
-
- DM_interp_loop_data(source_dm, target_dm, source_indices, weights,
- source_poly->totloop, target_loop_index);
-}
-
-typedef struct DMArrays {
- MVert *mvert;
- MEdge *medge;
- MLoop *mloop;
- MPoly *mpoly;
- bool mvert_allocated;
- bool medge_allocated;
- bool mloop_allocated;
- bool mpoly_allocated;
-} DMArrays;
-
-static void dm_arrays_get(DerivedMesh *dm, DMArrays *arrays)
-{
- arrays->mvert = DM_get_vert_array(dm, &arrays->mvert_allocated);
- arrays->medge = DM_get_edge_array(dm, &arrays->medge_allocated);
- arrays->mloop = DM_get_loop_array(dm, &arrays->mloop_allocated);
- arrays->mpoly = DM_get_poly_array(dm, &arrays->mpoly_allocated);
-}
-
-static void dm_arrays_free(DMArrays *arrays)
-{
- if (arrays->mvert_allocated) {
- MEM_freeN(arrays->mvert);
- }
- if (arrays->medge_allocated) {
- MEM_freeN(arrays->medge);
- }
- if (arrays->mloop_allocated) {
- MEM_freeN(arrays->mloop);
- }
- if (arrays->mpoly_allocated) {
- MEM_freeN(arrays->mpoly);
- }
-}
-
-/* **** Importer from derived mesh to Carve **** */
-
-typedef struct ImportMeshData {
- DerivedMesh *dm;
- float obmat[4][4];
- MVert *mvert;
- MEdge *medge;
- MLoop *mloop;
- MPoly *mpoly;
-} ImportMeshData;
-
-/* Get number of vertices. */
-static int importer_GetNumVerts(ImportMeshData *import_data)
-{
- DerivedMesh *dm = import_data->dm;
- return dm->getNumVerts(dm);
-}
-
-/* Get number of edges. */
-static int importer_GetNumEdges(ImportMeshData *import_data)
-{
- DerivedMesh *dm = import_data->dm;
- return dm->getNumEdges(dm);
-}
-
-/* Get number of loops. */
-static int importer_GetNumLoops(ImportMeshData *import_data)
-{
- DerivedMesh *dm = import_data->dm;
- return dm->getNumLoops(dm);
-}
-
-/* Get number of polys. */
-static int importer_GetNumPolys(ImportMeshData *import_data)
-{
- DerivedMesh *dm = import_data->dm;
- return dm->getNumPolys(dm);
-}
-
-/* Get 3D coordinate of vertex with given index. */
-static void importer_GetVertCoord(ImportMeshData *import_data, int vert_index, float coord[3])
-{
- MVert *mvert = import_data->mvert;
-
- BLI_assert(vert_index >= 0 && vert_index < import_data->dm->getNumVerts(import_data->dm));
-
- mul_v3_m4v3(coord, import_data->obmat, mvert[vert_index].co);
-}
-
-/* Get index of vertices which are adjucent to edge specified by it's index. */
-static void importer_GetEdgeVerts(ImportMeshData *import_data, int edge_index, int *v1, int *v2)
-{
- MEdge *medge = &import_data->medge[edge_index];
-
- BLI_assert(edge_index >= 0 && edge_index < import_data->dm->getNumEdges(import_data->dm));
-
- *v1 = medge->v1;
- *v2 = medge->v2;
-}
-
-/* Get number of adjucent vertices to the poly specified by it's index. */
-static int importer_GetPolyNumVerts(ImportMeshData *import_data, int poly_index)
-{
- MPoly *mpoly = import_data->mpoly;
-
- BLI_assert(poly_index >= 0 && poly_index < import_data->dm->getNumPolys(import_data->dm));
-
- return mpoly[poly_index].totloop;
-}
-
-/* Get list of adjucent vertices to the poly specified by it's index. */
-static void importer_GetPolyVerts(ImportMeshData *import_data, int poly_index, int *verts)
-{
- MPoly *mpoly = &import_data->mpoly[poly_index];
- MLoop *mloop = import_data->mloop + mpoly->loopstart;
- int i;
- BLI_assert(poly_index >= 0 && poly_index < import_data->dm->getNumPolys(import_data->dm));
- for (i = 0; i < mpoly->totloop; i++, mloop++) {
- verts[i] = mloop->v;
- }
-}
-
-// Triangulate 2D polygon.
-#if 0
-static int importer_triangulate2DPoly(ImportMeshData *UNUSED(import_data),
- const float (*vertices)[2], int num_vertices,
- unsigned int (*triangles)[3])
-{
- // TODO(sergey): Currently import_data is unused but in the future we could
- // put memory arena there which will reduce amount of allocations happening
- // over the triangulation period.
- //
- // However that's not so much straighforward to do it right now because we
- // also are tu consider threaded import/export.
-
- BLI_assert(num_vertices > 3);
-
- BLI_polyfill_calc(vertices, num_vertices, triangles);
-
- return num_vertices - 2;
-}
-#endif
-
-static CarveMeshImporter MeshImporter = {
- importer_GetNumVerts,
- importer_GetNumEdges,
- importer_GetNumLoops,
- importer_GetNumPolys,
- importer_GetVertCoord,
- importer_GetEdgeVerts,
- importer_GetPolyNumVerts,
- importer_GetPolyVerts,
-
- /* TODO(sergey): We don't use BLI_polyfill_calc() because it tends
- * to generate degenerated geometry which is fatal for booleans.
- *
- * For now we stick to Carve's triangulation.
- */
- NULL, /* importer_triangulate2DPoly */
-};
-
-/* **** Exporter from Carve to derived mesh **** */
-
-typedef struct ExportMeshData {
- DerivedMesh *dm;
- float obimat[4][4];
- MVert *mvert;
- MEdge *medge;
- MLoop *mloop;
- MPoly *mpoly;
- int *vert_origindex;
- int *edge_origindex;
- int *poly_origindex;
- int *loop_origindex;
-
- /* Objects and derived meshes of left and right operands.
- * Used for custom data merge and interpolation.
- */
- Object *ob_left;
- Object *ob_right;
- DerivedMesh *dm_left;
- DerivedMesh *dm_right;
- MVert *mvert_left;
- MEdge *medge_left;
- MLoop *mloop_left;
- MPoly *mpoly_left;
- MVert *mvert_right;
- MEdge *medge_right;
- MLoop *mloop_right;
- MPoly *mpoly_right;
-
- float left_to_right_mat[4][4];
-
- /* Hash to map materials from right object to result. */
- GHash *material_hash;
-} ExportMeshData;
-
-BLI_INLINE Object *which_object(ExportMeshData *export_data, int which_mesh)
-{
- Object *object = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- object = export_data->ob_left;
- break;
- case CARVE_MESH_RIGHT:
- object = export_data->ob_right;
- break;
- }
- return object;
-}
-
-BLI_INLINE DerivedMesh *which_dm(ExportMeshData *export_data, int which_mesh)
-{
- DerivedMesh *dm = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- dm = export_data->dm_left;
- break;
- case CARVE_MESH_RIGHT:
- dm = export_data->dm_right;
- break;
- }
- return dm;
-}
-
-BLI_INLINE MVert *which_mvert(ExportMeshData *export_data, int which_mesh)
-{
- MVert *mvert = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- mvert = export_data->mvert_left;
- break;
- case CARVE_MESH_RIGHT:
- mvert = export_data->mvert_right;
- break;
- }
- return mvert;
-}
-
-BLI_INLINE MEdge *which_medge(ExportMeshData *export_data, int which_mesh)
-{
- MEdge *medge = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- medge = export_data->medge_left;
- break;
- case CARVE_MESH_RIGHT:
- medge = export_data->medge_right;
- break;
- }
- return medge;
-}
-
-BLI_INLINE MLoop *which_mloop(ExportMeshData *export_data, int which_mesh)
-{
- MLoop *mloop = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- mloop = export_data->mloop_left;
- break;
- case CARVE_MESH_RIGHT:
- mloop = export_data->mloop_right;
- break;
- }
- return mloop;
-}
-
-BLI_INLINE MPoly *which_mpoly(ExportMeshData *export_data, int which_mesh)
-{
- MPoly *mpoly = NULL;
- switch (which_mesh) {
- case CARVE_MESH_LEFT:
- mpoly = export_data->mpoly_left;
- break;
- case CARVE_MESH_RIGHT:
- mpoly = export_data->mpoly_right;
- break;
- }
- return mpoly;
-}
-
-/* Create new external mesh */
-static void exporter_InitGeomArrays(ExportMeshData *export_data,
- int num_verts, int num_edges,
- int num_loops, int num_polys)
-{
- DerivedMesh *dm = CDDM_new(num_verts, num_edges, 0,
- num_loops, num_polys);
- DerivedMesh *dm_left = export_data->dm_left,
- *dm_right = export_data->dm_right;
-
- /* Mask for custom data layers to be merged from operands. */
- CustomDataMask merge_mask = CD_MASK_DERIVEDMESH & ~CD_MASK_ORIGINDEX;
-
- export_data->dm = dm;
- export_data->mvert = dm->getVertArray(dm);
- export_data->medge = dm->getEdgeArray(dm);
- export_data->mloop = dm->getLoopArray(dm);
- export_data->mpoly = dm->getPolyArray(dm);
-
- /* Merge custom data layers from operands.
- *
- * Will only create custom data layers for all the layers which appears in
- * the operand. Data for those layers will not be allocated or initialized.
- */
-
- CustomData_merge(&dm_left->vertData, &dm->vertData, merge_mask, CD_DEFAULT, num_verts);
- CustomData_merge(&dm_right->vertData, &dm->vertData, merge_mask, CD_DEFAULT, num_verts);
-
- CustomData_merge(&dm_left->loopData, &dm->loopData, merge_mask, CD_DEFAULT, num_loops);
- CustomData_merge(&dm_right->loopData, &dm->loopData, merge_mask, CD_DEFAULT, num_loops);
-
- CustomData_merge(&dm_left->polyData, &dm->polyData, merge_mask, CD_DEFAULT, num_polys);
- CustomData_merge(&dm_right->polyData, &dm->polyData, merge_mask, CD_DEFAULT, num_polys);
-
- CustomData_merge(&dm_left->edgeData, &dm->edgeData, merge_mask, CD_DEFAULT, num_edges);
- CustomData_merge(&dm_right->edgeData, &dm->edgeData, merge_mask, CD_DEFAULT, num_edges);
-
- export_data->vert_origindex = dm->getVertDataArray(dm, CD_ORIGINDEX);
- export_data->edge_origindex = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
- export_data->poly_origindex = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- export_data->loop_origindex = dm->getLoopDataArray(dm, CD_ORIGINDEX);
-}
-
-/* Set coordinate of vertex with given index. */
-static void exporter_SetVert(ExportMeshData *export_data,
- int vert_index, float coord[3],
- int which_orig_mesh, int orig_vert_index)
-{
- DerivedMesh *dm = export_data->dm;
- DerivedMesh *dm_orig;
- MVert *mvert = export_data->mvert;
-
- BLI_assert(vert_index >= 0 && vert_index <= dm->getNumVerts(dm));
-
- dm_orig = which_dm(export_data, which_orig_mesh);
- if (dm_orig) {
- BLI_assert(orig_vert_index >= 0 && orig_vert_index < dm_orig->getNumVerts(dm_orig));
- mvert[vert_index] = which_mvert(export_data, which_orig_mesh)[orig_vert_index];
- CustomData_copy_data(&dm_orig->vertData, &dm->vertData, orig_vert_index, vert_index, 1);
- }
-
- /* Set original index of the vertex. */
- if (export_data->vert_origindex) {
- if (which_orig_mesh == CARVE_MESH_LEFT) {
- export_data->vert_origindex[vert_index] = orig_vert_index;
- }
- else {
- export_data->vert_origindex[vert_index] = ORIGINDEX_NONE;
- }
- }
-
- mul_v3_m4v3(mvert[vert_index].co, export_data->obimat, coord);
-}
-
-/* Set vertices which are adjucent to the edge specified by it's index. */
-static void exporter_SetEdge(ExportMeshData *export_data,
- int edge_index, int v1, int v2,
- int which_orig_mesh, int orig_edge_index)
-{
- DerivedMesh *dm = export_data->dm;
- MEdge *medge = &export_data->medge[edge_index];
- DerivedMesh *dm_orig;
-
- BLI_assert(edge_index >= 0 && edge_index < dm->getNumEdges(dm));
- BLI_assert(v1 >= 0 && v1 < dm->getNumVerts(dm));
- BLI_assert(v2 >= 0 && v2 < dm->getNumVerts(dm));
-
- dm_orig = which_dm(export_data, which_orig_mesh);
- if (dm_orig) {
- BLI_assert(orig_edge_index >= 0 && orig_edge_index < dm_orig->getNumEdges(dm_orig));
-
- *medge = which_medge(export_data, which_orig_mesh)[orig_edge_index];
-
- /* Copy all edge layers, including medge. */
- CustomData_copy_data(&dm_orig->edgeData, &dm->edgeData, orig_edge_index, edge_index, 1);
- }
-
- /* Set original index of the edge. */
- if (export_data->edge_origindex) {
- if (which_orig_mesh == CARVE_MESH_LEFT) {
- export_data->edge_origindex[edge_index] = orig_edge_index;
- }
- else {
- export_data->edge_origindex[edge_index] = ORIGINDEX_NONE;
- }
- }
-
- medge->v1 = v1;
- medge->v2 = v2;
-
- medge->flag |= ME_EDGEDRAW | ME_EDGERENDER;
-}
-
-static void setMPolyMaterial(ExportMeshData *export_data,
- MPoly *mpoly,
- int which_orig_mesh)
-{
- Object *orig_object;
- GHash *material_hash;
- Material *orig_mat;
-
- if (which_orig_mesh == CARVE_MESH_LEFT) {
- /* No need to change materian index for faces from left operand */
- return;
- }
-
- material_hash = export_data->material_hash;
- orig_object = which_object(export_data, which_orig_mesh);
-
- /* Set material, based on lookup in hash table. */
- orig_mat = give_current_material(orig_object, mpoly->mat_nr + 1);
-
- if (orig_mat) {
- /* For faces from right operand check if there's requested material
- * in the left operand. And if it is, use index of that material,
- * otherwise fallback to first material (material with index=0).
- */
- if (!BLI_ghash_haskey(material_hash, orig_mat)) {
- int a, mat_nr;
-
- mat_nr = 0;
- for (a = 0; a < export_data->ob_left->totcol; a++) {
- if (give_current_material(export_data->ob_left, a + 1) == orig_mat) {
- mat_nr = a;
- break;
- }
- }
-
- BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr));
-
- mpoly->mat_nr = mat_nr;
- }
- else
- mpoly->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat));
- }
- else {
- mpoly->mat_nr = 0;
- }
-}
-
-/* Set list of adjucent loops to the poly specified by it's index. */
-static void exporter_SetPoly(ExportMeshData *export_data,
- int poly_index, int start_loop, int num_loops,
- int which_orig_mesh, int orig_poly_index)
-{
- DerivedMesh *dm = export_data->dm;
- MPoly *mpoly = &export_data->mpoly[poly_index];
- DerivedMesh *dm_orig;
- int i;
-
- /* Poly is always to be either from left or right operand. */
- dm_orig = which_dm(export_data, which_orig_mesh);
-
- BLI_assert(poly_index >= 0 && poly_index < dm->getNumPolys(dm));
- BLI_assert(start_loop >= 0 && start_loop <= dm->getNumLoops(dm) - num_loops);
- BLI_assert(num_loops >= 3);
- BLI_assert(dm_orig != NULL);
- BLI_assert(orig_poly_index >= 0 && orig_poly_index < dm_orig->getNumPolys(dm_orig));
-
- /* Copy all poly layers, including mpoly. */
- *mpoly = which_mpoly(export_data, which_orig_mesh)[orig_poly_index];
- CustomData_copy_data(&dm_orig->polyData, &dm->polyData, orig_poly_index, poly_index, 1);
-
- /* Set material of the curren poly.
- * This would re-map materials from right operand to materials from the
- * left one as well.
- */
- setMPolyMaterial(export_data, mpoly, which_orig_mesh);
-
- /* Set original index of the poly. */
- if (export_data->poly_origindex) {
- if (which_orig_mesh == CARVE_MESH_LEFT) {
- export_data->poly_origindex[poly_index] = orig_poly_index;
- }
- else {
- export_data->poly_origindex[poly_index] = ORIGINDEX_NONE;
- }
- }
-
- /* Set poly data itself. */
- mpoly->loopstart = start_loop;
- mpoly->totloop = num_loops;
-
- /* Interpolate data for poly loops. */
- {
- MVert *source_mverts = which_mvert(export_data, which_orig_mesh);
- MLoop *source_mloops = which_mloop(export_data, which_orig_mesh);
- MPoly *source_mpolys = which_mpoly(export_data, which_orig_mesh);
- MPoly *source_poly = &source_mpolys[orig_poly_index];
- MVert *target_mverts = export_data->mvert;
- MLoop *target_mloops = export_data->mloop;
- float (*transform)[4] = NULL;
-
- if (which_orig_mesh == CARVE_MESH_RIGHT) {
- transform = export_data->left_to_right_mat;
- }
-
- for (i = 0; i < mpoly->totloop; i++) {
- DM_loop_interp_from_poly(dm_orig,
- source_mverts,
- source_mloops,
- source_poly,
- dm,
- target_mverts,
- target_mloops,
- transform,
- i + mpoly->loopstart);
- }
- }
-}
-
-/* Set list vertex and edge which are adjucent to loop with given index. */
-static void exporter_SetLoop(ExportMeshData *export_data,
- int loop_index, int vertex, int edge,
- int which_orig_mesh, int orig_loop_index)
-{
- DerivedMesh *dm = export_data->dm;
- MLoop *mloop = &export_data->mloop[loop_index];
- DerivedMesh *dm_orig;
-
- BLI_assert(loop_index >= 0 && loop_index < dm->getNumLoops(dm));
- BLI_assert(vertex >= 0 && vertex < dm->getNumVerts(dm));
- BLI_assert(edge >= 0 && vertex < dm->getNumEdges(dm));
-
- dm_orig = which_dm(export_data, which_orig_mesh);
- if (dm_orig) {
- BLI_assert(orig_loop_index >= 0 && orig_loop_index < dm_orig->getNumLoops(dm_orig));
-
- /* Copy all loop layers, including mloop. */
- *mloop = which_mloop(export_data, which_orig_mesh)[orig_loop_index];
- CustomData_copy_data(&dm_orig->loopData, &dm->loopData, orig_loop_index, loop_index, 1);
- }
-
- /* Set original index of the loop. */
- if (export_data->loop_origindex) {
- if (which_orig_mesh == CARVE_MESH_LEFT) {
- export_data->loop_origindex[loop_index] = orig_loop_index;
- }
- else {
- export_data->loop_origindex[loop_index] = ORIGINDEX_NONE;
- }
- }
-
- mloop->v = vertex;
- mloop->e = edge;
-}
-
-/* Edge index from a loop index for a given original mesh. */
-static int exporter_MapLoopToEdge(ExportMeshData *export_data,
- int which_mesh, int loop_index)
-{
- DerivedMesh *dm = which_dm(export_data, which_mesh);
- MLoop *mloop = which_mloop(export_data, which_mesh);
-
- (void) dm; /* Unused in release builds. */
-
- BLI_assert(dm != NULL);
- BLI_assert(loop_index >= 0 && loop_index < dm->getNumLoops(dm));
-
- return mloop[loop_index].e;
-}
-
-static CarveMeshExporter MeshExporter = {
- exporter_InitGeomArrays,
- exporter_SetVert,
- exporter_SetEdge,
- exporter_SetPoly,
- exporter_SetLoop,
- exporter_MapLoopToEdge
-};
-
-static int operation_from_optype(int int_op_type)
-{
- int operation;
-
- switch (int_op_type) {
- case 1:
- operation = CARVE_OP_INTERSECTION;
- break;
- case 2:
- operation = CARVE_OP_UNION;
- break;
- case 3:
- operation = CARVE_OP_A_MINUS_B;
- break;
- default:
- BLI_assert(!"Should not happen");
- operation = -1;
- break;
- }
-
- return operation;
-}
-
-static void prepare_import_data(Object *object,
- DerivedMesh *dm,
- const DMArrays *dm_arrays,
- ImportMeshData *import_data)
-{
- import_data->dm = dm;
- copy_m4_m4(import_data->obmat, object->obmat);
- import_data->mvert = dm_arrays->mvert;
- import_data->medge = dm_arrays->medge;
- import_data->mloop = dm_arrays->mloop;
- import_data->mpoly = dm_arrays->mpoly;
-}
-
-static struct CarveMeshDescr *carve_mesh_from_dm(Object *object,
- DerivedMesh *dm,
- const DMArrays *dm_arrays)
-{
- ImportMeshData import_data;
- prepare_import_data(object, dm, dm_arrays, &import_data);
- return carve_addMesh(&import_data, &MeshImporter);
-}
-
-static void prepare_export_data(Object *object_left, DerivedMesh *dm_left, const DMArrays *dm_left_arrays,
- Object *object_right, DerivedMesh *dm_right, const DMArrays *dm_right_arrays,
- ExportMeshData *export_data)
-{
- float object_right_imat[4][4];
-
- invert_m4_m4(export_data->obimat, object_left->obmat);
-
- export_data->ob_left = object_left;
- export_data->ob_right = object_right;
-
- export_data->dm_left = dm_left;
- export_data->dm_right = dm_right;
-
- export_data->mvert_left = dm_left_arrays->mvert;
- export_data->medge_left = dm_left_arrays->medge;
- export_data->mloop_left = dm_left_arrays->mloop;
- export_data->mpoly_left = dm_left_arrays->mpoly;
- export_data->mvert_right = dm_right_arrays->mvert;
- export_data->medge_right = dm_right_arrays->medge;
- export_data->mloop_right = dm_right_arrays->mloop;
- export_data->mpoly_right = dm_right_arrays->mpoly;
-
- export_data->material_hash = BLI_ghash_ptr_new("CSG_mat gh");
-
- /* Matrix to convert coord from left object's loca; space to
- * right object's local space.
- */
- invert_m4_m4(object_right_imat, object_right->obmat);
- mul_m4_m4m4(export_data->left_to_right_mat, object_left->obmat,
- object_right_imat);
-}
-
-DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob,
- DerivedMesh *dm_select, struct Object *ob_select,
- int int_op_type)
-{
-
- struct CarveMeshDescr *left, *right, *output = NULL;
- DerivedMesh *output_dm = NULL;
- int operation;
- bool result;
- DMArrays dm_left_arrays, dm_right_arrays;
-
- if (dm == NULL || dm_select == NULL) {
- return NULL;
- }
-
- operation = operation_from_optype(int_op_type);
- if (operation == -1) {
- return NULL;
- }
-
- dm_arrays_get(dm_select, &dm_left_arrays);
- dm_arrays_get(dm, &dm_right_arrays);
-
- left = carve_mesh_from_dm(ob_select, dm_select, &dm_left_arrays);
- right = carve_mesh_from_dm(ob, dm, &dm_right_arrays);
-
- result = carve_performBooleanOperation(left, right, operation, &output);
-
- carve_deleteMesh(left);
- carve_deleteMesh(right);
-
- if (result) {
- ExportMeshData export_data;
-
- prepare_export_data(ob_select, dm_select, &dm_left_arrays,
- ob, dm, &dm_right_arrays,
- &export_data);
-
- carve_exportMesh(output, &MeshExporter, &export_data);
- output_dm = export_data.dm;
-
- /* Free memory used by export mesh. */
- BLI_ghash_free(export_data.material_hash, NULL, NULL);
-
- output_dm->cd_flag |= dm->cd_flag | dm_select->cd_flag;
- output_dm->dirty |= DM_DIRTY_NORMALS;
- carve_deleteMesh(output);
- }
-
- dm_arrays_free(&dm_left_arrays);
- dm_arrays_free(&dm_right_arrays);
-
- return output_dm;
-}
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.h b/source/blender/modifiers/intern/MOD_boolean_util.h
deleted file mode 100644
index 00d7c37b266..00000000000
--- a/source/blender/modifiers/intern/MOD_boolean_util.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/modifiers/intern/MOD_boolean_util.h
- * \ingroup modifiers
- */
-
-
-#ifndef __MOD_BOOLEAN_UTIL_H__
-#define __MOD_BOOLEAN_UTIL_H__
-
-struct Object;
-struct DerivedMesh;
-
-/* Performs a boolean between two mesh objects, it is assumed that both objects
- * are in fact mesh object. On success returns a DerivedMesh. On failure
- * returns NULL and reports an error. */
-
-struct DerivedMesh *NewBooleanDerivedMesh(struct DerivedMesh *dm, struct Object *ob,
- struct DerivedMesh *dm_select, struct Object *ob_select, int int_op_type);
-
-#endif /* MOD_BOOLEAN_UTILS */
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index 41018468695..a71478cdb15 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -248,10 +248,6 @@ if(WITH_LIBMV)
add_definitions(-DWITH_LIBMV)
endif()
-if(WITH_MOD_BOOLEAN)
- add_definitions(-DWITH_MOD_BOOLEAN)
-endif()
-
if(WITH_MOD_FLUID)
add_definitions(-DWITH_MOD_FLUID)
endif()
diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c
index 501e09dd6ad..d5c325e4317 100644
--- a/source/blender/python/intern/bpy_app_build_options.c
+++ b/source/blender/python/intern/bpy_app_build_options.c
@@ -58,7 +58,6 @@ static PyStructSequence_Field app_builtopts_info_fields[] = {
{(char *)"sdl_dynload", NULL},
{(char *)"jack", NULL},
{(char *)"libmv", NULL},
- {(char *)"mod_boolean", NULL},
{(char *)"mod_fluid", NULL},
{(char *)"mod_oceansim", NULL},
{(char *)"mod_remesh", NULL},
@@ -237,12 +236,6 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
-#ifdef WITH_MOD_BOOLEAN
- SetObjIncref(Py_True);
-#else
- SetObjIncref(Py_False);
-#endif
-
#ifdef WITH_MOD_FLUID
SetObjIncref(Py_True);
#else
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 328453df118..dc7acb5ccd7 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -197,10 +197,6 @@ endif()
list(APPEND BLENDER_SORTED_LIBS extern_ceres)
endif()
- if(WITH_MOD_BOOLEAN)
- list(APPEND BLENDER_SORTED_LIBS extern_carve)
- endif()
-
if(WITH_GHOST_XDND)
list(APPEND BLENDER_SORTED_LIBS extern_xdnd)
endif()