diff options
151 files changed, 8 insertions, 34746 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c4ce5030ac..c0a0b4bd27f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -310,7 +310,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) @@ -645,13 +644,12 @@ 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) set_and_warn(WITH_OPENAL OFF) # depends on AUDASPACE set_and_warn(WITH_GAMEENGINE OFF) # depends on AUDASPACE set_and_warn(WITH_PLAYER OFF) # depends on GAMEENGINE elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_AUDASPACE 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. @@ -1758,7 +1756,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 8ec2b1c6da5..e3eb4d9241a 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -721,10 +721,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 91919adb4a2..2e8589ffd17 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> ¤t_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> > ¤t_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> > ¤t_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> > ¤t_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 3b62d37181a..942882a9053 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 bbacdaebe5d..766dd196562 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 f3d3ed4692b..2f92c47eed9 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1958,12 +1958,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"); @@ -1980,11 +1974,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 ad2b862141c..a70612447d3 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 @@ -125,16 +124,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 45c829e05fb..2a6bf108f25 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> @@ -51,11 +47,9 @@ #include "depsgraph_private.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" @@ -65,18 +59,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; } @@ -136,8 +128,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, @@ -184,13 +174,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 @@ -203,7 +187,7 @@ 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( +static DerivedMesh *applyModifier( ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag flag) @@ -372,66 +356,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)) { @@ -442,28 +366,6 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED( return dataMask; } -static DerivedMesh *applyModifier( - ModifierData *md, 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 cdbf65546d3..2b6dc54dad4 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -240,10 +240,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 e5a5ff828dd..25ae83d04cd 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -188,10 +188,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() |