diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 54acc136b..cfee06342 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.13)
project(PrusaSlicer-native)
-add_subdirectory(mesh_fix)
add_subdirectory(build-utils)
add_subdirectory(admesh)
add_subdirectory(avrdude)
diff --git a/src/mesh_fix/CMakeLists.txt b/src/mesh_fix/CMakeLists.txt
deleted file mode 100644
index d0a195131..000000000
--- a/src/mesh_fix/CMakeLists.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-################################################################################
-
-set(SOURCES
- src/TMesh/edge.cpp
- src/TMesh/vertex.cpp
- src/TMesh/io.cpp
- src/TMesh/triangle.cpp
- src/TMesh/tin.cpp
- src/Algorithms/detectIntersections.cpp
- src/Algorithms/holeFilling.cpp
- src/Algorithms/marchIntersections.cpp
- src/Algorithms/checkAndRepair.cpp
- src/Kernel/heap.cpp
- src/Kernel/matrix.cpp
- src/Kernel/orientation.c
- src/Kernel/list.cpp
- src/Kernel/coordinates.cpp
- src/Kernel/tmesh.cpp
- src/Kernel/graph.cpp
- src/Kernel/point.cpp
- src/Kernel/jqsort.cpp
-# src/MeshFix/meshfix.cpp
-)
-
-################################################################################
-
-add_library(meshfix ${SOURCES})
-
-target_include_directories(meshfix PUBLIC
- include/TMesh
- include/Kernel
-)
-
-################################################################################
diff --git a/src/mesh_fix/README.txt b/src/mesh_fix/README.txt
deleted file mode 100644
index 1a94b4701..000000000
--- a/src/mesh_fix/README.txt
+++ /dev/null
@@ -1,114 +0,0 @@
-This distribution of MeshFix-V2.1 library is only meant for interfacing MeshFix-V2.1 with Slic3rPE
-(https://github.com/prusa3d/PrusaSlicer).
-
-The MeshFix-V2.1 source file was acquired from https://github.com/MarcoAttene/MeshFix-V2.1 at revision
-e9399efd6954f6f38e19852226241839a4e1cd53.
-
-We did various changes and fixes to the original library:
- - removed void pointers, substituted with pointers to Data struct (with virtual destructor)
- - all structs stored previously in void ptr now inherit from the added Data struct
- - created double and int wrapper which inherits from Data
- - fixed detected unefined behaviours
- - fixed detected buffer over/underflows
-
-Many thanks to Marco Attene and other contributors.
-
-Pavel Mikus (pavel.mikus@prusa3d.cz)
-6.6.2022
-
-
-See original contents of the README file below.
-
-======================================================================================
-======================================================================================
-======================================================================================
-
-
-----------------------------
-MeshFIX - Version 2.1
-----------------------------
-
-by Marco Attene
-
-Consiglio Nazionale delle Ricerche
-Istituto di Matematica Applicata e Tecnologie Informatiche
-Sezione di Genova
-IMATI-GE / CNR
-
-This software takes as input a polygon mesh and produces a copy of the input where all the occurrences of a specific set of "defects" are corrected. MeshFix has been designed to correct typical flaws present in RAW DIGITIZED mesh models, thus it might fail or produce coarse results if run on other sorts of input meshes (e.g. tessellated CAD models). When the software fails, it appends a textual description to the file "meshfix.log".
-
-The input is assumed to represent a single CLOSED SOLID OBJECT, thus the output will be a SINGLE WATERTIGHT TRIANGLE MESH bounding a polyhedron. All the singularities, self-intersections and degenerate elements are removed from the input, while regions of the surface without defects are left unmodified. Accepted input file formats are:
-STL (http://www.sdsc.edu/tmf/Stl-specs/stl.html)
-OFF (http://shape.cs.princeton.edu/benchmark/documentation/off_format.html)
-PLY (http://www.cs.unc.edu/~geom/Powerplant/Ply.doc)
-and partially:
-IV 2.1, VRML 1.0, VRML 2.0, OBJ.
-
-
------------------------------
-ALGORITHM AND CITATION POLICY
------------------------------
-To better understand how the algorithm works, please refer to the following paper:
-
- M. Attene.
- A lightweight approach to repairing digitized polygon meshes.
- The Visual Computer, 2010. (c) Springer. DOI: 10.1007/s00371-010-0416-3
-
-This software is based on ideas published therein. If you use MeshFix for research purposes you should cite the above paper in your published results. MeshFix cannot be used for commercial purposes without a proper licensing contract.
-
-----------
-PARAMETERS
-----------
-The user may want to force the software to join the connected components [-a] whose boundary loops are closer to each other. Otherwise, only the largest component is kept while the others are considered as "noise". By default, the output file is in OFF format. The user may change this to STL [-j]. If the software is run as part of a script that processes all the files in a directory, the parameter [-x] may be useful to avoid to re-run the repairing of a mesh if its result already exists as a file.
-
--------------------
-COMMAND LINE SYNTAX
--------------------
-Run MeshFix without parameters to get the synopsis.
-
----------------------
-OTHER LAUNCHING MODES
----------------------
-A mesh can also be fixed my simply dragging its icon on MeshFix's icon. In this case, only default parameters can be used.
-MeshFix does not require any interaction, thus it can be inserted into a script to automatically repair all the models of a given repository (e.g. a folder). If some failure cases occur, they will be logged to "meshfix.log" and thus can be easily located and possibly processed is a second stage through interactive software tools such as ReMESH (http://remesh.sourceforge.net).
-
----------------------
-SOURCE CODE
----------------------
-
-From version 2.0 MeshFix is self-contained, that is, it does not depend on any other software.
-To compile the source code on Windows you need Microsoft Visual C++ 2013 or newer.
-Just click on vc12/MeshFix_All.sln and hit F7.
-The executable will be saved in bin/.
-
-Both 32bit and 64bit versions can be produced.
-
-The source code is standard ANSI C++ and should be portable.
-To compile on other configurations you may use CMake (thanks to Jeremie Dumas for having created the CMakeLists!).
-
-
----------
-Copyright
----------
-
-MeshFix is
-
-Copyright(C) 2010: IMATI-GE / CNR
-
-All rights reserved.
-
-This program is dual-licensed as follows:
-
-(1) You may use MeshFix as 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.
-In this case the 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 (http://www.gnu.org/licenses/gpl.txt)
-for more details.
-
-(2) You may use MeshFix as part of a commercial software. In this case a
-proper agreement must be reached with the Authors and with IMATI-GE/CNR
-based on a proper licensing contract.
\ No newline at end of file
diff --git a/src/mesh_fix/gpl-3.0.txt b/src/mesh_fix/gpl-3.0.txt
deleted file mode 100644
index 94a9ed024..000000000
--- a/src/mesh_fix/gpl-3.0.txt
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- 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.
-
-
- Copyright (C)
-
- 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 .
-
-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:
-
- Copyright (C)
- 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
-.
-
- 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
-.
diff --git a/src/mesh_fix/include/Kernel/basics.h b/src/mesh_fix/include/Kernel/basics.h
deleted file mode 100644
index 809f81b39..000000000
--- a/src/mesh_fix/include/Kernel/basics.h
+++ /dev/null
@@ -1,302 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef _BASICS_H
-#define _BASICS_H
-
-#include
-#include
-#include
-#include
-#include
-#include "coordinates.h"
-
-namespace T_MESH
-{
-
-#ifdef EXTENSIBLE_TMESH
-#define TMESH_VIRTUAL virtual
-#else
-#define TMESH_VIRTUAL
-#endif
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#define TMESH_VERSION "2.0"
-#define TMESH_YEAR 2012
-
-class TMesh
-{
- public:
-
- static void (*display_message)(const char *, int);
- static const char *app_name;
- static const char *app_version;
- static const char *app_year;
- static const char *app_authors;
- static const char *app_url;
- static const char *app_maillist;
-
- static const char *filename; // This might be null. If not, it represents the file we are currently working with.
-
- static bool quiet;
-
- static void init(void (*)(const char *, int) = NULL);
-
- static void info(const char *, ...);
- static void warning(const char *, ...);
- static void error(const char *, ...);
- static void begin_progress();
- static void report_progress(const char *, ...);
- static void end_progress();
-
- //! When called with a nonzero argument 'ts', launches a chronometer with a timeout of 'ts' seconds.
- //! Later calls without arguments check the chronometer, and if it is over 'ts' the program exits.
- static void exitOnTimeout(clock_t ts = 0);
-
- //! Appends a line to the file "tmesh.log"
- static void addMessageToLogFile(const char *msg);
-
- //! Formats a message headed with date/time/filename, appends it to "tmesh.log", and exits with error
- static void logToFileAndExit(const char *msg);
-
- //! When called without arguments prints the elapsed time from the latest reset.
- static void printElapsedTime(bool reset = false);
-
- static void useRationals(bool u);
- static bool isUsingRationals();
- static void useFiltering(bool u);
- static bool isUsingFiltering();
-
- //! Returns the status before the switch
- static bool useRationals() { bool t = isUsingRationals(); useRationals(true); return t; }
-
- static void setFilename(const char *fname) { filename = fname; }
-};
-
-#define DISPMSG_ACTION_SETWIDGET 1
-#define DISPMSG_ACTION_PUTNEWLINE 2
-#define DISPMSG_ACTION_PUTPROGRESS 3
-#define DISPMSG_ACTION_PUTMESSAGE 4
-#define DISPMSG_ACTION_ERRORDIALOG 5
-
-#ifndef _INC_WINDOWS
-typedef unsigned char UBYTE;
-typedef signed char BYTE;
-typedef unsigned short UINT16;
-typedef signed short INT16;
-#endif
-
-#define UBYTE_MAX 255
-
-#ifndef UINT16_MAX
-#define UINT16_MAX 65535
-#endif
-
-#define FABS(a) (((a)<0)?(-(a)):(a))
-#define LOG2(a) (log(a)/log(2))
-#define PI2 (M_PI/2.0)
-#ifndef MIN
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#endif
-#ifndef MAX
-#define MAX(a,b)(((a)>(b))?(a):(b))
-#endif
-
-//////// Swaps two pointers. ///////////////////////////////
-
-inline void p_swap(void **a, void **b) {void *t = *a; *a = *b; *b = t;}
-
-/////////////////////////////////////////////////////////////////////////////////////////////
-
-
-template
-class Primitive {
-protected:
- T value;
-
-public:
-
- // we must type cast to child to so
- // a += 3 += 5 ... and etc.. work the same way
- // as on primitives
- Child &childRef(){
- return *((Child*)this);
- }
-
- // you can overload to give a default value if you want
- Primitive(){}
- explicit Primitive(T v):value(v){}
-
- T get(){
- return value;
- }
-
- #define OP(op) Child &operator op(Child const &v){\
- value op v.value; \
- return childRef(); \
- }\
- Child &operator op(T const &v){\
- value op v; \
- return childRef(); \
- }
-
- // all with equals
- OP(+=)
- OP(-=)
- OP(*=)
- OP(/=)
- OP(<<=)
- OP(>>=)
- OP(|=)
- OP(^=)
- OP(&=)
- OP(%=)
-
- #undef OP
-
- #define OP(p) Child operator p(Child const &v){\
- Child other = childRef();\
- other p ## = v;\
- return other;\
- }\
- Child operator p(T const &v){\
- Child other = childRef();\
- other p ## = v;\
- return other;\
- }
-
- OP(+)
- OP(-)
- OP(*)
- OP(/)
- OP(<<)
- OP(>>)
- OP(|)
- OP(^)
- OP(&)
- OP(%)
-
- #undef OP
-
-
- #define OP(p) bool operator p(Child const &v){\
- return value p v.value;\
- }\
- bool operator p(T const &v){\
- return value p v;\
- }
-
- OP(&&)
- OP(||)
- OP(<)
- OP(<=)
- OP(>)
- OP(>=)
- OP(==)
- OP(!=)
-
- #undef OP
-
- Child operator +(){return Child(value);}
- Child operator -(){return Child(-value);}
- Child &operator ++(){++value; return childRef();}
- Child operator ++(int){
- Child ret(value);
- ++value;
- return childRef();
- }
- Child operator --(int){
- Child ret(value);
- --value;
- return childRef();
- }
-
- bool operator!(){return !value;}
- Child operator~(){return Child(~value);}
-
-};
-
-
-class Data {
-public:
- virtual ~Data() = default;
-};
-
-class intWrapper: public Data {
-private:
- int val;
- public:
- intWrapper(int val = 0) :
- val(val) {
- }
- operator int &() {
- return val;
- }
- int* operator &() {
- return &val;
- }
- operator int() const {
- return val;
- }
- operator int*() {
- return &val;
- }
-};
-
-class doubleWrapper: public Data, public Primitive {
-public:
- doubleWrapper(double val = 0) {
- this->value = val;
- }
- operator double &() {
- return value;
- }
- double* operator &() {
- return &value;
- }
- operator double() const {
- return value;
- }
- operator double*() {
- return &value;
- }
-};
-
-inline int to_int(Data *d) {
- return static_cast(d)->operator int();
-}
-
-} //namespace T_MESH
-
-#endif //_BASICS_H
-
diff --git a/src/mesh_fix/include/Kernel/coordinates.h b/src/mesh_fix/include/Kernel/coordinates.h
deleted file mode 100644
index d58d279c4..000000000
--- a/src/mesh_fix/include/Kernel/coordinates.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef _COORDINATES_H
-#define _COORDINATES_H
-
-#include
-#include
-#include
-#include
-
-#ifdef USE_HYBRID_KERNEL
-
-#ifdef USE_CGAL_LAZYNT
-#include
-#include
-#include
-
-typedef CGAL::Lazy_exact_nt EXACT_NT;
-#define EXACT_NT_TO_DOUBLE(x) (CGAL::to_double(x))
-#define EXACT_NT_DENOMINATOR(x) ((x)->exact().denominator())
-#define EXACT_NT_NUMERATOR(x) ((x)->exact().numerator())
-
-#else
-#include
-
-typedef mpq_class EXACT_NT;
-#define EXACT_NT_TO_DOUBLE(x) ((x).get_d())
-#define EXACT_NT_DENOMINATOR(x) ((x)->get_den())
-#define EXACT_NT_NUMERATOR(x) ((x)->get_num())
-
-#endif
-
-#endif
-
-#ifndef __APPLE__
-#include
-#endif
-
-namespace T_MESH
-{
-
-#ifdef USE_HYBRID_KERNEL
-class PM_Rational
- {
- private:
- // Only one of the following two static members can be true at any time, but both of them can be false
- // Thus, three configurations are possible:
- // 1) APPROXIMATED: use_rationals = false, use_filtering = false
- // 2) FILTERED: use_rationals = false, use_filtering = true
- // 3) PRECISE: use_rationals = true, use_filtering = false
- static bool use_rationals; // Kernel_mode uses rational numbers (precise)
- static bool use_filtering; // Kernel_mode uses filtering
-
- public:
- inline static bool isUsingRationals() { return use_rationals; }
- inline static bool isUsingFiltering() { return use_filtering; }
- static void useRationals(bool v) { use_rationals = v; use_filtering = !v; }
- static void useFiltering(bool v) { use_filtering = v; if (v) use_rationals = false; }
-
- protected:
- int64_t _val; // value. Might contain either a double or a pointer to mpq_class.
- bool _whv; // Which value type is stored here. 1=rational, 0=double
-
- inline bool isOfRationalType() const { return _whv; }
- inline bool isOfDoubleType() const { return !_whv; }
-
- inline static int64_t d2int64t(double a) { return *((int64_t *)((void *)(&a))); }
- inline static double& int64t2d(const int64_t& a) { return *((double *)((void *)(&a))); }
-
- inline EXACT_NT& getVal() { return *((EXACT_NT *)_val); }
- inline double& getDVal() { return int64t2d(_val); }
-
- inline const EXACT_NT& getVal() const { return *((EXACT_NT *)_val); }
- inline const double& getDVal() const { return int64t2d(_val); }
-
- void switchToDouble();
- void switchToRational();
-
- public:
- PM_Rational() : _whv(0) {} // Undetermined double
- PM_Rational(const EXACT_NT& a) { _whv = use_rationals; _val = (_whv) ? ((int64_t)new EXACT_NT(a)) : (d2int64t(EXACT_NT_TO_DOUBLE(a))); }
- PM_Rational(float a) { _whv = use_rationals; _val = (_whv) ? ((int64_t)new EXACT_NT(a)) : (d2int64t(a)); }
- PM_Rational(double a) { _whv = use_rationals; _val = (_whv) ? ((int64_t)new EXACT_NT(a)) : (d2int64t(a)); }
- PM_Rational(int a) { _whv = use_rationals; _val = (_whv) ? ((int64_t)new EXACT_NT(a)) : (d2int64t(a)); }
-
- PM_Rational(const PM_Rational& a) { _whv = a._whv; _val = (_whv) ? ((int64_t)new EXACT_NT(a.getVal())) : (a._val); }
- ~PM_Rational() { if (_whv) delete ((EXACT_NT *)_val); }
-
- inline EXACT_NT toRational() const { return (_whv) ? (getVal()) : (EXACT_NT(getDVal())); }
-
- // The following toSomething() functions may cause rounding. Use with caution !
- inline double toDouble() const { return ((_whv) ? (EXACT_NT_TO_DOUBLE(getVal())) : (getDVal())); }
- inline int toInt() const { return int(toDouble()); }
- inline float toFloat() const { return float(toDouble()); }
-
- void operator+=(const PM_Rational& a);
- void operator-=(const PM_Rational& a);
- void operator*=(const PM_Rational& a);
- void operator/=(const PM_Rational& a);
- PM_Rational operator+(const PM_Rational& a) const;
- PM_Rational operator-(const PM_Rational& a) const;
- PM_Rational operator*(const PM_Rational& a) const;
- PM_Rational operator/(const PM_Rational& a) const;
- bool operator==(const PM_Rational& a) const;
- bool operator!=(const PM_Rational& a) const;
-
- PM_Rational& operator=(const PM_Rational& a);
- void setFromRational(const EXACT_NT& a);
-
- bool operator<(const PM_Rational& a) const;
- bool operator>(const PM_Rational& a) const;
- inline bool operator<=(const PM_Rational& a) const { return (operator==(a) || operator<(a)); }
- inline bool operator>=(const PM_Rational& a) const { return (operator==(a) || operator>(a)); }
-
- friend PM_Rational orient2D(const PM_Rational& px, const PM_Rational& py, const PM_Rational& qx, const PM_Rational& qy, const PM_Rational& rx, const PM_Rational& ry);
- friend PM_Rational orient3D(const class Point *t, const class Point *a, const class Point *b, const class Point *c);
-};
-
-PM_Rational operator-(const PM_Rational& a);
-PM_Rational ceil(const PM_Rational& a);
-PM_Rational floor(const PM_Rational& a);
-PM_Rational round(const PM_Rational& a);
-
-/**************** I/O operators ****************/
-
-inline std::ostream & operator<<(std::ostream &o, const PM_Rational& c) { return o << c.toRational(); }
-inline std::istream & operator>>(std::istream &i, PM_Rational& c) { EXACT_NT a; i >> a; c.setFromRational(a); return i; }
-
-#define TMESH_TO_DOUBLE(x) ((x).toDouble())
-#define TMESH_TO_FLOAT(x) ((x).toFloat())
-#define TMESH_TO_INT(x) ((x).toInt())
-
-#else
-
-typedef double PM_Rational;
-
-#define TMESH_TO_DOUBLE(x) (x)
-#define TMESH_TO_FLOAT(x) ((float)(x))
-#define TMESH_TO_INT(x) ((int)(x))
-
-#endif
-
-typedef PM_Rational coord;
-
-#define TMESH_DETERMINANT3X3(a11, a12, a13, a21, a22, a23, a31, a32, a33) ((a11)*((a22)*(a33) - (a23)*(a32)) - (a12)*((a21)*(a33) - (a23)*(a31)) + (a13)*((a21)*(a32) - (a22)*(a31)))
-
-} //namespace T_MESH
-
-#endif //_COORDINATES_H
-
diff --git a/src/mesh_fix/include/Kernel/graph.h b/src/mesh_fix/include/Kernel/graph.h
deleted file mode 100644
index 2fcd1f596..000000000
--- a/src/mesh_fix/include/Kernel/graph.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef _GRAPH_H
-#define _GRAPH_H
-
-#include "list.h"
-#include "basics.h"
-
-namespace T_MESH
-{
-
-//! Base class type for nodes of non-oriented graphs
-
-class graphNode : public Data
-{
- public:
-
- //! List of incident edges.
- List edges;
-
- //! Generic 8-bit mask for marking purposes.
- unsigned char mask;
-
- graphNode() {mask=0;}
- TMESH_VIRTUAL ~graphNode() {}
-
- //! Returns TRUE if the node is isolated. O(1).
- bool isIsolated() {return (edges.numels()==0);}
-
- //! Returns the edge connecting this with 'n'. NULL if not connected. O(degree).
- class graphEdge *getEdge(graphNode *n);
-};
-
-
-//! Base class type for edges of non-oriented graphs
-
-class graphEdge : public Data
-{
- public:
-
- //! Edge's end-points
- graphNode *n1, *n2;
-
- //! Generic info attached to the edge
- void *info;
-
- //! Generic 8-bit mask for marking purposes.
- unsigned char mask;
-
- //! Constructor.
- graphEdge(graphNode *, graphNode *);
- TMESH_VIRTUAL ~graphEdge() {}
-
- //! Returns the node oppsite to 'n'. O(1).
- graphNode *oppositeNode(graphNode *n) {return (n1==n)?(n2):((n2==n)?(n1):(NULL));}
-
- //! Returns TRUE if this edge does not connect points. O(1).
- bool isUnlinked() {return (n1==NULL);}
-
- //! Returns TRUE if 'n' is a node of this edge. O(1).
- bool hasNode(graphNode *n) {return (n1==n || n2==n);}
-
- //! Makes this edge as 'unlinked' from the graph. O(1).
- void makeUnlinked() {n1=NULL; n2=NULL;}
-
- //! Edge collapse. O(degree of neighbors).
-
- //! After one (or a series of) collapse, remember to call Graph::deleteUnlinkedElements()
- //! to make the graph coherent with its node and edge lists.
- void collapse();
-
- //! Inverts the edge's orientation
- void invert();
-};
-
-
-//! Base class type for non oriented graphs
-
-class Graph
-{
- public:
-
- //! Nodes and edges of the graph.
- List nodes, edges;
-
- ~Graph();
-
- //! Adds an existing isolated node to the graph. O(1).
- graphNode *addNode(graphNode *n) {nodes.appendHead(n); return n;}
-
- //! Creates a new edge out of a pair of nodes. O(degree of nodes).
-
- //! If the edges already exists, no new edge is created and the
- //! existing one is returned. Otherwise the newly created edge is returned.
- graphEdge *createEdge(graphNode *n1, graphNode *n2);
-
- //! Unlinks the edge and updates the graph connectivity accordingly.
- void unlinkEdge(graphEdge *e);
-
- //! Removes and deletes the edge. Updates the graph connectivity accordingly.
- void destroyEdge(graphEdge *e);
-
- //! Removes a node and updates the graph connectivity accordingly.
- //! The unlinked node is returned.
- graphNode *unlinkNode(graphNode *n);
-
- //! Eliminates isolated nodes and unlinked edges from the lists. O(N).
- //! The eliminated elements are deleted too.
- void deleteUnlinkedElements();
-
-
- bool isConnected();
-};
-
-} //namespace T_MESH
-
-#endif // _GRAPH_H
diff --git a/src/mesh_fix/include/Kernel/heap.h b/src/mesh_fix/include/Kernel/heap.h
deleted file mode 100644
index 4768089bf..000000000
--- a/src/mesh_fix/include/Kernel/heap.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef _HEAP_H
-#define _HEAP_H
-
-#include "basics.h"
-
-namespace T_MESH
-{
-
-//! Heap base class type.
-
-//! abstractHeap is the base class for implementing heaps.
-//! Each implementation (class extension) must define the method
-//! compare to be used for sorting the heap. If the objects being
-//! sorted are non-negative numbers, a special implementation may
-//! use the field positions to record the index of each element
-//! within the heap. This feature is useful when there is a need to
-//! re-sort an element whose cost changes after its insertion into
-//! the heap. The array 'positions' must be allocated by
-//! the extended class constructor, and must be able to contain NMAX+1
-//! integer numbers, where NMAX is the maximum value that can be
-//! assumed by an object.
-
-
-class abstractHeap
-{
- protected:
- Data **heap; //!< Heap data is stored here
- int numels; //!< Current number of elements
- int maxels; //!< Maximum number of elements
- int *positions; //!< Optional pointer to an array of positions
-
- int upheap(int i); //!< Moves the i'th object up on the heap
- int downheap(int i); //!< Moves the i'th object down on the heap
-
- //! Comparison of two heap elements
-
- //! This function must be implemented in the extended class.
- //! The return value must be <0 if a0 if a>b or 0 if a=b.
-
- virtual int compare(const Data *a, const Data *b) = 0;
-
- public :
-
- abstractHeap(int n); //!< Creates a heap which can contain up to 'n' elements
- virtual ~abstractHeap() = 0; //!< Default destructor
-
- //! Inserts 'e' into the heap
-
- //! Inserts an element 'e' into the heap in the correct position, according to the
- //! method compare. If the insertion fails because the heap is full, -1 is
- //! returned, otherwise the index position of the newly inserted element is
- //! returned.
-
- int insert(Data *e);
-
- int isEmpty() const {return (numels == 0);} //!< Returns TRUE if the heap is empty
- Data *getHead() const {return heap[1];} //!< Returns the first element of the heap
- Data *removeHead(); //!< Removes and returns the first element after rearranging the heap
- void flush() {numels=0;} //!< Removes all the elements
-};
-
-} //namespace T_MESH
-
-#endif // _HEAP_H
diff --git a/src/mesh_fix/include/Kernel/jqsort.h b/src/mesh_fix/include/Kernel/jqsort.h
deleted file mode 100644
index 57b4cc046..000000000
--- a/src/mesh_fix/include/Kernel/jqsort.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-//! \file
-//! \brief Declaration of a generic QuickSort function.
-//!
-//! The jqsort() function sorts an array with numels elements.
-//! The v argument points to the start of the array of elements casted to void *.
-//! The contents of the array are sorted in ascending order according to a
-//! comparison function pointed to by comp, which is called with two
-//! arguments that point to the objects being compared.
-//! The comparison function must return an integer less than, equal to, or
-//! greater than zero if the first argument is considered to be respectively
-//! less than, equal to, or greater than the second. If two members
-//! compare as equal, their order in the sorted array is undefined.
-//! See the manpage of the standard library qsort() function for further information.
-
-namespace T_MESH
-{
-
-extern void jqsort(Data *v[], int numels, int (*comp)(const Data *, const Data *));
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/include/Kernel/list.h b/src/mesh_fix/include/Kernel/list.h
deleted file mode 100644
index ba2c77d72..000000000
--- a/src/mesh_fix/include/Kernel/list.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef _JLIST_H
-#define _JLIST_H
-
-#include
-#include "basics.h"
-
-namespace T_MESH
-{
-
-/////////////////////////////////////////////////////////////////////////////////////////////
-
-//! Generic node of a doubly likned list.
-
-class Node
-{
- friend class List; // This is to make methods in 'List' able to modify n_prev and n_next
-
- public :
- Data *data; //!< Actual data stored in the node
-
- //! Creates an isolated node storing 'd'
- Node(const void *d) {data=(Data *)d; n_prev=n_next=NULL;}
-
- //! Creates a new node storing 'd' and links it to a previous node 'p' and to a next one 'n'.
- Node(const Node *p, const Data *d, const Node *n);
- ~Node(); //!< Standard destructor
-
- inline Node *prev() const {return n_prev;} //!< Returns the previous node in the list, possibly NULL
- inline Node *next() const {return n_next;} //!< Returns the next node in the list, possibly NULL
-
- protected:
- Node *n_prev,*n_next; //!< Previous and next node pointers
-};
-
-
-/////////////////////////////////////////////////////////////////////////////////////////////
-
-//! Doubly linked list.
-
-
-class List : public Data
-{
- protected :
-
- Node *l_head; //!< First node pointer
- Node *l_tail; //!< Last node pointer
- int l_numels; //!< Number of elements in the list
-
- public :
-
- //! Creates an empty list
- List() {l_head = l_tail = NULL; l_numels = 0;}
-
- //! Creates a list containing an element 'd' (singleton)
- List(const Data *d) {l_head = l_tail = new Node(d); l_numels = 1;}
-
- //! Creates a list out of an array 'd' made of 'n' elements.
- List(const Data **d, int n);
-
- //! Creates a duplicated list.
- List(List& l) {l_head = l_tail = NULL; l_numels = 0; appendList(&l);}
-
- //! Creates a duplicated list.
- List(List* l) {l_head = l_tail = NULL; l_numels = 0; appendList(l);}
-
- //! Destructor
- ~List();
-
- Node *head() const {return l_head;} //!< Gets the first node, NULL if empty. \n O(1).
- Node *tail() const {return l_tail;} //!< Gets the last node, NULL if empty. \n O(1).
- int numels() const {return l_numels;} //!< Gets the number of elements. \n O(1).
-
- void appendHead(const Data *d); //!< Appends a new node storing 'd' to the head. \n O(1).
- void appendTail(const Data *d); //!< Appends a new node storing 'd' to the tail. \n O(1).
- void insertAfter(Node *n, const Data *d); //! Inserts a new node storing 'd' right after 'n'. \n O(1).
-
- //! Deletes and removes the node containing 'd'. Returns its position, 0 if 'd' is not in the list. \n O(numels()).
- int removeNode(const Data *d);
-
- //! Deletes and i'th node (starting from 0). Returns 0 if the list has less than i+1 nodes. \n O(numels()).
- int removeNode(int i);
-
- //! Returns the node at position 'i' (starting from 0). Returns NULL if the list has less than i+1 nodes. \n O(numels()).
- Node *getNode(int i) const;
-
- //! Deletes and removes the node 'n' from the list. \n O(1).
- void removeCell(Node *n);
-
- //! Appends a list 'l' to the head by duplicating nodes in 'l'. \n O(l->numels()).
- void appendList(const List *l);
-
- //! Appends a list 'l' to the tail by linking the first node of 'l' to the last one of this list. 'l' becomes empty. \n O(1).
- void joinTailList(List *l);
-
- //! Moves node 'n' from this list to the end of 'l'. \n O(1).
- void moveNodeTo(Node *n, List *l);
-
- Data *popHead(); //!< Deletes and removes the first node. Returns its data. \n O(1).
- Data *popTail(); //!< Deletes and removes the last node. Returns its data. \n O(1).
-
- //! Deletes and removes the node 'n' from the list and frees data memory. \n O(1).
-
- // NOTE: The following is not true after refactoring, void* has been replaced with Data*
- //! Warning. This method uses the free() function to to dispose the memory space
- //! used by the data stored in the node. This means that such data should have
- //! been allocated through malloc(), calloc() or realloc(), and not through the
- //! 'new' operator. On some systems, however, the 'delete' operator simply calls 'free()'
- //! right after the execution of the proper object destructor so, if the object
- //! does not need to free internally allocated memory, it is safe to dispose the
- //! memory trhough free() although the object was allocated by 'new'. This works
- //! on Linux Fedora Core 2 distributions.
- void freeCell(Node *n);
-
- //! Deletes and removes the node storing 'd' and frees the memory occupied by 'd' itself. \n O(numels()).
-
- //! Warning. Read the comment for the method 'freeCell()'
- void freeNode(Data *d);
-
- //! Returns the node storing 'd'. NULL if not found. \n O(numels()).
- Node *containsNode(const Data *d) const;
-
- //! Replaces old_n with new_n. The Node containing new_n is returned. \n O(numels()).
- Node *replaceNode(const Data *old_n, const Data *new_n);
-
- //! Deletes and removes all the nodes and frees data memory. \n O(numels()).
-
- //! Warning. Read the comment for the method 'freeCell()'
- void freeNodes();
-
- void removeNodes(); //!< Deletes and removes all the nodes. \n O(numels()).
-
- Data **toArray() const; //!< Creates an array out of the list. \n O(numels()).
-
- //! Sorts the list using 'comp' as comparison function for two elements. \n O(numels()^2).
-
- //! This method uses the QuickSort algorithm for sorting, thus the complexity is N^2 in the
- //! worst case, but it is actually much faster in the average case. If, however, there is
- //! the need to have a guaranteed O(NlogN) complexity, it is possible to implement a heap
- //! based on the 'abstractHeap' class. See the documentation of the standard 'qsort' library
- //! function for details on the prototype of the comparison function 'comp'.
- int sort(int (*comp)(const Data *, const Data *));
-};
-
-//! Convenience macro to scan the nodes of a list.
-#define FOREACHNODE(l, n) for ((n) = (l).head(); (n) != NULL; (n)=(n)->next())
-
-//! Convenience macro to circulate around the nodes of a list 'l' starting from node 'm'. Must exit with break or return.
-#define FOREACHNODECIRCULAR(l, m, n) for ((n) = (m); ; (n)=((n)!=(l).tail())?((n)->next()):((l).head()))
-
-} //namespace T_MESH
-
-#endif // _JLIST_H
-
diff --git a/src/mesh_fix/include/Kernel/matrix.h b/src/mesh_fix/include/Kernel/matrix.h
deleted file mode 100644
index 3bd222399..000000000
--- a/src/mesh_fix/include/Kernel/matrix.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef MATRIX_H
-#define MATRIX_H
-
-#include
-#include
-#include "coordinates.h"
-#include "list.h"
-
-namespace T_MESH
-{
-
-//////////////////////////////////////////////////////////////////////////
-//
-// Generic 3x3 matrix
-//
-//////////////////////////////////////////////////////////////////////////
-
-//! Generic 3x3 matrix.
-
-//! Elements are stored in a row-dominant order, thus
-//! for example, M[4] is the first element of the second row.
-
-class Matrix3x3
-{
- public:
- double M[9]; //!< Actual values of the matrix
-
- Matrix3x3() {M[0]=M[1]=M[2]=M[3]=M[4]=M[5]=M[6]=M[7]=M[8]=0.0;} //!< Contructs a null matrix
-
- //! Constructs a fully initialized matrix.
- Matrix3x3(const double& a11, const double& a12, const double& a13,
- const double& a21, const double& a22, const double& a23,
- const double& a31, const double& a32, const double& a33);
-
- //! Constructs a 3x3 matrix as the product of Transpose(v1,v2,v3) and (w1,w2,w3).
- Matrix3x3(const double& v1, const double& v2, const double& v3,
- const double& w1, const double& w2, const double& w3);
-
- //! Constructs a 3x3 matrix as the product of Transpose(a,b,c) and (a,b,c).
- Matrix3x3(const double& a, const double& b, const double& c);
-
- //! Returns TRUE if the matrix is symmetric
- bool isSymmetric() const {return (M[2]==M[4] && M[3]==M[7] && M[6]==M[8]);}
-
-
- //! Initializes all elements to 'd'
- void operator=(const double& d) {M[0]=M[1]=M[2]=M[3]=M[4]=M[5]=M[6]=M[7]=M[8]=d;}
-
- void operator+=(const Matrix3x3&); //!< Sum another matrix
- void operator-=(const Matrix3x3&); //!< Subtract another matrix
- void operator*=(const double&); //!< Multiply by a scalar
- void operator/=(const double& d) {operator *=(1.0/d);} //!< Divide by a scalar
- Matrix3x3 operator+(const Matrix3x3&) const; //!< Returns the sum of this and another matrix
- Matrix3x3 operator*(const double&) const; //!< Returns the product of this matrix with a scalar
- Matrix3x3 operator*(const Matrix3x3&) const; //!< Returns the product of this and another matrix (rows by columns)
- Matrix3x3 operator~() const; //!< Returns the transpose of this matrix
-
- //! Return the matrix transpose
- Matrix3x3 transpose() const;
-
- //! Returns Transpose(a,b,c)*M*(a,b,c)
-
- //! Returns the (scalar) result of multiplying the matrix on
- //! the left and on the right by the vector (a,b,c).
- double lrMultiply(const double& a, const double& b, const double& c) const;
-
- //! Returns the (scalar) result of v*M*w
- double lrMultiply(const double& v1, const double& v2, const double& v3,
- const double& w1, const double& w2, const double& w3) const;
-};
-
-
-//////////////////////////////////////////////////////////////////////////
-//
-// Symmetric 3x3 matrix
-//
-//////////////////////////////////////////////////////////////////////////
-
-//! Symmetric 3x3 matrix
-
-//! Compact storage: \n
-//! M[0] M[1] M[3] \n
-//! M[1] M[2] M[4] \n
-//! M[3] M[4] M[5] \n
-
-class SymMatrix3x3
-{
- public:
- double M[6]; //!< Actual values of the matrix
-
- SymMatrix3x3() {M[0]=M[1]=M[2]=M[3]=M[4]=M[5]=0.0;} //!< Constructs a null matrix.
-
- //! Constructs a fully initialized matrix.
- SymMatrix3x3(const double&a11, const double&a12, const double&a22,
- const double&a13, const double&a23, const double&a33);
-
- //! Constructs a symmetric matrix as the product of Transpose(a,b,c) and (a,b,c).
- SymMatrix3x3(const double& a, const double& b, const double& c);
-
- //! Constructs a symmetric 3x3 matrix as a copy of an existing 3x3 matrix S.
-
- //! If 'S' is not symmetric, its upper triangular part is reflected to the lower.
-
- SymMatrix3x3(const Matrix3x3& S);
-
- bool operator==(const SymMatrix3x3& s) //!< True iff all entries are equal
- {return (M[0]==s.M[0] && M[1]==s.M[1] && M[2]==s.M[2] && M[3]==s.M[3] && M[4]==s.M[4] && M[5]==s.M[5]);}
- bool operator!=(const SymMatrix3x3& s) //!< True iff at least one different entry
- {return (M[0]!=s.M[0] || M[1]!=s.M[1] || M[2]!=s.M[2] || M[3]!=s.M[3] || M[4]!=s.M[4] || M[5]!=s.M[5]);}
-
- void operator+=(const SymMatrix3x3&); //!< Sum another matrix
- void operator-=(const SymMatrix3x3&); //!< Subtract another matrix
- void operator*=(const double&); //!< Multiply by a scalar
- void operator/=(const double& d) {operator *=(1.0/d);} //!< Divide by a scalar
- SymMatrix3x3 operator+(const SymMatrix3x3&) const; //!< Returns the sum of this and another matrix
- SymMatrix3x3 operator*(const double&) const; //!< Returns the product of this matrix with a scalar
-
- //! Initializes all elements to 'd'
- void operator=(const double& d) {M[0]=M[1]=M[2]=M[3]=M[4]=M[5]=d;}
-
- //! Returns the determinant
- double determinant() const {return (M[0]*M[2]*M[5])+(2.0*M[1]*M[3]*M[4])-(M[0]*M[4]*M[4])-(M[2]*M[3]*M[3])-(M[5]*M[1]*M[1]);}
-
- //! Returns TRUE iff the matrix is made of all zeroes.
- bool isNull() const {return (M[0]==0 && M[1]==0 && M[2]==0 && M[3]==0 && M[4]==0 && M[5]==0);}
-
- //! Returns Transpose(a,b,c)*M*(a,b,c)
-
- //! Returns the (scalar) result of multiplying the matrix on
- //! the left and on the right by the vector (a,b,c).
- double lrMultiply(const double& a, const double& b, const double& c) const;
-
-
- //! Returns the (scalar) result of v*M*w
- double lrMultiply(const double& v1, const double& v2, const double& v3,
- const double& w1, const double& w2, const double& w3) const;
-
- bool invert(); //!< Inverts this matrix. Returns FALSE if not invertible, TRUE otherwise
-
- //! Returns the matrix trace
- double trace() const {return M[0]+M[2]+M[5];}
-
- //! Compute eigenvalues and eigenvectors of the matrix (Jacobi method).
-
- //! The calling function is responsible of verifying that the matrix
- //! is diagonalizable. Also, eigen_vals and eigen_vecs must be allocated
- //! prior to calling this method.\n
- //! eigen_vals are sorted in ascending order (i.e., eigen_vals[0] is the smallest one).\n
- //! eigen_vecs are sorted accordingly to the order of eigen_vals, that is,
- //! (eigen_vecs[0], eigen_vecs[1], eigen_vecs[2]) is the eigenvector corresponding to
- //! eigen_vals[0].
- void diagonalize(double eigen_vals[3], double eigen_vecs[9]) const;
-
- //! Compute the eigenvalues l1, l2 and l3.
-
- //! This method is much faster and precise than 'diagonalize', as it uses
- //! an analytical direct method instead of an iterative approach.
- void getEigenvalues(double *l1, double *l2, double *l3) const;
-
- //! Compute the eigenvector (a,b,c) corresponding to the minimum eigenvalue.
-
- //! This method is much faster and precise than 'diagonalize', as it uses
- //! an analytical direct method instead of an iterative approach.
- //! Returns the corresponding eigenvalue
- double getMinEigenvector(double *a, double *b, double *c) const;
-
- //! This method is much faster and precise than 'diagonalize', as it uses
- //! an analytical direct method instead of an iterative approach.
- void getMaxEigenvector(double *a, double *b, double *c) const;
-
- //! Prints the contents of the matrix to the specified FILE id.
-
- //! If no 'id' is specifyed, results are printed to stdout.
-
- void print(FILE *id =stdout) const;
-};
-
-
-//////////////////////////////////////////////////////////////////////////
-//
-// Symmetric 4x4 matrix
-//
-//////////////////////////////////////////////////////////////////////////
-
-//! Symmetric 4x4 matrix.
-
-//! Compact storage: \n
-//! a2 ab ac ad \n
-//! ab b2 bc bd \n
-//! ac bc c2 cd \n
-//! ad bd cd d2 \n
-
-class SymMatrix4x4
-{
- public:
- coord a2,ab,ac,ad,b2,bc,bd,c2,cd,d2; //!< Actual matrix coeffs.
-
- SymMatrix4x4() {a2=ab=ac=ad=b2=bc=bd=c2=cd=d2=0;} //!< Constructs a null matrix
-
- //! Extend a 3x3 symmetric matrix to homogeneous coordinates (ad=bd=cd=0 and d2=1).
- SymMatrix4x4(const SymMatrix3x3&);
-
- //! Quadric (a,b,c,d)*Transpose(a,b,c,d)
- SymMatrix4x4(const coord& a, const coord& b, const coord& c, const coord& d);
-
- bool operator==(const SymMatrix4x4&); //!< True iff equal
- bool operator!=(const SymMatrix4x4&); //!< True iff not equal
-
- void operator+=(const SymMatrix4x4&); //!< Sum another matrix
- SymMatrix4x4 operator+(const SymMatrix4x4&) const; //!< Returns the sum of this and another matrix
- SymMatrix4x4 operator*(const coord&) const; //!< Returns the product of this matrix by a scalar
-
- //! Adds the quadric (a,b,c,d)*Transpose(a,b,c,d)
- void add(const coord& a, const coord& b, const coord& c, const coord& d);
-
- //! Returns Transpose(a,b,c,d)*M*(a,b,c,d)
-
- //! Returns the (scalar) result of multiplying the matrix on
- //! the left and on the right by the vector (a,b,c,d).
- coord lrMultiply(const coord& a, const coord& b, const coord& c, const coord& d) const;
-
- //! \brief Computes the vector (a,b,c) that minimizes the quantity lrMultiply(a,b,c,1).
- //! Returns FALSE if such a vector is not unique.
- bool getMinimizer(coord *a, coord *b, coord *c) const;
-
- bool invert(); //!< Inverts this matrix. Returns FALSE if not invertible, TRUE otherwise
-};
-
-
-//////////////////////////////////////////////////////////////////////////
-//
-// Generic 4x4 matrix
-//
-//////////////////////////////////////////////////////////////////////////
-
-//! Generic 4x4 matrix.
-
-class Matrix4x4
-{
- public:
- double matrix[4][4]; //!< Actual matrix coefficients
-
- //! Constructs an undefined matrix
- Matrix4x4();
-
- //! Constructs a diagonal matrix with 'd' values on the diagonal
- Matrix4x4(const double& d);
-
- //! Constructs a fully initialized matrix (parameters are in row dominant order M[0][0], M[0][1], ...).
- Matrix4x4(
- const double&, const double&, const double&, const double&,
- const double&, const double&, const double&, const double&,
- const double&, const double&, const double&, const double&,
- const double&, const double&, const double&, const double&
- );
-
- //! Rotation matrix from a quaternion
- void setRotation(const double &, const double&, const double&, const double&);
-
- //! Translation matrix from a vector
- void setTranslation(const double &, const double&, const double&);
-
- Matrix4x4 operator*(const Matrix4x4&) const; //!< Returns the product of this and another matrix (rows by columns)
-
- void transform(double *, double *, double *); //! Transform the vector by left-multiplication with the matrix
-};
-
-} //namespace T_MESH
-
-#endif // MATRIX_H
-
diff --git a/src/mesh_fix/include/Kernel/point.h b/src/mesh_fix/include/Kernel/point.h
deleted file mode 100644
index c35dbcb38..000000000
--- a/src/mesh_fix/include/Kernel/point.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef _POINT_H
-#define _POINT_H
-
-#include "basics.h"
-
-namespace T_MESH
-{
-
-//! Orientation predicates using filtering on doubles
-extern "C" double orient2d(double *, double *, double *);
-extern "C" double orient3d(double *, double *, double *, double *);
-
-//! Orientation predicates on PM_Rationals
-
-// orient2D: >0 =0 <0 if (p,q,r) are CCW, aligned, CW respectively
-PM_Rational orient2D(const PM_Rational& px, const PM_Rational& py, const PM_Rational& qx, const PM_Rational& qy, const PM_Rational& rx, const PM_Rational& ry);
-
-
-//! Geometric point definition
-
-//! This class represents a point in the Euclidean 3D space. It can be used
-//! to represent 3D vectors originating at (0,0,0) and terminating at the
-//! corresponding point. Several methods of this class are intended to
-//! manipulate vectors rather than points; for example, a call of the
-//! method normalize is an actual normalization if the object is a vector,
-//! but it has to be intended as a projection on the unit sphere if the
-//! object is intended to be a point. An object of type Point is a triplet
-//! (x,y,z) of coordinates endowed with a pointer 'info' to possible additional
-//! information. Each coordinate is a number of type 'coord' which, by
-//! default, is a standard double. Operations on points include addition,
-//! subtraction, cross and dot product, and many others. This class implements
-//! several useful operations using vector arithmethic. For example,
-//! the simple piece of code "A = B*C;" assignes to A the value of the dot
-//! product of B and C.
-//! Nearly zero or nearly flat angles are automatically snapped to
-//! exactly zero and exactly flat angles if the difference is smaller
-//! than the global variable _acos_tolerance. This is the very basic application
-//! of our version of the epsilon geometry for robust computation.
-
-
-class Point : public Data
-{
- public :
- coord x,y,z; //!< Coordinates
- Data *info; //!< Further information
-
- //! Creates a new point with coordinates (0,0,0).
- Point() {x = y = z = 0; info = NULL;}
-
- //! Creates a new point with the same coordinates as 's'. The info field is not copied.
- Point(const Point *s) {x = s->x; y = s->y; z = s->z; info = NULL;}
-
- //! Creates a new point with the same coordinates as 's'. The info field is not copied.
- Point(const Point& s) {x = s.x; y = s.y; z = s.z; info = NULL;}
-
- //! Creates a new point with coordinates (a,b,c).
- Point(const coord& a, const coord& b, const coord& c) {x = a; y = b; z = c; info = NULL;}
-
- //! Do not remove this. It makes the compiler produce a vtable for this object.
- TMESH_VIRTUAL bool isPoint() const { return true; }
-
- //! Set the coordinates to (a,b,c).
- void setValue(const coord& a, const coord& b, const coord& c) {x = a; y = b; z = c;}
-
- //! Set the coordinates as those of 'p'
- void setValue(const Point& p) {x = p.x; y = p.y; z = p.z;}
-
- //! Set the coordinates as those of '*p'
- void setValue(const Point *p) {x = p->x; y = p->y; z = p->z;}
-
- //! Returns the vector difference
- Point operator-(const Point& p) const {return Point(x-p.x, y-p.y, z-p.z);}
-
- //! Returns the vector sum
- Point operator+(const Point& p) const {return Point(x+p.x, y+p.y, z+p.z);}
-
- //! Sums another point
- void operator+=(const Point& p) {x+=p.x; y+=p.y; z+=p.z;}
-
- //! Subtracts another point
- void operator-=(const Point& p) {x-=p.x; y-=p.y; z-=p.z;}
-
- //! Returns the Cross Product
- Point operator&(const Point& p) const {return Point(y*p.z-z*p.y, z*p.x-x*p.z, x*p.y-y*p.x);}
-
- //! Returns the Dot Product
- coord operator*(const Point& p) const {return (x*p.x+y*p.y+z*p.z);}
-
- //! Returns the product with a scalar
- Point operator*(const coord& d) const {return Point(x*d,y*d,z*d);}
-
- //! Multiplies by a scalar
- void operator*=(const coord& m) { x *= m; y *= m; z *= m; }
-
- //! Divides by a scalar
- void operator/=(const coord& m) { x /= m; y /= m; z /= m; }
-
- //! Returns the vector divided by the scalar
- Point operator/(const coord& d) const { return Point(x / d, y / d, z / d); }
-
- //! TRUE iff coordinates are equal
- bool operator==(const Point& p) const {return (x==p.x && y==p.y && z==p.z);}
-
- //! FALSE iff coordinates are equal
- bool operator!=(const Point& p) const {return (x!=p.x || y!=p.y || z!=p.z);}
-
- //! TRUE iff this is lexycographically smaller than s
- bool operator<(const Point& s) const;
-
- //! Returns the i'th coordinate
- inline coord& at(unsigned char i) { return (i == 0) ? (x) : ((i == 1) ? (y) : (z)); }
-
- //! Returns the i'th coordinate
- inline coord& operator[](unsigned char i) { return (i == 0) ? (x) : ((i == 1) ? (y) : (z)); }
-
- //! Returns the inverse vector
- Point inverse() const {return Point(-x,-y,-z);}
-
- //! Inverts the vector
- void invert() {x=-x; y=-y; z=-z;}
-
- //! TRUE if vector is (0,0,0)
- bool isNull() const {return (x==0 && y==0 && z==0);}
-
- //! Squared distance from origin
- coord squaredLength() const {return (x*x + y*y + z*z);}
-
- //! Squared distance from '*b'
- coord squaredDistance(const Point *b) const { return (((*(this)) - (*b)).squaredLength()); }
-
- //! Returns the solution of the linear system Ax = d, where A is a 3x3 matrix whose rows are row1, row2 and row3, d = this
- Point linearSystem(const Point& row1, const Point& row2, const Point& row3);
-
-
- //! Projects the vector on the plane with normal 'n' passing through the origin.
- void project(const Point *n);
-
- //! Returns the projection of the point on the straight line though 'a' and 'b'.
- Point projection(const Point *a, const Point *b) const;
-
- //! Prints the coordinates of the point to a file handler. stdout is the default.
- void printPoint(FILE *fp = stdout) const { fprintf(fp, "%f %f %f,\n", TMESH_TO_FLOAT(x), TMESH_TO_FLOAT(y), TMESH_TO_FLOAT(z)); } // Debug
-
-
- //! Exact orientation test.
- //! Return value is positive iff the tetrahedron (this,a,b,c) has a positive volume;
- //! It is negative iff the tetrahedron (this,a,b,c) has a negative volume;
- //! It is zero iff the tetrahedron (this,a,b,c) has a zero volume.
- coord exactOrientation(const Point *a, const Point *b, const Point *c) const;
- coord side3D(const Point *p1, const Point *p2, const Point *p3) const { return exactOrientation(p1, p2, p3); }
-
-
- //! Exact misalignment test. Returns TRUE iff points are not aligned.
- bool exactMisalignment(const Point *a, const Point *b) const;
- bool notAligned(const Point *a, const Point *b) const { return exactMisalignment(a,b); }
-
- //! Exact planar side test. Returns TRUE iff 'this', Q, A and B are coplanar
- //! and 'this' and Q are (properly) on the same side of A-B.
- //! Warning! Coplanarity is not checked, result is undetermined if
- //! 'this', Q, A and B are not coplanar.
- bool exactSameSideOnPlane(const Point *Q, const Point *A, const Point *B) const;
-
- //! Itersection point between lines p-q and r-s. Return INFINITE_POINT if lineas are either parallel or degenerate.
- static Point lineLineIntersection(const Point& p, const Point& q, const Point& r, const Point& s);
-
- //! Itersection point between line p-q and plane r-s-t. Return INFINITE_POINT for parallel/degenerate args.
- static Point linePlaneIntersection(const Point& p, const Point& q, const Point& r, const Point& s, const Point& t);
-
- //! Squared area of the triangle p-q-r.
- static coord squaredTriangleArea3D(const Point& p, const Point& q, const Point& r);
-
- //! true if 'p' is a point of the segment v1-v2 (endpoints excluded)
- static bool pointInInnerSegment(const Point *p, const Point *v1, const Point *v2);
-
- //! true if 'p' is a point of the segment v1-v2 (endpoints included)
- static bool pointInSegment(const Point *p, const Point *v1, const Point *v2);
-
- //! true if the coplanar point 'p' is in the inner area of v1-v2-v3.
- //! Undetermined if points are not coplanar.
- static bool pointInInnerTriangle(const Point *p, const Point *v1, const Point *v2, const Point *v3);
-
- //! true if the coplanar point 'p' is either in the inner area of v1-v2-v3 or on its border.
- //! Undetermined if points are not coplanar.
- static bool pointInTriangle(const Point *p, const Point *v1, const Point *v2, const Point *v3);
-
- //! true if (p1-p2) properly intersects (sp1-sp2) at any point (endpoints included).
- //! Collinear overlapping segments are not considered to be properly intersecting.
- static bool segmentsIntersect(const Point *p1, const Point *p2, const Point *sp1, const Point *sp2);
-
- //! true if the interior of (p1-p2) properly intersects the interior of (sp1-sp2).
- //! Collinear overlapping segments are not considered to be properly intersecting.
- static bool innerSegmentsCross(const Point& p1, const Point& p2, const Point& sp1, const Point& sp2);
-
- //! true if segment (s1-s2) intersects the triangle v1-v2-v3 (border included).
- static bool segmentIntersectsTriangle(const Point *s1, const Point *s2, const Point *v1, const Point *v2, const Point *v3);
-
- //! true if segment (s1-s2) intersects the triangle v1-v2-v3 (border included).
- //! Accelerated version - relative orientations are passed as parameters.
- static bool segmentIntersectsTriangle(const Point *s1, const Point *s2, const Point *v1, const Point *v2, const Point *v3, const coord& o1, const coord& o2);
-
-
-
-
- // FUNCTIONS BELOW THIS LINE MAY RETURN APPROXIMATED/NOT ROBUST RESULTS EVEN WHEN USING RATIONALS
-
-
-
- //! Distance from origin
- double length() const { return sqrt(TMESH_TO_DOUBLE((x*x + y*y + z*z))); }
-
- //! Divides the vector by its length. If isNull() the application exits with an error.
- void normalize();
-
- //! Rotates the vector around 'axis' by 'ang' radians ccw.
- void rotate(const Point& axis, const double& ang);
-
- //! Distance from 'b'
- double distance(const Point& b) const {return (((*(this))-(b)).length());}
-
- //! Distance from '*b'
- double distance(const Point *b) const { return (((*(this)) - (*b)).length()); }
-
- //! Distance from straight line through 'a' and 'b'
- double distanceFromLine(const Point *a, const Point *b) const;
-
- //! Distance from straight line through 'a' and 'b'. *cc is set to the closest line point.
- double distanceFromLine(const Point *a, const Point *b, Point *cc) const;
-
- double distanceFromEdge(const Point *a, const Point *b) const; //!< Distance from segment a-b
-
- //! Distance from segment a-b. *cc is set to the closest edge point.
- double distanceFromEdge(const Point *a, const Point *b, Point *cc) const;
-
- //! Distance between the straight lines through (this) - l1_p2 and l2_p1 - l2_p2.
- double distanceLineLine(const Point *l1_p2, const Point *l2_p1, const Point *l2_p2) const;
-
- //!< Angle between this vector and 'v' in radians.
- double getAngle(const Point& v) const;
-
- //! Angle defined by in radians.
- double getAngle(const Point& a, const Point& b) const { return (a - (*this)).getAngle(b - (*this)); }
-
- //! Angle defined by <*a, *this, *b> in radians.
- double getAngle(const Point *a, const Point *b) const { return ((*a) - (*this)).getAngle((*b) - (*this)); }
-
-
- //! Line-line closest point computation.
- //! I SUSPECT THIS CAN BE MADE EXACT...
-
- //! Computes the closest points of the line passing through this and this2,
- //! and the line passing through p1 and p2. The computed points are used to
- //! initialize the coordinates of cpOnThis and cpOnOther. The method
- //! returns 0 if the lines are parallel, 1 otherwise.
- int closestPoints(const Point *this2, const Point *p1, const Point *p2, Point *cpOnThis, Point *cpOnOther) const;
-};
-
-//! Lexycographic comparison to be used with jqsort() or abstractHeap.
-int xyzCompare(const Data *p1, const Data *p2);
-
-//! Static point with DBL_MAX coordinates.
-extern const Point INFINITE_POINT;
-
-//! Checks whether a point is INFINITE_POINT.
-#define IS_FINITE_POINT(p) ((p).x < DBL_MAX)
-
-} //namespace T_MESH
-
-#endif // _POINT_H
-
diff --git a/src/mesh_fix/include/Kernel/tmesh_kernel.h b/src/mesh_fix/include/Kernel/tmesh_kernel.h
deleted file mode 100644
index 40ad5a552..000000000
--- a/src/mesh_fix/include/Kernel/tmesh_kernel.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef _TMESH_KERNEL_H
-#define _TMESH_KERNEL_H
-
-#include "basics.h"
-#include "list.h"
-#include "point.h"
-#include "matrix.h"
-
-#endif //_TMESH_KERNEL_H
diff --git a/src/mesh_fix/include/TMesh/detectIntersections.h b/src/mesh_fix/include/TMesh/detectIntersections.h
deleted file mode 100644
index 9659890cf..000000000
--- a/src/mesh_fix/include/TMesh/detectIntersections.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef DETECT_INTERSECTIONS_H
-#define DETECT_INTERSECTIONS_H
-
-#include "tin.h"
-
-namespace T_MESH
-{
-#define DI_MAX_NUMBER_OF_CELLS 10000
-#define DI_EPSILON_POINT Point(1.0e-9, 1.0e-9, 1.0e-9)
-
-class di_cell : public Data
-{
-public:
- Point mp, Mp;
- List triangles;
-
- di_cell() {}
- di_cell(Basic_TMesh *tin, bool useAll = true);
-
- bool is_triangleBB_in_cell(Triangle *t) const;
-
- di_cell *fork();
- void selectIntersections(bool justproper = false);
- bool doesNotIntersectForSure();
-};
-
-} //namespace T_MESH
-
-#endif // DETECT_INTERSECTIONS_H
diff --git a/src/mesh_fix/include/TMesh/edge.h b/src/mesh_fix/include/TMesh/edge.h
deleted file mode 100644
index 89b8bf5ed..000000000
--- a/src/mesh_fix/include/TMesh/edge.h
+++ /dev/null
@@ -1,252 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef _EDGE_H
-#define _EDGE_H
-
-#include "basics.h"
-#include "vertex.h"
-
-namespace T_MESH
-{
-
-//! Edge of a Basic_TMesh.
-
-//! This class represents an edge of a triangulation. An Edge is the main
-//! part of the Basic_TMesh data structure. Each edge has an orientation
-//! (i.e. from v1 to v2) which forces the order in which incident triangles
-//! (t1 and t2) are stored in the class. When looking the edge so that it
-//! points "upwards", if the normal of t1 points towards the observer then
-//! t1 must be on the left of the edge. The field mask is useful for
-//! assigning up to 256 different states to the edge.
-
-
-class Edge : public Data
-{
- public :
-
- Vertex *v1,*v2; //!< End-points
- class Triangle *t1,*t2; //!< Incident triangles
- unsigned char mask; //!< bit-mask for marking purposes
- Data *info; //!< Further information
-
-
- Edge(); //!< AMF_ADD 1.1-2 >
- Edge(Vertex *s, Vertex *d); //!< Constructor
- ~Edge(); //!< Destructor
-
- //! Returns true only if object is a basic Edge. All the reimplementations must return false.
- TMESH_VIRTUAL bool isBaseType() const { return true; }
-
- //! TRUE iff edge is properly linked to a Basic_TMesh.
- bool isLinked() const {return (v1 != NULL);}
-
- //! TRUE iff 'v' is an end-point of the edge.
- bool hasVertex(const Vertex *v) const {return (v1==v || v2==v);}
-
- //! TRUE iff 't' is incident to the edge.
- bool hasTriangle(const Triangle *t) const {return (t1==t || t2==t);}
-
- //! TRUE if both 'va' and 'vb' are vertices of the edge.
- bool hasVertices(const Vertex *va, const Vertex *vb) const {return ((v1==va && v2==vb) || (v2==va && v1==vb));}
-
- //! Squared length of the edge.
- coord squaredLength() const {return v1->squaredDistance(v2);}
-
- //! Convert to vector v2-v1.
- Point toVector() const {return (*v2)-(*v1);}
-
- //! Return the edge's mid-point.
- Point getMidPoint() const {return ((*v1)+(*v2))/2.0;}
-
- //! Invert the edge's orientation.
- TMESH_VIRTUAL void invert() {p_swap((void **)(&v1), (void **)(&v2)); p_swap((void **)(&t1), (void **)(&t2));} //!< AMF_CHANGE 1.1-2>
-
- //! Triangle on the left of the edge when looking from 'v'. NULL if 'v' is not a vertex of the edge.
- Triangle *leftTriangle(const Vertex *v) const {return ((v1 == v)?(t1):((v2 == v)?(t2):(NULL)));}
-
- //! Triangle on the right of the edge when looking from 'v'. NULL if 'v' is not a vertex of the edge.
- Triangle *rightTriangle(const Vertex *v) const {return ((v1 == v)?(t2):((v2 == v)?(t1):(NULL)));}
-
- //! Vertex opposite to 'v'. NULL if 'v' is not a vertex of the edge.
- Vertex *oppositeVertex(const Vertex *v) const {return ((v1 == v)?(v2):((v2 == v)?(v1):(NULL)));}
-
- //! Incident triangle opposite to 't'. NULL if 't' is not incident to the edge.
- Triangle *oppositeTriangle(const Triangle *t) const {return ((t1 == t)?(t2):((t2 == t)?(t1):(NULL)));}
-
- //! Replace vertex 'a' with vertex 'b' in the edge and return TRUE. If 'a' is not a vertex of the edge return FALSE.
- bool replaceVertex(const Vertex *a, Vertex *b) {if (v1==a) v1=b; else if (v2==a) v2=b; else return 0; return 1;}
-
- //! Replace incident triangle 'a' with 'b' and return TRUE. If 'a' is not incident to the edge return FALSE.
- bool replaceTriangle(const Triangle *a, Triangle *b) {if (t1==a) t1=b; else if (t2==a) t2=b; else return 0; return 1;}
-
- //! Vertex shared with edge 'b'. NULL if this and 'b' do not share any vertex.
- Vertex *commonVertex(const Edge *b) const {return ((v1 == b->v1 || v1 == b->v2)?(v1):((v2 == b->v1 || v2 == b->v2)?(v2):(NULL)));}
-
- //! TRUE iff edge is on the boundary (i.e., one of the two incident triangles is NULL).
- bool isOnBoundary() const {return (t1 == NULL || t2 == NULL);}
-
- //! TRUE iff edge is isolated (i.e., both the two incident triangles are NULL).
- bool isIsolated() const {return (t1 == NULL && t2 == NULL);}
-
- //! TRUE iff the two endpoints coincide exactly
- bool isDegenerate() const {return ((*v1)==(*v2));}
-
- //! If the edge is on boundary return its only incident triangle. NULL otherwise.
- Triangle *getBoundaryTriangle() const {return (t2 == NULL)?(t1):((t1 == NULL)?(t2):(NULL));}
-
- //! Print the coordinates of the end-ponts to the file handler pointed to by 'f' (stdout by default).
- void printEdge(FILE *f =stdout) const {v1->printPoint(f); v2->printPoint(f);}
-
- //! Combinatorial edge-swap.
-
- //! Vertices of the edge are replaced with vertices of the two incident triangles which are opposite to this edge.
- //! Connectivity information is updated properly.
- //! If the edge is on boundary or if the edge after the swap already exists return FALSE and do not change anything.
- //! Return TRUE on success.
- //! If 'fast' is set, no topological check is performed.
- TMESH_VIRTUAL bool swap(const bool fast=0);
-
- //! Edge collapse.
-
- //! This method collapses the edge and updates the connectivity of the
- //! neighboring elements consistently. The edge will be contracted into its
- //! first vertex v1 (or v2, for collapseOnV2()).
- //! This method returns v1 (or v2) on success, NULL otherwise.
- //! Failure occurs when the collapse would produce an invalid connectivity graph.
- //! Caution! If the collapse succeeds the
- //! edge, its incident triangles and the second vertex are unlinked, but
- //! they are still present in the lists of the Basic_TMesh.
- //! The calling function is responsible of removing them from the lists using
- //! the method removeUnlinkedElements().
- Vertex *collapseOnV1();
- Vertex *collapseOnV2();
-
- //! This method collapses the edge and updates the connectivity of the
- //! neighboring elements consistently. The edge will be transformed into a
- //! vertex with the coordinates of 'p'.
- //! This method returns TRUE on success, FALSE otherwise.
- //! Failure occurs when the collapse would produce an invalid connectivity graph.
- //! Caution! If the collapse succeeds the
- //! edge, its incident triangles and the second vertex are unlinked, but
- //! they are still present in the lists of the Basic_TMesh.
- //! The calling function is responsible of removing them from the lists using
- //! the method removeUnlinkedElements().
- bool collapse(const Point& p);
-
- //! Edge collapse.
-
- //! This method collapses the edge and updates the connectivity of the
- //! neighboring elements consistently. The edge will be transformed into a
- //! vertex placed at the edge's mid-point.
- //! This method returns TRUE on success, FALSE otherwise.
- //! Failure occurs when the collapse would produce an invalid connectivity graph.
- //! Caution! If the collapse succeeds the
- //! edge, its incident triangles and the second vertex are unlinked, but
- //! they are still present in the lists of the Basic_TMesh.
- //! The calling function is responsible of removing them from the lists using
- //! the method removeUnlinkedElements().
- bool collapse();
-
- //! Merge with another boundary edge.
-
- //! If both this and 'e' are boundary edges, the edge 'e' is identified with
- //! this one, and the connectivity of the neighboring elements is updated consistently.
- //! This method returns TRUE on success, FALSE otherwise.
- //! Failure occurs when the merge would produce an invalid connectivity graph (i.e., non orientable).
- //! Caution! If the merge succeeds the edge 'e' and its two end-points
- //! are unlinked, but they are still present in the lists of the
- //! Basic_TMesh. It's responsibility of the calling function to remove
- //! them from the lists using the method removeUnlinkedElements().
- bool merge(Edge *e);
-
- //! Stitching primitive.
-
- //! If there is a copy of this edge incident to one of the end-points,
- //! identify it with this edge, and update the connectivity properly.
- //! This method returns TRUE on success, FALSE otherwise.
- //! Caution! If the stitch succeeds, the duplicated edge
- //! is unlinked, but it is still present in the lists of the
- //! Basic_TMesh. It's responsibility of the calling function to remove
- //! it from the lists using the method removeEdges().
- bool stitch();
-
- //! Returns TRUE if edge is not on boundary and its two incident triangles overlap
- bool overlaps() const;
-
- //! true if this edge itersects 't' other than on common subsimplexes
- bool intersects(const Triangle *t) const;
-
- //! Returns a positive value if dihedral angle is less than flat (convex), 0 if flat,
- //! negative if more than flat (concave). Returns DBL_MAX if edge is on boundary.
- coord getConvexity() const;
-
- // FUNCTIONS BELOW THIS LINE MAY RETURN APPROXIMATED/NOT ROBUST RESULTS EVEN WHEN USING RATIONALS
-
-
-
- //! Euclidean length of the edge.
- double length() const { return v1->distance(v2); }
-
- //! Convert to normalized vector (v2-v1)/|v2-v1|.
- Point toUnitVector() const;
-
- //! Return the normal at the edge as the average of the normals of the two incident triangles.
- //! A null (0,0,0) vector is returned if the edge is on boundary.
- Point getNormal() const;
-
- //! Return the minimum among the six angles of the two incident triangles.2PI if on boundary.
- double delaunayMinAngle() const;
-
- //! Dihedral angle at the edge.
- double dihedralAngle() const;
-
- //! Angle between the normals of the two incident triangles.
-
- //! Angle between the normals of the two incident triangles. If
- //! the edge is on boundary or one or both the incident triangles are
- //! degenerate, return -1.
- double curvature() const;
-};
-
-//! Edge comparison based on length to be used with jqsort() or abstractHeap.
-int edgeCompare(const Data *a, const Data *b);
-
-//! Lexycographic edge comparison to be used with jqsort() or abstractHeap.
-int lexEdgeCompare(const Data *a, const Data *b);
-
-//! Vertex-based edge comparison for qsort.
-//! Duplicated edges are contiguous in this sorting.
-int vtxEdgeCompare(const Data *a, const Data *b);
-
-} //namespace T_MESH
-
-#endif //_EDGE_H
-
diff --git a/src/mesh_fix/include/TMesh/marchIntersections.h b/src/mesh_fix/include/TMesh/marchIntersections.h
deleted file mode 100644
index 37a575fb7..000000000
--- a/src/mesh_fix/include/TMesh/marchIntersections.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef MARCHING_INTS_H
-#define MARCHING_INTS_H
-
-#include "tmesh.h"
-
-namespace T_MESH
-{
-
-///////////////////////////////////////////////////////////////
-//
-// A ray-mesh intersection.
-//
-///////////////////////////////////////////////////////////////
-
-class mc_ints : public Data
-{
- public:
-
- coord ic; // Distance from ray source
- unsigned char sg; // 1 if ray enters mesh, 0 if it exits
- ExtVertex *v; // Used to support polygonization
- Triangle *source; // The triangle that generates this intersection
-
- mc_ints(coord a, unsigned char b, Triangle *s) { ic = a; sg = b; v = NULL; source = s; }
- ~mc_ints() { if (v) delete(v); }
-
- static int compare(const Data *e1, const Data *e2);
-};
-
-
-///////////////////////////////////////////////////////////////
-//
-// A cubical cell to be polygonized
-//
-///////////////////////////////////////////////////////////////
-
-class mc_cell : public Data
-{
- public:
- int x,y,z; // Coordinates (i.e. cell's position)
- mc_ints *ints[12]; // Intersection at each voxel edge
-
- mc_cell(int a, int b, int c) {x=a; y=b; z=c;}
- mc_cell(int a, int b, int c, mc_ints *m, int i) : x(a), y(b), z(c)
- {
- for (int n=0; n<12; n++) ints[n] = (n==i)?(m):(NULL);
- }
-
- void polygonize(Basic_TMesh *tin);
- static int compare(const Data *e1, const Data *e2);
-
- void merge(mc_cell *m);
-
-private:
- unsigned char lookup() const; // The polygonization to be used
- unsigned char lookdown(); // The other polygonization to be used
- void purgeIntersections(); // TRUE if intersections are consistent in the cell
-};
-
-
-///////////////////////////////////////////////////////////////
-//
-// The marching intersections grid
-//
-///////////////////////////////////////////////////////////////
-
-class mc_grid : public Data
-{
- Point origin; // Origin for normalization
- coord norm; // Normalization factor
-protected: //! < AMF_CHANGE - since T_MESH 2.4-2 >
- Basic_TMesh *tin; // Triangulation to remesh //! < AMF_CHANGE - since T_MESH 2.4-2 >
- List *xy, *xz, *zy; // Axis-parallel rays //! < AMF_CHANGE - since T_MESH 2.4-2 >
- int numrays; // Number of rays per axis //! < AMF_CHANGE - since T_MESH 2.4-2 >
-
-public:
- mc_grid(Basic_TMesh *_tin, int n);
- ~mc_grid() {delete [] xy; delete [] xz; delete [] zy;}
-
- TMESH_VIRTUAL mc_ints * newMcInts(coord a, unsigned char b, Triangle *s){ return new mc_ints(a,b,s); } //! < AMF_CHANGE - since T_MESH 2.4-2 >
-
- void remesh(bool simplify_result =false);
- void simplify();
-
- static bool segmentIntersectsTriangle(Point& ev1, Point& ev2, Triangle *t, Point& op);
-
-protected: //! < AMF_CHANGE - since T_MESH 2.4-2 >
- TMESH_VIRTUAL void sample_triangle(Triangle *t); //! < AMF_CHANGE - since T_MESH 2.4-2 >
- TMESH_VIRTUAL void createVertices(List *l, int i, int j, int k); //! < AMF_CHANGE - since T_MESH 2.4-2 >
-private:
- void sort();
- void purge();
- void createVertices();
- List *createCells();
- void trackOuterHull();
-
- static inline coord oceil(const coord& d) { coord c; return ((c = ceil(d)) == d) ? (c + 1) : (c); }
- void purgeList(List *l);
-};
-
-} //namespace T_MESH
-
-#endif // MARCHING_INTS_H
diff --git a/src/mesh_fix/include/TMesh/tin.h b/src/mesh_fix/include/TMesh/tin.h
deleted file mode 100644
index e53814954..000000000
--- a/src/mesh_fix/include/TMesh/tin.h
+++ /dev/null
@@ -1,804 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef _TIN_H
-#define _TIN_H
-
-#include "tmesh.h"
-
-namespace T_MESH
-{
-
-//! Basic_TMesh
-
-//! This class represents a manifold and oriented triangle mesh.
-//! Vertices, Edges and Triangles are stored in the Lists V, E and T
-//! respectively. Methods boundaries(), handles() and shells() may
-//! be used to retrieve the respective topological entities.
-//! Navigation of the mesh is based on the topological relationships
-//! stored in each Vertex, Edge and Triangle.
-//! Some methods would require a global update only to maintain
-//! consistent values of the protected fields n_boundaries, n_handles
-//! and n_shells. On the other hand, the same methods would work in
-//! constant time if these values would not need to be updated.
-//! To keep complexity as low as possible,
-//! we make use of the 'dirty bits' d_boundaries, d_handles and
-//! d_shells to mark that the respective entities must be updated.
-//! The access functions boundaries(), handles() and shells()
-//! check the status of the respective dirty bit and do a global
-//! update (i.e., eulerUpdate()) only if necessary.
-//! The complexity of the methods is provided as a function of a
-//! generic 'N', which is O(V.numels()) = O(E.numels()) = O(T.numels()).
-
-class Basic_TMesh
-{
- protected:
-
- int n_boundaries; //!< Number of boundary loops
- int n_handles; //!< Number of handles
- int n_shells; //!< Number of connected components
-
- bool d_boundaries; //!< Dirty bit for n_boundaries
- bool d_handles; //!< Dirty bit for n_handles
- bool d_shells; //!< Dirty bit for n_shells
-
- public:
-
- List V; //!< Vertex set
- List E; //!< Edge set
- List T; //!< Triangle set
-
- void *info; //! Generic information attached to this mesh
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Constructors/Destructor (Implemented in "MESH_STRUCTURE/io.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
- //! Empty triangulation. Should be used only prior to a call to load().
- Basic_TMesh();
-
- //! Pre-defined triangulation. Currently, only "triangle" and "tetrahedron"
- //! are recognized.
- Basic_TMesh(const char *);
- void init(const char *);
-
- //! Clones an existing Trianglation.
- Basic_TMesh(const Basic_TMesh *, const bool clone_info = false);
- void init(const Basic_TMesh *, const bool clone_info = false);
-
- //! Clones an existing connected component.
-
- //! Creates a new Basic_TMesh out of a connected component of an existing
- //! Basic_TMesh. 't' is a triangle of the connected component that must
- //! be copied. If 'keep_ref' is TRUE, each element of the existing mesh
- //! keeps a pointer to the corresponding new element in the 'info' field.
- Basic_TMesh(const Triangle *t, const bool keep_ref = false);
- void init(const Triangle *t, const bool keep_ref = false);
-
- //FIXED:
- //! Destructor. Frees the memory allocated for all the mesh elements.
- //! Warning! This method uses the freeNodes() method of the class List,
- //! which is not guaranteed to work correctly on systems other than
- //! Linux (see the documentation of List for details).
- //! Assuming that the method works correctly, however, the calling
- //! function is responsible of freeing the memory that was possibly
- //! allocated for objects pointed to by the 'info' field of mesh
- //! elements. Clearly, this must be done before calling the destructor.
- ~Basic_TMesh();
-
- //! Returns true only if object is a basic Basic_TMesh. All the reimplementations must return false.
-// TMESH_VIRTUAL bool isBaseType() const { return true; }
-
- //! Get the number of boundary loops of the triangle mesh. O(1) or O(N).
- int boundaries() { if (d_boundaries) eulerUpdate(); return n_boundaries; }
-
- //! Get the number of handles of the triangle mesh. O(1) or O(N).
- int handles() { if (d_handles) eulerUpdate(); return n_handles; }
-
- //! Get the number of connected components of the triangle mesh. O(1) or O(N).
- int shells() { if (d_shells) eulerUpdate(); return n_shells; }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Input/Output methods (Implemented in "MESH_STRUCTURE/io.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
- //! Initialize the triangle mesh from the file 'filename'.
-
- //! The file format is automatically deduced from the magic number
- //! or the filename extension. If 'doupdate' is FALSE, the
- //! global update for the topological entities is prevented.
- //! Currently, the following file formats are supported:
- //! Open Inventor (IV), VRML 1.0 and 2.0 (WRL), Object File Format (OFF),
- //! IMATI Ver-Tri (VER, TRI), PLY, OBJ, STL.
- //! A non-zero value is returned in case of error. Specifically,
- //! IO_CANTOPEN means that the file couldn't be opened for reading.
- //! IO_FORMAT means that the file format was not recognized by the loader.
- //! IO_UNKNOWN represents all the other errors.
- //! The calling function is responsible of verifying that the mesh is
- //! empty before calling this method.
-
- int load(const char *filename, const bool update = 1);
- int loadIV(const char *); //!< Loads IV
- int loadVRML1(const char *); //!< Loads VRML 1.0
- int loadOFF(const char *); //!< Loads OFF
- int loadEFF(const char *); //!< Loads EFF
- int loadPLY(const char *); //!< Loads PLY
- int loadVerTri(const char *); //!< Loads VER-TRI
- int loadVRML2(const char *); //!< Loads VRML 2.0
- int loadOBJ(const char *); //!< Loads OBJ
- int loadSTL(const char *); //!< Loads STL
-
- int cutAndStitch(); //!< Convert to manifold
- Triangle * CreateIndexedTriangle(ExtVertex **, int, int, int);
- TMESH_VIRTUAL Triangle * CreateTriangleFromVertices(ExtVertex *, ExtVertex *, ExtVertex *);
-
- //! This function approximates the vertex coordinates with the values
- //! that can be represented in an ASCII file.
- void coordBackApproximation();
-
- protected:
- void closeLoadingSession(FILE *, int, ExtVertex **, bool);
- bool pinch(Edge *e, bool wcv);
- //! If the 'e' is internal, creates a copy of the edge and associates e->t2
- //! to this copy. After this operation, 'e' and its copy are boundary edges
- //! with the same vertices. If 'e' is already on boundary, nothing is done
- //! and NULL is returned. Otherwise the newly created copy is returned.
- TMESH_VIRTUAL Edge *duplicateEdge(Edge *e);
-
- public:
- TMESH_VIRTUAL Vertex * newVertex();
- TMESH_VIRTUAL Vertex * newVertex(const coord &, const coord &, const coord &);
- TMESH_VIRTUAL Vertex * newVertex(Point *);
- TMESH_VIRTUAL Vertex * newVertex(Point &);
- TMESH_VIRTUAL Vertex * newVertex(Vertex *);
- TMESH_VIRTUAL Edge * newEdge(Vertex *, Vertex *);
- TMESH_VIRTUAL Edge * newEdge(Edge *);
- TMESH_VIRTUAL Triangle * newTriangle();
- TMESH_VIRTUAL Triangle * newTriangle(Edge *, Edge *, Edge *);
- TMESH_VIRTUAL Basic_TMesh * newObject() const { return new Basic_TMesh(); }
- TMESH_VIRTUAL Basic_TMesh * newObject(const Basic_TMesh *tm, const bool ci = false) const { return new Basic_TMesh(tm, ci); }
- TMESH_VIRTUAL Basic_TMesh * newObject(const char *s) const { return new Basic_TMesh(s); }
-
- //! Save the triangle mesh to file 'filename'.
-
- //! The file format is deduced from the filename extension
- //! (wrl = vrml 1.0), (iv = OpenInventor), (off = Object
- //! file format), (ply = PLY format), (tri = IMATI Ver-Tri).
- //! If 'back_approx' is set, vertex coordinates are approximated
- //! to reflect the limited precision of floating point
- //! representation in ASCII files. This should be used when
- //! coherence is necessary between in-memory and saved data.
- //! A non-zero return value is returned if errors occur.
-
- int save(const char *filename, bool back_approx = 0);
-
- int saveIV(const char *); //!< Saves IV
- int saveOFF(const char *); //!< Saves OFF 1.0
- int saveEFF(const char *); //!< Saves EFF
- int saveOBJ(const char *); //!< Saves OBJ
- int saveSTL(const char *); //!< Saves STL
- int savePLY(const char *, bool ascii = 1); //!< Saves PLY 1.0 (ascii or binary)
- int saveVerTri(const char *); //!< Saves Ver-Tri
-
- //! Saves the triangle mesh to a VRML 1.0 file.
- //! The value of 'mode' specifies whether to use additional
- //! information attached to mesh elements in order to assign
- //! them a proper color.
- //! IO_CSAVE_OVERALL assigns a unique color for the entire mesh (default).
- //! IO_CSAVE_PERFACE assigns a color to each triangle depending on the value
- //! of its 'info' field.
- //! IO_CSAVE_PERVERTEX assigns a color to each vertex depending on the value
- //! of its 'info' field.
- //! IO_CSAVE_PERFACE_INDEXED assigns one of five base colors to each triangle
- //! depending on the value of its 'mask' field.
- //! IO_CSAVE_PERVERTEX_INDEXED assigns one of five base colors to each vertex
- //! depending on the value of its 'mask' field.
- int saveVRML1(const char *, const int mode = 0);
-
-
- //! Append another triangle mesh to the existing one.
-
- //! This method works exactly as the 'load()' method, except for the fact
- //! that it does not assume that the mesh is empty.
- int append(const char *filename, const bool doupdate = 1);
-
-
- // Move all the elements of 't' to this mesh and delete 't' itself.
- TMESH_VIRTUAL void moveMeshElements(Basic_TMesh *t, bool delInput = true);
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Primitive Construction (Implemented in "MESH_STRUCTURE/tin.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
- //! Creates an Edge connecting two existing mesh vertices.
-
- //! Returns the newly created edge. If an edge connecting the two vertices
- //! already exists in the mesh, then no new edge is created and the old one
- //! is returned.
- Edge *CreateEdge(Vertex *v1, Vertex *v2);
-
-
- //! Creates an Edge connecting two existing mesh Extended vertices.
-
- //! Returns the newly created edge. If an edge connecting the two vertices
- //! already exists in the mesh, then no new edge is created and the old one
- //! is returned.
- //! If 'check' is FALSE, the check for previously existing edges is skipped.
- Edge *CreateEdge(ExtVertex *v1, ExtVertex *v2, const bool check = 1);
-
-
- //! Creates a properly oriented Triangle bounded by three existing mesh edges.
-
- //! Returns the newly created Triangle. If e1, e2 and e3
- //! are not suitable for creating a properly oriented and
- //! manifold triangle, the creation fails and NULL is returned.
- TMESH_VIRTUAL Triangle * CreateTriangle(Edge *e1, Edge *e2, Edge *e3);
-
-
- //! Creates an arbitrarily oriented Triangle bounded by three existing mesh edges.
-
- //! Returns the newly created Triangle. If either e1, e2 or e3
- //! has already two incident triangles, the creation fails and NULL is returned.
- //! This method assumes that e1, e2 and e3 are incident to exactly three vertices.
- TMESH_VIRTUAL Triangle * CreateUnorientedTriangle(Edge *, Edge *, Edge *);
-
-
- //! Creates a newEdge 'e' and an oriented Triangle bounded by 'e', 'e1' and 'e2'.
-
- //! The newly created triangle is returned, unless 'e1' and 'e2' do not share a
- //! vertex or they are not boundary edges. In this cases, NULL is returned.
- TMESH_VIRTUAL Triangle *EulerEdgeTriangle(Edge *e1, Edge *e2);
-
-
- //! Splits and edge at a given point and returns the newly created Vertex.
- //! If the boolean parameter is set to true, the 'mask' fields of edges and
- //! triangles are propagated to the new elements.
- TMESH_VIRTUAL Vertex *splitEdge(Edge *, Point *, bool = 0);
-
-
- //! Splits a triangle at a given point and returns the newly created Vertex.
- //! If the boolean parameter is set to true, the 'mask' field of the
- //! triangle is propagated to the new triangle.
- TMESH_VIRTUAL Vertex *splitTriangle(Triangle *, Point *, bool = 0);
-
- //! Creates two new triangles connecting the boundary edges e1 and e2
- //! and returns their common edge.
- //! If e1 and e2 share a vertex, then only one triangle is created and
- //! e1 is returned.
- //! Returns NULL if either e1 or e2 are not boundary edges.
- TMESH_VIRTUAL Edge *bridgeBoundaries(Edge *e1, Edge *e2);
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Primitive Destruction (Implemented in "MESH_STRUCTURE/tin.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
-
- //! Unlinks a triangle from the mesh. O(1).
-
- //! Resulting isolated vertices and edges are unlinked too.
- //! If necessary, this method duplicates non-manifold vertices that can
- //! occur due to the removal of the triangle.
- //! The unlinked triangle, along with the other possible unlinked elements,
- //! must be removed from the List T through removeUnlinkedElements().
- void unlinkTriangle(Triangle *);
-
-
- //! Unlinks a triangle from the mesh. O(1).
-
- //! No check is performed on the resulting topology, which may be inconsistent.
- //! The unlinked triangle, along with the other possible unlinked elements,
- //! must be removed from the List T through removeUnlinkedElements().
- void unlinkTriangleNoManifold(Triangle *);
-
-
- //! Removes a triangle from the mesh. O(N).
-
- //! This is equivalent to an unlinkTriangle(t) followed by a
- //! removeUnlinkedElements().
- void removeTriangle(Triangle *t) { unlinkTriangle(t); removeUnlinkedElements(); }
-
- //! Removes all the unlinked triangles from List T. Returns the number of removed triangles. O(N).
- int removeTriangles();
-
- //! Removes all the unlinked edges from List E. Returns the number of removed edges. O(N).
- int removeEdges();
-
- //! Removes all the unlinked vertices from List V. Returns the number of removed vertices. O(N).
- int removeVertices();
-
- //! Removes all the unlinked elements from the lists. Returns the number of removed elements. O(N).
- int removeUnlinkedElements() { return removeTriangles() + removeEdges() + removeVertices(); }
-
- //! Removes all the vertices that can be deleted without changing the geometric realization. O(N).
- int removeRedundantVertices();
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Methods acting on selections (Implemented in "MESH_STRUCTURE/tin.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
- //! Deselects all the triangles. O(N).
- void deselectTriangles();
-
- //! Removes all the selected triangles. O(N).
- void removeSelectedTriangles();
-
- //! Selects all the triangles having at least one boundary vertex. O(N).
- //! Returns the number of selected triangles.
- int selectBoundaryTriangles();
-
- //! Enlarges the current selection of one triangle in width. O(N).
-
- //! Each triangle sharing at least one vertex with a currently selected
- //! triangle becomes selected.
- //! Returns the number of newly selected triangles.
- int growSelection();
-
- //! Shrinks the current selection of one triangle in width. O(N).
-
- //! Each triangle sharing at least one vertex with a currently unselected
- //! triangle becomes unselected.
- void shrinkSelection();
-
- //! Inverts the selection status of all the triangles. O(N).
-
- //! If 't0' is not NULL, then only the connected component containing 't0'
- //! is inverted.
- void invertSelection(Triangle *t0 = NULL);
-
- //! If 't0' is selected, deselect everything but the selected triangles connected to 't0'
- void reselectSelection(Triangle *t0);
-
- //! Creates a new Basic_TMesh out of an existing selection containing 't0'. O(output).
-
- //! If necessary, non-manifold vertices are properly duplicated.
- //! If 'keep_ref' is set to TRUE, then elements of the original mesh point
- //! (through their info field) to corresponding elements of the newly created copy.
-
- TMESH_VIRTUAL Basic_TMesh *createSubMeshFromSelection(Triangle *t0 = NULL, bool keep_ref = 0);
-
- //! Creates a new Basic_TMesh out of an existing triangle 't0'. O(output).
-
- TMESH_VIRTUAL Basic_TMesh *createSubMeshFromTriangle(Triangle *t0);
-
- //! Marks all the triangles within distance L from 'p' as selected. O(output).
-
- //! A triangle is considered to be within distance L from 'p' only if all
- //! its three vertices are so.
- //! Point 'p' is assumed to belong to triangle 't0', which is required to
- //! limit the complexity to the size of the selected region.
- //! Returns the number of selected triangles.
- int selectSphericalRegion(Triangle *t0, const double L, const Point *p);
-
-
- //! Marks all the triangles within distance L from 'p' as deselected. O(output).
-
- //! A triangle is considered to be within distance L from 'p' only if all
- //! its three vertices are so.
- //! Point 'p' is assumed to belong to triangle 't0', which is required to
- //! limit the complexity to the size of the selected region.
- //! Returns the number of deselected triangles.
- int deselectSphericalRegion(Triangle *t0, const double L, const Point *p);
-
-
- //! Deselects all the triangles farther than L from 'p'. O(N).
-
- //! A triangle is considered to be farther than L from 'p' if at least
- //! one of its three vertices is so.
- //! Point 'p' is assumed to belong to triangle 't0'. Passing 't0' avoids
- //! the non robust and expensive computation of point-in-triangle.
- void reselectSphericalRegion(Triangle *t0, const double L, const Point *p);
-
- //! Re-triangulates the currently selected region using a Delaunay-like approach. O(SlogS).
-
- //! A common plane is computed as the average of the planes of the triangles selected;
- //! then, the vertices of the region are projected on the plane and edges are iteratively
- //! swapped up to convergence (which is guaranteed on planar and simple domains).
- //! Finally, the vertices are moved back to their original positions. This operation is
- //! particularly useful to improve the quality of nearly flat regions. The selection must
- //! be simple and its Gauss map must be entirely contained in a semi-sphere.
- //! Returns TRUE on success, FALSE otherwise.
- bool retriangulateSelectedRegion();
-
-
- //! TRUE iff the set of selected triangles in 'l' is simply connected. O(l->numels()).
- bool isSelectionSimple(List *l);
-
- //! Unmarks all the elements but leaves the selection status of triangles as is. O(N).
- void unmarkEverythingButSelections();
-
-
- //! Selects all the triangles of the connected component containing t0. O(N).
-
- //! If 'stop_on_sharp', expansion from 't0' brakes at tagged sharp edges.
- //! Returns the number of selected triangles.
- int selectConnectedComponent(Triangle *t0, bool stop_on_sharp = 0);
-
-
- //! Deselects all the triangles of the connected component containing t0. O(N).
-
- //! If 'stop_on_sharp', expansion from 't0' brakes at tagged sharp edges.
- //! Returns the number of deselected triangles.
- int deselectConnectedComponent(Triangle *t0, bool stop_on_sharp = 0);
-
-
- //! Append to the current mesh a copy of all the elements of 't'.
- //! The newly created elements form a new selection.
- TMESH_VIRTUAL void append(Basic_TMesh *t);
-
- //! This method removes one connected component from the mesh and creates
- //! a separate new mesh out of it. The components to be removed is the one
- //! containing the first triangle in the list T.
- //! Possible selection flags are deleted by this method.
- TMESH_VIRTUAL Basic_TMesh *split();
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Region manipulation (Implemented in "MESH_STRUCTURE/tin.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
- //! Make a list of triangles within distance L from 'p'. O(output).
-
- //! Starting from 't0', which is assumed to contain 'p', add a triangle at a
- //! time to the list as long as all the vertices stay within distance L from 'p'.
- List *getRegion(Triangle *t0, const double L, const Point *p);
-
- //! Removes triangles within distance L from 'p'. O(N).
-
- //! Starting from 't0', which is assumed to contain 'p', remove a triangle at a
- //! time as long as all its vertices stay within distance L from 'p'.
- void removeRegion(Triangle *t0, const double L, const Point *p);
-
- //! Get the vertex next to 'v' on the boundary of the region. O(1).
- Vertex *nextVertexOnRegionBoundary(Vertex *v) const;
-
- //! Retrieve internal vertices of a region. O(l->numels()).
-
- //! This method returns a list containing an edge of the region's boundary
- //! as its first element, and all the internal vertices as the remaining elements.
- List *getRegionInternalVertices(List *l);
-
- //! Transform the vertices of the shell containing 't0' using the matrix m. O(S).
- void transformShell(Triangle *t0, const Matrix4x4& m);
-
- //! Translate the mesh by a vector
- void translate(const Point& t_vec);
-
- //! Return the center of mass of the mesh
- Point getCenter() const;
-
- //! Remove all the triangles belonging to the shell containing 't0'. O(N).
- void removeShell(Triangle *t0);
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Global Operations (Implemented in "MESH_STRUCTURE/tin.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
- //! Tag sharp edges based on threshold angle. O(N).
-
- //! Tag as sharp all the edges in which the normals of the two incident
- //! triangles form an angle greater than 't'.
- void sharpEdgeTagging(const double t);
-
- //! Unmark all the elements. O(N).
- void unmarkEverything();
-
- //! Bounding box longest edge. 'b' and 't' are set as the longest diagonal end-points. O(N).
- coord getBoundingBox(Point& b, Point& t) const;
-
- //! Bounding box longest diagonal. O(N).
- double bboxLongestDiagonal() { Point a, b; getBoundingBox(a, b); return a.distance(b); }
-
- //! Approximate bounding ball radius. O(N).
- double getBoundingBallRadius() const;
-
- //! Total area of the mesh. O(N).
- double area() const;
-
- //! Total volume of the mesh assuming that boundaries() = 0. O(N).
- double volume() const;
-
- //! Scale the mesh to make it fit within a cube [0,0,0]-[s,s,s]. O(N).
- void normalize(const coord s = 1.0);
-
- //! Scale the mesh to make it fit within a cube [0,0,0]-[s,s,s] and snap coordinates on grid points O(N).
- void quantize(const int s = 65536);
-
- //! Transform the mesh geometry using the transformation matrix m. O(N).
- void transform(const Matrix4x4& m);
-
- //! Randomly move vertices along their normals. O(N).
- //! Displacement is bounded by 'p'% of the bounding ball radius.
- void addNormalNoise(const double p);
-
- //! Iteratively swaps edges to minimize the Delaunay minimum angle. O(N).
-
- //! Edges tagged as sharp are constrained not to swap.
- //! On generically curved manifolds this process is not guaranteed to converge.
- //! This method returns TRUE if convergence is reached, FALSE otherwise.
- bool iterativeEdgeSwaps();
-
- //! True if the mesh properly contains 'p' (exact when using rationals).
- //! The mesh is assumed to be a well-defined polyhedron (i.e. no boundary,
- //! no degenerate triangles, no self-intersections) and to have a correct orientation:
- //! result is undetermined otherwise.
- bool isInnerPoint(Point& p) const;
-
- //! Performs one step of Loop subdivision. If 'midpoint' is set, only the connectivity
- //! is subdivided, whereas the surface shape is kept unchanged.
- void loopSubdivision(bool midpoint =false);
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Surface topology manipulation (Implemented in "MESH_STRUCTURE/tin.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
- //! Invert all the triangle and edge orientations. O(N).
- void flipNormals();
-
- //! Invert the orientation of triangles and edges belonging to the shell containing 't0'. O(S).
- void flipNormals(Triangle *t0);
-
- //! Return the triangle with the maximum 'z' coordinate in the shell containing 't0'. O(N).
-
- //! Useful for orienting meshes bounding solids.
- Triangle *topTriangle(Triangle *t0);
-
- //! Updates the values of n_boundaries, n_handles and n_shells. O(N).
-
- //! The relative dirty bits are set to zero.
- void eulerUpdate();
-
- //! Duplicates edges and vertices to make the mesh homeomorphic to a disk. O(N).
- void openToDisk();
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Topological fixes (Implemented in "MESH_STRUCTURE/checkAndRepair.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
- //! Removes all connected components but the one having most triangles.
- //! Returns the number of components removed.
- int removeSmallestComponents();
-
- //! Checks that triangles are consistently oriented and, if they are not,
- //! invert some of them to achieve an overall consistency. If the mesh is
- //! not orientable cut it. Returns: 0 if mesh was already oriented; 1 if
- //! the mesh could be oriented without cuts; >1 if cuts were necessary.
- int forceNormalConsistence();
-
- //! Same as above, but acts on a single connected component and uses one
- //! specific triangle from which the orientation is propagated.
- int forceNormalConsistence(Triangle *);
-
- //! Detect singular vertices and duplicte them. Return number of singular
- //! vertices being duplicated.
- int duplicateNonManifoldVertices();
-
- //! Remove redundant triangles (i.e. having the same vertices as others)
- //! and return their number.
- int removeDuplicatedTriangles();
-
- //! Check the mesh connectivity. If everything is fine NULL is returned,
- //! otherwise an error string is returned.
- const char *checkConnectivity();
-
- //! If called in rebuildConnectivity(bool) fix the connectivity between
- //! geometric elements
- bool fixConnectivity(); //!< AMF_ADD 1.1>
-
- //! Considers triangles as purely geometric entities and recomputes their
- //! connectivity based on vertex correspondence.
- //! Returns false if mesh was not an oriented manifold.
- TMESH_VIRTUAL bool rebuildConnectivity(bool = true); //!< AMF_CHANGE 1.1>
-
- //! Looks for topologically different edges having the same geometry
- //! (i.e. coincident vertices) and unify them. Return their number.
- int mergeCoincidentEdges();
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Geometrical fixes (Implemented in "MESH_STRUCTURE/checkAndRepair.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
- //! Looks for zero-area triangles and resolve them by splits and collapses.
- //! If, for any reason, some degeneracies cannot be removed
- //! a warning is issued and the degenerate triangles that could not
- //! be resolved are selected.
- //! The absolute value of the integer returned is the number of
- //! collapses performed; the return value is negative if some
- //! degenerate triangles could not be resolved.
- int removeDegenerateTriangles();
-
- //! Calls 'removeDegenerateTriangles()' and, if some degeneracies remain,
- //! removes them and fills the resulting holes. Then tries again and, if
- //! some degeneracies still remain, removes them and their neighbors and
- //! fills the resulting holes, and so on, until the neighborhood growth
- //! reaches max-iters. If even in this case some degeneracies remain,
- //! returns false, otherwise returns true.
- bool strongDegeneracyRemoval(int max_iters);
-
- //! Removes all the intersecting triangles and patches the resulting holes.
- //! If the patches still produce intersections, iterates again on a larger
- //! neighborhood. Tries up to max_iters times before giving up. Returns
- //! true only if all the intersections could be removed.
- bool strongIntersectionRemoval(int max_iters);
-
- //! Iteratively call strongDegeneracyRemoval and strongIntersectionRemoval
- //! to produce an eventually clean mesh without degeneracies and intersections.
- //! The two aforementioned methods are called up to max_iter times and
- //! each of them is called using 'inner_loops' as a parameter.
- //! Returns true only if the mesh could be completely cleaned.
- bool meshclean(int max_iters = 10, int inner_loops = 3);
-
- //! Removes overlapping triangles and return their number.
- int removeOverlappingTriangles();
-
- //! Checks the mesh for degeneracies, concident vertices and overlaps.
- //! If such a flaw is found returns its closest vertex.
- Vertex *checkGeometry();
-
- //! Selects all the triangles that unproperly intersect other parts of
- //! the mesh and return their number. The parameter 'tris_per_cell'
- //! determines the depth of the recursive space subdivision used to keep
- //! the complexity under a resonable threchold. The default value is safe
- //! in most cases.
- //! if 'justproper' is true, coincident edges and vertices are not regarded
- //! as intersections even if they are not common subsimplexes.
- int selectIntersectingTriangles(UINT16 tris_per_cell = 50, bool justproper = false);
-
-
- //! This is as coordBackApproximation() but it also checks for
- //! intersections and, if any, it tries different approximations.
- //! Returns true if no intersections remain.
- bool safeCoordBackApproximation();
-
- //! Removes all the connected components whose area is less than 'epsilon'.
- //! Returns the number of components removed.
- int removeSmallestComponents(double epsilon);
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Hole triangulation (Implemented in "MESH_STRUCTURE/holeFilling.cpp")
- //
- /////////////////////////////////////////////////////////////////////////////
-
- //! Computes the barycenter of the boundary loop and connects it with
- //! all the edges of the loop. Returns the number of triangles
- //! created.
- TMESH_VIRTUAL int StarTriangulateHole(Edge *);
-
- //! Creates a triangulation whose projection on the plane with normal 'nor'
- //! is Delaunay. Returns the number of triangles created.
- int TriangulateHole(Edge *, Point *nor);
-
- //! Creates a triangulation of the hole based on heuristics.
- //! Returns the number of triangles created.
- int TriangulateHole(Edge *);
-
- //! Creates a triangulation of the hole based on the assumption that it is flat.
- //! Returns the number of triangles created.
- // int TriangulateFlatHole(Edge *);
-
- //! Creates a triangulation and inserts the additional points in the List.
- //! Returns the number of triangles created.
- TMESH_VIRTUAL int TriangulateHole(Edge *, List *);
-
- //! Hole filling algorithm. Performs a triangulation based on heuristics and,
- //! if 'refine' is set to true, adds inner vertices to reproduce the sampling
- //! density of the surroundings.
- void FillHole(Edge *, bool refine = true);
-
- //! Fills all the holes having at least 'nbe' boundary edges. If 'refine'
- //! is true, adds inner vertices to reproduce the sampling density
- //! of the surroundings. Returns number of holes patched.
- //! If 'nbe' is 0 (default), all the holes are patched.
- int fillSmallBoundaries(int nbe = 0, bool refine = true);
-
- //! Takes a selected region and inserts inner vertices to reproduce the
- //! sampling density of the surroundings. If 't0' is not NULL, only the
- //! selected region containing 't0' is refined. Returns the number of
- //! vertices inserted.
- TMESH_VIRTUAL int refineSelectedHolePatches(Triangle *t0 =NULL);
-
- //! Retriangulates the vertex neghborhood based on heuristics.
- int retriangulateVT(Vertex *);
-
- //! Joins the two boundary vertices gv and gw through an edge. A pair of triangles is
- //! added to properly change the topology of the mesh.
- Edge *joinBoundaryLoops(Vertex *, Vertex *, bool = 0, bool = 1);
-
- // Debug and work-in-progress
-
- void printReport();
-
- protected:
- Vertex *watsonInsert(Point *, List *, int);
- };
-
-#define FOREACHTRIANGLE(Tt, n) for (n = T.head(), Tt = (n)?((Triangle *)n->data):NULL; n != NULL; n=n->next(), Tt = (n)?((Triangle *)n->data):NULL)
-#define FOREACHEDGE(Tt, n) for (n = E.head(), Tt = (n)?((Edge *)n->data):NULL; n != NULL; n=n->next(), Tt = (n)?((Edge *)n->data):NULL)
-#define FOREACHVERTEX(Tt, n) for (n = V.head(), Tt = (n)?((Vertex *)n->data):NULL; n != NULL; n=n->next(), Tt = (n)?((Vertex *)n->data):NULL)
-
-#define MARK_VISIT(a) ((a)->mask |= ((unsigned char)1))
-#define IS_VISITED(a) ((a)->mask & ((unsigned char)1))
-#define UNMARK_VISIT(a) ((a)->mask &= (~((unsigned char)1)))
-
-#define MARK_VISIT2(a) ((a)->mask |= ((unsigned char)2))
-#define IS_VISITED2(a) ((a)->mask & ((unsigned char)2))
-#define UNMARK_VISIT2(a) ((a)->mask &= (~((unsigned char)2)))
-
-#define MARK_BIT(a,b) ((a)->mask |= ((unsigned char)(1<mask & ((unsigned char)(1<mask &= (~((unsigned char)(1<commonVertex(e2);} //!< First vertex
- Vertex *v2() const {return e2->commonVertex(e3);} //!< Second vertex
- Vertex *v3() const {return e3->commonVertex(e1);} //!< Third vertex
-
- //! First adjacent triangle. NULL if boundary.
- Triangle *t1() const {return e1->oppositeTriangle(this);}
-
- //! Second adjacent triangle. NULL if boundary.
- Triangle *t2() const {return e2->oppositeTriangle(this);}
-
- //! Third adjacent triangle. NULL if boundary.
- Triangle *t3() const {return e3->oppositeTriangle(this);}
-
- //! TRUE iff 'e' is an edge of the triangle.
- bool hasEdge(const Edge *e) const {return (e==e1 || e==e2 || e==e3);}
-
- //! TRUE iff 'v' is a vertex of the triangle.
- bool hasVertex(const Vertex *v) const {return (e1->hasVertex(v) || e2->hasVertex(v) || e3->hasVertex(v));}
-
- //! Triangle's edge opposite to 'v'. NULL if 'v' is not a vertex of the triangle.
- Edge *oppositeEdge(const Vertex *v) const
- {return ((!e1->hasVertex(v))?(e1):((!e2->hasVertex(v))?(e2):((!e3->hasVertex(v))?(e3):(NULL))));}
-
- //! Adjacent triangle opposite to 'v'. NULL if 'v' is not a vertex of the triangle.
- Triangle *oppositeTriangle(const Vertex *v) const
- {return ((!e1->hasVertex(v))?(t1()):((!e2->hasVertex(v))?(t2()):((!e3->hasVertex(v))?(t3()):(NULL))));}
-
- //! Triangle's vertex opposite to 'e'. NULL if 'e' is not an edge of the triangle.
- Vertex *oppositeVertex(const Edge *e) const
- {return (e==e1)?(v2()):((e==e2)?(v3()):((e==e3)?(v1()):(NULL)));}
-
- //! Triangle adjacent to the next edge of 'e'. NULL if 'e' is not an edge of the triangle.
- Triangle *rightTriangle(const Edge *e) const
- {return (e==e1)?(t2()):((e==e2)?(t3()):((e==e3)?(t1()):(NULL)));}
-
- //! Triangle adjacent to the previous edge of 'e'. NULL if 'e' is not an edge of the triangle.
- Triangle *leftTriangle(const Edge *e) const
- {return (e==e1)?(t3()):((e==e2)?(t1()):((e==e3)?(t2()):(NULL)));}
-
- //! Edge next to 'e' in the ordering or the triangle. NULL if 'e' is not an edge of the triangle.
- Edge *nextEdge(const Edge *e) const {return ((e==e1)?(e2):((e==e2)?(e3):((e==e3)?(e1):(NULL))));}
-
- //! Edge preceeding 'e' in the ordering or the triangle. NULL if 'e' is not an edge of the triangle.
- Edge *prevEdge(const Edge *e) const {return ((e==e1)?(e3):((e==e2)?(e1):((e==e3)?(e2):(NULL))));}
-
- //! Vertex next to 'v' in the ordering or the triangle. NULL if 'v' is not a vertex of the triangle.
- Vertex *nextVertex(const Vertex *v) const
- {return (!e1->hasVertex(v))?(v3()):((!e2->hasVertex(v))?(v1()):((!e3->hasVertex(v))?(v2()):(NULL)));}
-
- //! Vertex preceeding 'v' in the ordering or the triangle. NULL if 'v' is not a vertex of the triangle.
- Vertex *prevVertex(const Vertex *v) const
- {return (!e1->hasVertex(v))?(v1()):((!e2->hasVertex(v))?(v2()):((!e3->hasVertex(v))?(v3()):(NULL)));}
-
- //! Edge next to 'e' in the ordering or the triangle. NULL if 'e' is not an edge of the triangle.
- Edge *nextEdge(const Vertex *v) const { return (v == v1()) ? (e2) : ((v == v2()) ? (e3) : ((v == v3()) ? (e1) : (NULL))); }
-
-
- //! If this triangle shares an edge with 'b', then such an edge is returned. NULL otherwise.
- Edge *commonEdge(const Triangle *b) const
- {return ((e1 == b->e1 || e1 == b->e2 || e1 == b->e3)?(e1):\
- (((e2 == b->e1 || e2 == b->e2 || e2 == b->e3)?(e2):\
- (((e3 == b->e1 || e3 == b->e2 || e3 == b->e3)?(e3):(NULL))))));}
-
- //! If this triangle shares a vertex with 'b', then such a vertex is returned. NULL otherwise.
- Vertex *commonVertex(const Triangle *b) const;
-
- //! Replace edge 'a' with edge 'b' in the triangle and return TRUE. If 'a' is not an edge of the triangle return FALSE.
- bool replaceEdge(const Edge *a, Edge *b)
- {if (e1==a) e1=b; else if (e2==a) e2=b; else if (e3==a) e3=b; else return 0; return 1;}
-
- //! TRUE if the oriantation is consistent with the one of 't' OR if this and 't' do not share any edge.
- bool checkAdjNor(const Triangle *t) const;
-
- //! Return a vector orthogonal to the plane of the triangle. If triangle is degenerate return a null vector.
- Point getVector() const;
-
- //! Return the triangle's barycenter.
- Point getCenter() const;
-
- //! Return the center of the triangle's bounding sphere.
- Point getCircleCenter() const;
-
- //! TRUE iff 'p' is inside the triangle's bounding sphere.
- bool inSphere(const Point *p) const;
-
- //! Squared distance of 'p' from the plane of the triangle. Return -1 if triangle is degenerate.
- coord squaredDistanceFromPoint(const Point *p) const;
-
- //! Squared distance of 'p' from the closest point of the triangle. Return -1 if triangle is degenerate.
- //! If closest point is in the interior of the triangle, *closest_edge and *closest_vertex are set to NULL.
- //! If the closest point is in the interior of an edge, *closest_edge is initialized with that edge.
- //! If the closest point is a vertex, *closest_vertex is initialized with it.
- coord pointTriangleSquaredDistance(const Point *p, Edge **closest_edge =NULL, Vertex **closest_vertex =NULL) const;
-
- //! Projection of 'p' on the plane of the triangle. Return INFINITE_POINT if triangle is degenerate.
- Point project(const Point *p) const;
-
- //! Returns the longest edge of the triangle.
- Edge *getLongestEdge() const;
-
- //! Degeneracy check using exact predicates. Return TRUE iff triangle has zero area.
- bool isExactlyDegenerate() const;
-
- //! Returns the edge opposite to a 'cap' vertex
- Edge *getCapEdge() const;
-
- //! Print the coordinates of the three vertices to the file handler pointed to by 'f' (stdout by default).
- void printTriangle(FILE *f =stdout) const;
-
- //! true if this triangle itersects 't' other than on common subsimplexes
- //! if 'justproper' is true, coincident edges and vertices are not regarded
- //! as intersections even if they are not common subsimplexes.
- bool intersects(const Triangle *t, bool justproper =false) const;
-
- // FUNCTIONS BELOW THIS LINE MAY RETURN APPROXIMATED/NOT ROBUST RESULTS EVEN WHEN USING RATIONALS
-
-
-
- //! Return a normal vector with direction (v1-v2) cross (v2-v3). If triangle is degenerate return a null vector.
- Point getNormal() const;
-
- //! Area of the triangle (Heron's formula).
- double area() const;
-
- //! Perimeter of the triangle.
- double perimeter() const;
-
- //! Angle at vertex 'v'. Return -1 if 'v' is not a vertex of the triangle.
- double getAngle(const Vertex *v) const;
-
- //! Angle between the normal vector of this and the one of 't'. Return -1 if one or both the triangles are degenerate.
- double getDAngle(const Triangle *t) const;
-
- //! Distance of 'p' from the plane of the triangle. Return -1 if triangle is degenerate.
- double distanceFromPoint(const Point *p) const;
-
- //! Distance of 'p' from the closest point of the triangle. Return -1 if triangle is degenerate.
- //! If 'c' is not NULL, its coordinates are set to the ones of the closest point.
- double pointTriangleDistance(const Point *p, Point *c = NULL) const;
-
- //! Return TRUE iff one of the adjacent triangles overlaps with this one
- bool overlaps() const;
-};
-
-#define FOREACHTRIANGLEEDGE(t, e) for ((e) = (t)->e1; (e) != NULL; (e)=((e)==(t)->e3)?(NULL):((t)->nextEdge(e)))
-
-} //namespace T_MESH
-
-#endif // _TRIANGLE_H
-
diff --git a/src/mesh_fix/include/TMesh/vertex.h b/src/mesh_fix/include/TMesh/vertex.h
deleted file mode 100644
index e43b898b9..000000000
--- a/src/mesh_fix/include/TMesh/vertex.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#ifndef _VERTEX_H
-#define _VERTEX_H
-
-#include "basics.h"
-#include "list.h"
-#include "point.h"
-
-namespace T_MESH
-{
-
-//! Vertex of a Basic_TMesh
-
-//! This class represents a vertex of a manifold and oriented triangulation.
-//! The base-class Point
-//! describes geometrical and additional attributes of the vertex. The
-//! field 'e0' is sufficient to retrieve all the neighboring elements in
-//! optimal time, while the field 'mask' is useful for assigning up to 256
-//! different states to the vertex.
-
-
-class Vertex : public Point
-{
- public :
- class Edge *e0; //!< One of the incident edges
- unsigned char mask; //!< bit-mask for marking purposes
-
- //! Creates a new vertex with coordinates (0,0,0).
- Vertex();
-
- //! Creates a new vertex with the same coordinates (x,y,z).
- Vertex(const coord& x, const coord& y, const coord& z);
-
- //! Creates a new vertex with the same coordinates as 'p'. The info field is not copied.
- Vertex(const Point *p);
-
- //! Creates a new vertex with the same coordinates as 'p'. The info field is not copied.
- Vertex(const Point& p);
- ~Vertex(); //!< Destructor
-
- //! Returns true only if object is a basic Vertex. All the reimplementations must return false.
- TMESH_VIRTUAL bool isBaseType() const { return true; }
-
- bool isLinked() const {return (e0!=0);} //!< TRUE iff vertex is not isolated
-
- //! List of adjacent vertices.
-
- //! Returns the list of vertices which are linked to this through an edge.
- //! The list is counter-clockwise ordered. In the case of an internal ver-
- //! tex the list starts from the opposite vertex of e0. If the vertex is on
- //! the boundary, the list starts from the opposite vertex of the clock-
- //! wise-most boundary edge.
- List *VV() const;
-
- //! List of incident edges.
-
- //! Returns the list of edges incident at this vertex. The list is counter-clockwise
- //! ordered. In the case of an internal vertex the list starts from 'e0'
- //! If the vertex is on the boundary, the list starts from its clockwise-most
- //! incident boundary edge.
- List *VE() const;
-
- //! List of incident triangles.
-
- //! Returns the list of triangles incident at this. The list is counter-
- //! clockwise ordered. In the case of an internal vertex the list starts
- //! from the triangle on the left of e0, when looking from this. If the
- //! vertex is on the boundary, the list starts from the clockwise-most
- //! boundary triangle.
- List *VT() const;
-
- //! Returns the edge connecting this vertex to 'v'. NULL if such an edge does not exist.
- class Edge *getEdge(const Vertex *v) const;
- int valence() const; //!< Returns the number of incident edges
- int isOnBoundary() const; //!< TRUE iff vertex is on boundary
-
- //! Returns the edge following this vertex on the boundary.
-
- //! This edge is the counterclockwise-most incident edge.
- //! Returns NULL if this vertex is not on the boundary.
- Edge *nextBoundaryEdge() const;
-
- //! Returns the edge preceeding this vertex on the boundary.
-
- //! This edge is the clockwise-most incident edge.
- //! Returns NULL if this vertex is not on the boundary.
- Edge *prevBoundaryEdge() const;
-
- //! Returns the vertex following this one on the boundary.
-
- //! If the vertex is on the boundary, this is equivalent to nextBoundaryEdge()->oppositeVertex(v)
- //! otherwise returns NULL.
- Vertex *nextOnBoundary() const;
-
- //! Returns the vertex preceeding this one on the boundary.
-
- //! If the vertex is on the boundary, this is equivalent to prevBoundaryEdge()->oppositeVertex(v)
- //! otherwise returns NULL.
- Vertex *prevOnBoundary() const;
-
- //! TRUE iff vertex neighborhood is a flat disk. Always FALSE for boundary vertices.
- bool isFlat() const;
-
- //! TRUE iff vertex neighborhood is made of either two flat halfdisks or one flat halfdisk on a rectilinear boundary.
- //! When TRUE, the two edges may be initialized with the two non-flat incident edges.
- //! If the two halfdisks are also coplanar, returns TRUE and e1 and e2 are set to NULL.
- bool isDoubleFlat(Edge **e1, Edge **e2) const;
-
- //! Unlinks the vertex if it is either Flat() or DoubleFlat(). On success, the function returns TRUE,
- //! the vertex neighborhood is retriangulated, and the geometric realization does not change.
- //! If 'check_neighborhood' is 'false', incident triangles are assumed to be neither degenerate nor
- //! overlapping.
- //! Attention! The method unlinks the vertex but does not remove it from the Basic_TMesh list. The
- //! calling function must clear the lists through Basic_TMesh::removeUnlinkedElements().
- bool removeIfRedundant(bool check_neighborhood = true);
-
- //! Normal at the vertex computed as the sum of incident triangle normals weighted on their incidence angle.
- Point getNormal() const;
-
- //! Returns the angle between the two incident boundary edges. If the vertex is not on the boundary, returns -1.
- double getBoundaryAngle() const;
-
- //! Discriminant Angle for triangulating 3D polygons.
-
- //! This method is useful when patching holes, and represents a heuristic
- //! for choosing which vertex of the hole's boundary must be patched first.
- //! Several cases are considered, including degenerate ones. Let 'v1' and 'v2'
- //! be the two boundary vertices which are linked to this one through a boundary
- //! edge. If 'v1' and 'v2' coincide, the method returns a negative number.
- //! If 'v1' , 'this' , 'v2' form a flat angle, the method returns 3PI (270
- //! degrees). If the angle formed by 'v1' , 'this' , 'v2' is 0, the method
- //! returns 0. If the vertex is not on the boundary, the method returns the
- //! limit number DBL_MAX. In all the other cases the method returns the sum
- //! of three angles A + D1 + D2, where A is the angle formed by v1 , this ,
- //! v2 , while D1 is the angle between the normal of the clockwise-most
- //! incident boundary triangle and the normal of the triangle v1 , this ,
- //! v2; D2 is the analogous for the counterclockwise-most incident boundary
- //! triangle.
- double getAngleForTriangulation() const;
-
- //! Discriminant Angle for triangulating flat (or nearly flat) polygons.
-
- //! This method returns the angle between the two incident boundary edges
- //! when projected onto the plane whose normal is 'n'. This angle
- //! may be more than PI, because it represents the aperture of the non-tri-
- //! angulated region around the vertex when projected on the plane. If the
- //! vertex is not on the boundary, the method returns the limit value
- //! DBL_MAX.
- double getAngleOnAveragePlane(Point *n) const;
-
- double totalAngle() const; //!< Sum of incident angles. Returns -1 if on boundary.
-
- //! Excess angle. Returns DBL_MAX if on boundary.
- double gaussianCurvature() const {double t=totalAngle(); return (t>=0)?(t):(DBL_MAX);}
-
- double totalDihedralAngle() const; //!< Sum of signed dihedral angles. Returns DBL_MAX if on boundary.
- double voronoiArea() const; //!< A third of the total area of incident triangles.
-
- //! Zips the gap starting from here.
- int zip(const bool =1);
-
-// Edge *inverseCollapse(Vertex *, Vertex *, Vertex *);
- Edge *inverseCollapse(Vertex *, Edge *, Edge *, Edge *, Edge *, Edge *, class Triangle *, class Triangle *);
-};
-
-//! Scans the nodes 'n' of a list 'l' of vertices 'v'.
-#define FOREACHVVVERTEX(l, v, n) for (n = l->head(), v = (n)?((Vertex *)n->data):NULL; n != NULL; n=n->next(), v = (n)?((Vertex *)n->data):NULL)
-
-//! Scans the nodes 'n' of a list 'l' of edges 'e'.
-#define FOREACHVEEDGE(l, e, n) for (n = l->head(), e = (n)?((Edge *)n->data):NULL; n != NULL; n=n->next(), e = (n)?((Edge *)n->data):NULL)
-
-//! Scans the nodes 'n' of a list 'l' of triangles 't'.
-#define FOREACHVTTRIANGLE(l, t, n) for (n = l->head(), t = (n)?((T_MESH::Triangle *)n->data):NULL; n != NULL; n=n->next(), t = (n)?((T_MESH::Triangle *)n->data):NULL)
-
-
-//! Extended vertex for temporary use during connectivity creation.
-
-//! This class is used to allow the reconstruction of the connectivity
-//! in linear time (average case) and to handle badly oriented input files.
-//! It provides a complete VE relation.
-
-class ExtVertex
-{
- public :
- Vertex *v;
- List VE;
-
- ExtVertex(Vertex *a) {v=a;}
-};
-
-} //namespace T_MESH
-
-#endif //_VERTEX_H
-
diff --git a/src/mesh_fix/src/Algorithms/checkAndRepair.cpp b/src/mesh_fix/src/Algorithms/checkAndRepair.cpp
deleted file mode 100644
index 263046a1d..000000000
--- a/src/mesh_fix/src/Algorithms/checkAndRepair.cpp
+++ /dev/null
@@ -1,1057 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "tmesh.h"
-#include "jqsort.h"
-#include
-#include
-
-namespace T_MESH
-{
-
-////////////// Checks the triangulation's connectivity //////////////
-//
-// This method should be used when implementing new algorithms to
-// check the consistency of the connectivity graph. Because an
-// inconsistent graph is not assumed by all the other methods, such
-// a flaw is considered critical and the program should terminate.
-// If connectivity is ok, NULL is returned, otherwise a string
-// describing the error is returned.
-//
-/////////////////////////////////////////////////////////////////////
-
-const char *Basic_TMesh::checkConnectivity()
-{
- Vertex *v;
- Edge *e,*e2;
- Triangle *t;
- Node *n,*m;
- List *ve;
-
- FOREACHVERTEX(v, n)
- {
- if (v == NULL) return "checkConnectivity: detected NULL element in V list!";
- if (v->e0 == NULL) return "checkConnectivity: detected NULL e0 pointer for a vertex!";
- if (!v->e0->hasVertex(v)) return "checkConnectivity: detected wrong e0 pointer for a vertex!";
- }
-
- FOREACHEDGE(e, n)
- {
- if (e == NULL) return "checkConnectivity: detected NULL element in E list!";
- if (e->v1 == NULL || e->v2 == NULL) return "checkConnectivity: detected edge with one or two NULL end-points!";
- if (e->v1 == e->v2) return "checkConnectivity: detected edge with two coincident end-points!";
- if (e->t1 == NULL && e->t2 == NULL) return "checkConnectivity: detected edge with no incident triangles!";
- if (e->t1 != NULL)
- {
- if (!e->t1->hasEdge(e)) return "checkConnectivity: detected wrong t1 triangle at an edge";
- if (e->commonVertex(e->t1->nextEdge(e)) == e->v1)
- return "checkConnectivity: Edge orientation does not match t1 normal";
- }
- if (e->t2 != NULL)
- {
- if (!e->t2->hasEdge(e)) return "checkConnectivity: detected wrong t2 triangle at an edge";
- if (e->commonVertex(e->t2->nextEdge(e)) == e->v2)
- return "checkConnectivity: Edge orientation does not match t2 normal";
- }
- }
-
- FOREACHTRIANGLE(t, n)
- {
- if (t == NULL) return "checkConnectivity: detected NULL element in T list!";
- if (t->e1 == NULL || t->e2 == NULL || t->e3 == NULL) return "checkConnectivity: detected NULL as a triangle edge!";
- if (t->e1 == t->e2 || t->e1 == t->e3 || t->e2 == t->e3) return "checkConnectivity: detected triangle with two coincident edges!";
- if (t->v1() == NULL || t->v2() == NULL || t->v3() == NULL) return "checkConnectivity: triangle edges do not share vertices!";
- if (t->e1->t1 != t && t->e1->t2 != t) return "checkConnectivity: detected triangle with 1st edge not pointing to the triangle itself!";
- if (t->e2->t1 != t && t->e2->t2 != t) return "checkConnectivity: detected triangle with 2nd edge not pointing to the triangle itself!";
- if (t->e3->t1 != t && t->e3->t2 != t) return "checkConnectivity: detected triangle with 3rd edge not pointing to the triangle itself!";
- }
-
- FOREACHEDGE(e, n)
- {
- ve = e->v1->VE();
- FOREACHVEEDGE(ve, e2, m)
- {
- if (e2 != e && e2->oppositeVertex(e->v1) == e->v2) return "checkConnectivity: detected duplicate edge!";
- }
- if (ve->containsNode(e) == NULL) return "checkConnectivity: detected non manifold vertex!";
- delete(ve);
- ve = e->v2->VE();
- FOREACHVEEDGE(ve, e2, m)
- {
- if (e2 != e && e2->oppositeVertex(e->v2) == e->v1) return "checkConnectivity: detected duplicate edge!";
- }
- if (ve->containsNode(e) == NULL) return "checkConnectivity: detected non manifold vertex!";
- delete(ve);
- }
-
- return NULL;
-}
-
-
-////////////// Duplicate non-manifold vertices /////////////////////
-//
-// If a vertex is topologically non-manifold, this data structure
-// does not guarantee its functionality. Therefore, in order to use
-// the same triangle mesh, this method allows to duplicate such
-// vertices. Notice that the data-structure cannot code non-manifold
-// edges.
-//
-////////////////////////////////////////////////////////////////////
-
-int Basic_TMesh::duplicateNonManifoldVertices()
-{
- Vertex *v;
- Edge *e, *f;
- Node *n, *m;
- List *ve;
- int dv = 0;
-
- FOREACHEDGE(e, n)
- {
- ve = e->v1->VE();
- if (ve->containsNode(e) == NULL)
- {
- v = newVertex(e->v1); //!
- v->info = e->v1->info; //! < AMF_CHANGE 1.1-2 >
- v->mask = 0; //!
- V.appendHead(v);
-
- FOREACHVEEDGE(ve, f, m) f->replaceVertex(e->v1, v);
- v->e0 = e->v1->e0;
- e->v1->e0 = e;
- dv++;
- }
- delete(ve);
- }
- FOREACHEDGE(e, n)
- {
- ve = e->v2->VE();
- if (ve->containsNode(e) == NULL)
- {
- v = newVertex(e->v2); //!
- v->info = e->v2->info; //! < AMF_CHANGE 1.1-2 >
- v->mask = 0; //!
- V.appendHead(v);
-
- FOREACHVEEDGE(ve, f, m) f->replaceVertex(e->v2, v);
- v->e0 = e->v2->e0;
- e->v2->e0 = e;
- dv++;
- }
- delete(ve);
- }
-
- if (dv) d_boundaries = d_handles = d_shells = 1;
-
- return dv;
-}
-
-////////////// Checks the triangulation geometry //////////////
-//// //////
-//// Looks for coincident vertices, degenerate triangles //////
-//// and overlapping triangles. //////
-//// If something is wrong returns the closest vertex. //////
-//// //////
-///////////////////////////////////////////////////////////////
-
-Vertex *Basic_TMesh::checkGeometry()
-{
- int i;
- Vertex *ret = NULL;
- double ang, minda = 0;
- Triangle *t;
- Edge *e;
- Vertex **varr = (Vertex **)V.toArray();
- Edge **evarr;
- Vertex *v1, *v2;
- Node *n;
-
- if (varr == NULL) TMesh::warning("checkGeometry: Not enough memory. Can't check for coincident vertices.\n");
- else
- {
- jqsort((Data **)varr, V.numels(), xyzCompare);
- for (i=0; i<(V.numels()-1); i++)
- {
- v1 = ((Vertex *)varr[i]);
- v2 = ((Vertex *)varr[i+1]);
- if ((*v1)==(*v2))
- {
- ret = v1;
- TMesh::warning("checkGeometry: detected coincident vertices.\n");
- if (v1->getEdge(v2))
- {
- TMesh::warning(" and there is an edge connecting them!\n");
- free(varr);
- return v1;
- }
- }
- }
- free(varr);
- }
-
- evarr = (Edge **)E.toArray();
- if (evarr == NULL) TMesh::warning("checkGeometry: Not enough memory. Can't check for coincident edges.\n");
- else
- {
- jqsort((Data **)evarr, E.numels(), lexEdgeCompare);
- for (i=0; i<(E.numels()-1); i++)
- {
- if (!lexEdgeCompare(evarr[i], evarr[i+1]))
- {
- ret = ((Edge *)evarr[i])->v1;
- TMesh::warning("checkGeometry: detected coincident edges.\n");
- }
- }
- free(evarr);
- }
-
- FOREACHTRIANGLE(t, n)
- {
- ang = t->getAngle(t->v1());
- if (ang == 0 || ang == M_PI) {TMesh::warning("checkGeometry: degenerate triangle detected.\n"); return t->v1();}
- ang = t->getAngle(t->v2());
- if (ang == 0 || ang == M_PI) {TMesh::warning("checkGeometry: degenerate triangle detected.\n"); return t->v2();}
- ang = t->getAngle(t->v3());
- if (ang == 0 || ang == M_PI) {TMesh::warning("checkGeometry: degenerate triangle detected.\n"); return t->v3();}
- }
-
- ang = minda = 0;
- FOREACHEDGE(e, n)
- if (e->t1 != NULL && e->t2 != NULL && (ang = e->t1->getDAngle(e->t2)) == M_PI)
- {TMesh::warning("checkGeometry: overlapping triangles detected.\n"); return e->v1;}
- else minda = MAX(minda,ang);
- TMesh::info("checkGeometry: minimum dihedral angle = %f (%f DEGs)\n", M_PI-minda, ((M_PI-minda)*360)/(2*M_PI));
- return ret;
-}
-
-
-///// Merges possible coincident edges //////////
-
-int Basic_TMesh::mergeCoincidentEdges()
-{
- V.sort(&xyzCompare);
- Node *n;
- Vertex *v, *pv = (Vertex *)V.head()->data;
-
- FOREACHVERTEX(v, n) UNMARK_BIT(v, 5);
-
- Edge *e;
- FOREACHEDGE(e, n) if (e->isOnBoundary()) { MARK_BIT(e->v1, 5); MARK_BIT(e->v2, 5); }
-
- FOREACHVERTEX(v, n)
- {
- if ((*v) != (*pv) || !IS_BIT(v,5)) pv = v;
- v->info = pv;
- UNMARK_BIT(v, 5);
- }
-
- // At this point any vertex points (through 'info') to its unique representative (possibly itself)
-
- FOREACHVERTEX(v, n) v->e0 = NULL;
-
- FOREACHEDGE(e, n)
- {
- if (e->v1->info != e->v1) e->v1 = (Vertex *)e->v1->info;
- if (e->v2->info != e->v2) e->v2 = (Vertex *)e->v2->info;
- e->v1->e0 = e->v2->e0 = e;
- }
- removeVertices();
-
- // At this point the mesh should no longer have duplicated vertices, but may have duplicated edges
- E.sort(&vtxEdgeCompare);
- Edge *pe = (Edge *)E.head()->data;
- FOREACHEDGE(e, n)
- {
- if (!e->isOnBoundary() || vtxEdgeCompare(e, pe)) pe = e;
- e->info = pe;
- }
- FOREACHEDGE(e, n) if (e->info != e)
- {
- Triangle *t1 = e->getBoundaryTriangle();
- Edge *f = ((Edge *)e->info);
- t1->replaceEdge(e, f);
- ((f->t1 == NULL) ? (f->t1) : (f->t2)) = t1;
- e->v1 = e->v2 = NULL;
- f->v1->e0 = f->v2->e0 = f;
- }
- removeUnlinkedElements();
-
- return 1;
-}
-
-///// Fix geometric connectivity //////////
-
-bool Basic_TMesh::fixConnectivity(){ //!< AMF_ADD 1.1>
- bool retval = true;
- int i;
-
- if ((i = removeVertices())) { retval = false; TMesh::warning("%d isolated vertices have been removed.\n", i); }
- if (cutAndStitch()) { retval=false; TMesh::warning("Some cuts were necessary to cope with non manifold configuration.\n"); }
- if (forceNormalConsistence()) { retval = false; TMesh::warning("Some triangles have been reversed to achieve orientation.\n"); }
- if ((i=duplicateNonManifoldVertices())) { retval=false; TMesh::warning("%d non-manifold vertices have been duplicated.\n",i); }
- if ((i=removeDuplicatedTriangles())) { retval=false; TMesh::warning("%d double-triangles have been removed.\n",i); }
-
- return retval;
-}
-
-///// Recompute triangle connectivity //////////
-
-bool Basic_TMesh::rebuildConnectivity(bool fixconnectivity) //!< AMF_CHANGE 1.1>
-{
- if (V.numels() == 0) return false;
- V.sort(&xyzCompare);
- Node *n;
- Vertex *v, *pv=(Vertex *)V.head()->data;
-
- FOREACHVERTEX(v,n)
- {
- if ((*v)!=(*pv)) pv=v;
- v->info = pv;
- }
-
- // At this point any vertex points (through 'info') to its unique representative (possibly itself)
-
- FOREACHVERTEX(v,n) v->e0=NULL;
-
- Edge *e;
- FOREACHEDGE(e, n)
- {
- if (e->v1->info != e->v1) e->v1 = (Vertex *)e->v1->info;
- if (e->v2->info != e->v2) e->v2 = (Vertex *)e->v2->info;
- e->v1->e0 = e->v2->e0 = e;
- }
- int rv = removeVertices();
-
- // At this point the mesh should no longer have duplicated vertices, but may have duplicated edges
-
- Triangle *t;
- ExtVertex **var = new ExtVertex *[V.numels()];
- int i=0;
- FOREACHVERTEX(v, n) { v->e0 = NULL; var[i] = new ExtVertex(v); v->info = new intWrapper(i); i++; }
- int nt = T.numels();
- int *triangles = new int[nt*3];
- i = 0; FOREACHTRIANGLE(t, n)
- {
- triangles[i * 3] = ((intWrapper*)t->v1()->info)->operator int();
- triangles[i*3+1] = ((intWrapper*)t->v2()->info)->operator int();
- triangles[i*3+2] = ((intWrapper*)t->v3()->info)->operator int();
- i++;
- }
- T.freeNodes();
- E.freeNodes();
- int v1,v2,v3;
- for (i = 0; iisOnBoundary() && e->t1->oppositeVertex(e) == e->t2->oppositeVertex(e))
- {
- unlinkTriangle(e->t2);
- i++;
- }
- removeUnlinkedElements();
-
- if (i) d_boundaries = d_handles = d_shells = 1;
-
- return i;
-}
-
-
-//////// Split an edge at all the vertices belonging to its inner segment /////////
-
-int multiSplitEdge(Basic_TMesh *tin, Edge *e)
-{
- List splitVertices;
- List triangles, tounmark;
- MARK_BIT(e, 5);
- if (e->t1 != NULL) { triangles.appendTail(e->t1); MARK_BIT(e->t1, 5); }
- if (e->t2 != NULL) { triangles.appendTail(e->t2); MARK_BIT(e->t2, 5); }
-
- Triangle *t, *y;
- Vertex *v;
-
- while ((t = (Triangle *)triangles.popHead()) != NULL)
- {
- tounmark.appendHead(t);
- int num_front_edges = 0;
- if (IS_BIT(t->e1, 5)) num_front_edges++;
- if (IS_BIT(t->e2, 5)) num_front_edges++;
- if (IS_BIT(t->e3, 5)) num_front_edges++;
- if (num_front_edges == 3) continue;
- if (num_front_edges == 1)
- {
- Edge *f = (IS_BIT(t->e1, 5)) ? (t->e1) : ((IS_BIT(t->e2, 5)) ? (t->e2) : (t->e3));
- v = t->oppositeVertex(f);
- if (!v->exactMisalignment(e->v1, e->v2))
- {
- if (!IS_BIT(v, 5) && Point::pointInInnerSegment(v, e->v1, e->v2)) { splitVertices.appendTail(v); MARK_BIT(v, 5); }
- y = t->nextEdge(f)->oppositeTriangle(t); if (y != NULL && !IS_BIT(y, 5)) { triangles.appendTail(y); MARK_BIT(y, 5); }
- y = t->prevEdge(f)->oppositeTriangle(t); if (y != NULL && !IS_BIT(y, 5)) { triangles.appendTail(y); MARK_BIT(y, 5); }
- }
- }
- MARK_BIT(t->e1, 5); MARK_BIT(t->e2, 5); MARK_BIT(t->e3, 5);
- }
-
- Node *n;
- FOREACHVTTRIANGLE((&tounmark), t, n) { UNMARK_BIT(t, 5); UNMARK_BIT(t->e1, 5); UNMARK_BIT(t->e2, 5); UNMARK_BIT(t->e3, 5); }
- FOREACHVVVERTEX((&splitVertices), v, n) UNMARK_BIT(v, 5);
-
- while (splitVertices.numels())
- {
- coord ad, mind = DBL_MAX;
- Vertex *gv = nullptr;
- FOREACHVVVERTEX((&splitVertices), v, n) if ((ad = v->squaredDistance(e->v2)) < mind) { gv = v; mind = ad; }
- splitVertices.removeNode(gv);
- tin->splitEdge(e, gv);
- }
-
- return 1;
-}
-
-//////// Split caps and collapse needles to eliminate degenerate triangles /////////
-
-int Basic_TMesh::removeDegenerateTriangles()
-{
- Node *n;
- Triangle *t;
- Edge *e, *e1, *e2, *e3, *e4;
- Vertex *ov1, *ov2, *splitvs[2];
- int nov;
-
- List edges(E);
- FOREACHVEEDGE((&edges), e, n) MARK_BIT(e, 5);
-
- while ((e = (Edge *)edges.popHead()) != NULL) // Split caps
- {
- UNMARK_BIT(e, 5);
- nov = 0;
- ov1 = (e->t1 != NULL) ? (e->t1->oppositeVertex(e)) : NULL;
- ov2 = (e->t2 != NULL) ? (e->t2->oppositeVertex(e)) : NULL;
- if (ov1 != NULL && Point::pointInInnerSegment(ov1, e->v1, e->v2)) splitvs[nov++] = ov1;
- if (ov2 != NULL && Point::pointInInnerSegment(ov2, e->v1, e->v2)) splitvs[nov++] = ov2;
- if (nov == 1) splitvs[1] = splitvs[0];
- if (nov > 1 && ov1->squaredDistance(e->v1) > ov2->squaredDistance(e->v1)) { splitvs[0] = ov2; splitvs[1] = ov1; }
-
- if (nov)
- {
- e1 = (e->t1 != NULL) ? (e->t1->nextEdge(e)) : NULL;
- e2 = (e->t1 != NULL) ? (e->t1->prevEdge(e)) : NULL;
- e3 = (e->t2 != NULL) ? (e->t2->nextEdge(e)) : NULL;
- e4 = (e->t2 != NULL) ? (e->t2->prevEdge(e)) : NULL;
- splitEdge(e, splitvs[1]);
- if (nov > 1) splitEdge(e, splitvs[0]);
- e = e1; if (e != NULL && !IS_BIT(e, 5)) { edges.appendTail(e); MARK_BIT(e, 5); }
- e = e2; if (e != NULL && !IS_BIT(e, 5)) { edges.appendTail(e); MARK_BIT(e, 5); }
- e = e3; if (e != NULL && !IS_BIT(e, 5)) { edges.appendTail(e); MARK_BIT(e, 5); }
- e = e4; if (e != NULL && !IS_BIT(e, 5)) { edges.appendTail(e); MARK_BIT(e, 5); }
- }
- }
-
- int nc = 0; // Num of collapses to remove needles
-
- // Remove needles
- FOREACHEDGE(e, n) if (e->isLinked() && ((*e->v1) == (*e->v2))) if (e->collapse()) nc++;
- FOREACHEDGE(e, n) if (e->isLinked() && ((*e->v1) == (*e->v2)))
- {
- if (e->t1) unlinkTriangle(e->t1);
- if (e->t2) unlinkTriangle(e->t2);
- }
- removeUnlinkedElements();
-
- int degn = 0;
- FOREACHTRIANGLE(t, n) if (t->isExactlyDegenerate()) degn++;
- if (degn)
- {
- TMesh::warning("removeDegenerateTriangles() - This should not happen!\n");
- FOREACHTRIANGLE(t, n) if (t->isExactlyDegenerate()) MARK_VISIT(t); else UNMARK_VISIT(t);
- }
-
- return (nc)*((degn) ? (-1) : (1));
-}
-
-//int Basic_TMesh::removeDegenerateTriangles()
-//{
-// Node *n;
-// Triangle *t;
-// Edge *e;
-//
-// // Split caps
-// E.sort(&edgeCompare);
-// Vertex *ov1, *ov2;
-// int nov;
-// bool done;
-//
-// do
-// {
-// done = false;
-// FOREACHEDGE(e, n)
-// {
-// nov = 0;
-// if (e->t1 != NULL && Point::pointInInnerSegment((ov1 = e->t1->oppositeVertex(e)), e->v1, e->v2)) nov++;
-// if (e->t2 != NULL && Point::pointInInnerSegment((ov2 = e->t2->oppositeVertex(e)), e->v1, e->v2)) nov += 2;
-// if (nov == 3 && ov1->squaredDistance(e->v1) < ov2->squaredDistance(e->v1)) { splitEdge(e, ov2); splitEdge(e, ov1); }
-// else if (nov == 3 && ov2->squaredDistance(e->v1) < ov1->squaredDistance(e->v1)) { splitEdge(e, ov1); splitEdge(e, ov2); }
-// else if (nov >= 2) splitEdge(e, ov2);
-// else if (nov == 1) splitEdge(e, ov1);
-// if (nov) done = true;
-// }
-// } while (done);
-//
-// //FOREACHEDGE(e, n) multiSplitEdge(this, e);
-//
-// int nc = 0; // Num of collapses to remove needles
-//
-// // Remove needles
-// FOREACHEDGE(e, n) if (e->isLinked() && ((*e->v1) == (*e->v2))) if (e->collapse()) nc++;
-//
-// FOREACHEDGE(e, n) if (e->isLinked() && ((*e->v1) == (*e->v2)))
-// {
-// if (e->t1) unlinkTriangle(e->t1);
-// if (e->t2) unlinkTriangle(e->t2);
-// }
-// removeUnlinkedElements();
-//
-// int degn = 0;
-// FOREACHTRIANGLE(t, n) if (t->isExactlyDegenerate()) degn++;
-// if (degn)
-// {
-// FOREACHTRIANGLE(t, n) if (t->isExactlyDegenerate()) MARK_VISIT(t); else UNMARK_VISIT(t);
-// }
-//
-// return (nc)*((degn) ? (-1) : (1));
-//}
-
-//int Basic_TMesh::removeDegenerateTriangles()
-//{
-// Edge *e;
-// Node *n;
-// int nc = 0; // Num of collapses to remove needles
-// int ns = 0; // Num of swaps to remove internal caps
-// int nr = 0; // Num of removals to remove boundary caps
-//
-// // Remove needles
-// FOREACHEDGE(e, n) if (e->isLinked() && ((*e->v1) == (*e->v2))) if (e->collapse()) nc++;
-//
-// // Swap or remove caps
-// Point p, w1, w2;
-// FOREACHEDGE(e, n) if (e->isLinked() && ((*e->v1) != (*e->v2)))
-// {
-// if (e->t1 != NULL)
-// {
-// p.setValue(e->t1->oppositeVertex(e));
-// w1 = p - (*e->v1);
-// w2 = p - (*e->v2);
-// if (!w1.isNull() && !w2.isNull() && (w1*w2 < 0) && e->t1->isExactlyDegenerate())
-// {
-// if (e->t2 != NULL) { if (e->swap()) { ns++; continue; } }
-// else { unlinkTriangle(e->t1); nr++; continue; }
-// }
-// }
-// if (e->t2 != NULL)
-// {
-// p.setValue(e->t2->oppositeVertex(e));
-// w1 = p - (*e->v1);
-// w2 = p - (*e->v2);
-// if (!w1.isNull() && !w2.isNull() && (w1*w2 < 0) && e->t2->isExactlyDegenerate())
-// {
-// if (e->t1 != NULL) { if (e->swap()) { ns++; continue; } }
-// else { unlinkTriangle(e->t2); nr++; continue; }
-// }
-// }
-// }
-//
-// // Remove possible newly-introduced needles
-// FOREACHEDGE(e, n) if (e->isLinked() && ((*e->v1) == (*e->v2))) if (e->collapse()) nc++;
-//
-// removeUnlinkedElements();
-//
-// Triangle *t;
-// int degn = 0;
-// FOREACHTRIANGLE(t, n) if (t->isExactlyDegenerate()) degn++;
-// if (degn)
-// {
-// FOREACHTRIANGLE(t, n) if (t->isExactlyDegenerate()) MARK_VISIT(t); else UNMARK_VISIT(t);
-// }
-//
-// return (nc + ns + nr)*((degn) ? (-1) : (1));
-//}
-
-//int Basic_TMesh::removeDegenerateTriangles()
-//{
-// Triangle *t;
-// Node *n;
-// Edge *e;
-// int degn = 0, tcs = 0;
-//
-// if (TMesh::acos_tolerance > 0.0)
-// {
-// int collapses, swaps;
-// List todo, *vt;
-//
-// do
-// {
-// collapses = swaps = 0;
-//
-// FOREACHTRIANGLE(t, n) if (t->isDegenerate())
-// {MARK_BIT(t, 5); todo.appendHead(t);}
-// else UNMARK_BIT(t, 5);
-//
-// while (todo.numels())
-// {
-// t = (Triangle *)todo.popHead();
-// UNMARK_BIT(t, 5);
-// if (t->isLinked())
-// {
-// if ((e = t->isCap()) != NULL)
-// {
-// if (e->isOnBoundary()) {unlinkTriangle(t); collapses++;}
-// else if (e->swap())
-// {
-// if (e->t1->overlaps() || e->t2->overlaps() || e->t1->isCap() || e->t2->isCap()) e->swap(1);
-// else
-// {
-// swaps++;
-// if (!IS_BIT(e->t1, 5)) { MARK_BIT(e->t1, 5); todo.appendTail(e->t1); }
-// if (!IS_BIT(e->t2, 5)) { MARK_BIT(e->t2, 5); todo.appendTail(e->t2); }
-// }
-// }
-// }
-// else if ((e = t->isNeedle()) != NULL)
-// {
-// vt = e->v2->VT();
-// if (e->collapse())
-// {
-// collapses++;
-// FOREACHVTTRIANGLE(vt, t, n)
-// if (t->isLinked() && !IS_BIT(t, 5)) { MARK_BIT(t, 5); todo.appendTail(t); }
-// }
-// else if (!e->isOnBoundary() && e->oppositeTriangle(t)->oppositeVertex(e)->valence() == 3)
-// {
-// if (e->oppositeTriangle(t)->nextEdge(e)->collapse())
-// {
-// MARK_BIT(t, 5); todo.appendHead(t);
-// t = e->oppositeTriangle(t);
-// if (t && !IS_BIT(t, 5)) { MARK_BIT(t, 5); todo.appendTail(t); }
-// collapses++;
-// }
-// }
-// delete(vt);
-// }
-// }
-// }
-//
-// if (collapses) removeUnlinkedElements();
-// tcs += collapses; tcs += swaps;
-// } while (collapses+swaps);
-//
-// FOREACHTRIANGLE(t, n) if (t->isDegenerate()) degn++;
-//
-// if (degn)
-// {
-// FOREACHTRIANGLE(t, n) if (t->isDegenerate()) MARK_VISIT(t); else UNMARK_VISIT(t);
-// }
-// }
-// else /// This uses exact arithmetics to deduce that triangles are degenerate
-// {
-// List triangles;
-// const int MAX_ATTEMPTS = 10;
-//
-// FOREACHTRIANGLE(t, n) t->info=0;
-//
-// // BIT5 means that the triangle is in the list
-// FOREACHTRIANGLE(t, n)
-// {
-// if (t->isExactlyDegenerate()) {triangles.appendTail(t); MARK_BIT(t, 5);}
-// else UNMARK_BIT(t, 5);
-// }
-//
-// while ((t=(Triangle *)triangles.popHead())!=NULL)
-// {
-// UNMARK_BIT(t, 5);
-// if (t->isLinked())
-// {
-// if (t->e1->isDegenerate()) {t->e1->collapse(); tcs++;}
-// else if (t->e2->isDegenerate()) {t->e2->collapse(); tcs++;}
-// else if (t->e3->isDegenerate()) {t->e3->collapse(); tcs++;}
-// else if ((e=t->getLongestEdge())!=NULL)
-// {
-// if (e->swap())
-// {
-// tcs++;
-// t=e->t1;
-// if (t->isExactlyDegenerate() && !IS_BIT(t, 5) && ((int)t->info < MAX_ATTEMPTS))
-// {triangles.appendTail(t); MARK_BIT(t, 5); t->info = (void *)(((int)t->info)+1);}
-// t=e->t2;
-// if (t->isExactlyDegenerate() && !IS_BIT(t, 5) && ((int)t->info < MAX_ATTEMPTS))
-// {triangles.appendTail(t); MARK_BIT(t, 5); t->info = (void *)(((int)t->info)+1);}
-// }
-// }
-// }
-// }
-//
-// removeUnlinkedElements();
-//
-// FOREACHTRIANGLE(t, n) if (t->isExactlyDegenerate()) degn++;
-// if (degn)
-// {
-// FOREACHTRIANGLE(t, n) if (t->isExactlyDegenerate()) MARK_VISIT(t); else UNMARK_VISIT(t);
-// }
-// }
-//
-// if (degn) tcs=-tcs;
-// if (tcs<0) TMesh::info("removeDegenerateTriangles: %d degeneracies could not be removed and have been selected\n",degn);
-// return tcs;
-//}
-
-
-bool Basic_TMesh::strongDegeneracyRemoval(int max_iters)
-{
- int n, iter_count = 0;
- bool qstatus = TMesh::quiet;
-
- TMesh::info("Removing degeneracies...\n");
- while ((++iter_count) <= max_iters && removeDegenerateTriangles()<0)
- {
- for (n=1; n max_iters) return false;
- return true;
-}
-
-//// If the mesh is made of more than one connected component ////
-//// keep only the biggest one and remove all the others. ////
-
-int Basic_TMesh::removeSmallestComponents()
-{
- Node *n,*m;
- List todo;
- List components;
- List *component, *biggest = NULL;
- Triangle *t, *t1, *t2, *t3;
- int nt = 0, gnt = 0;
-
- if (T.numels() == 0) return 0;
-
- FOREACHTRIANGLE(t, n) UNMARK_BIT(t, 5);
-
- t = ((Triangle *)T.head()->data);
- n = T.head();
- do
- {
- component = new List;
- components.appendHead(component);
- todo.appendHead(t);
- while (todo.numels())
- {
- t = (Triangle *)todo.head()->data;
- todo.removeCell(todo.head());
- if (!IS_BIT(t, 5))
- {
- t1 = t->t1();
- t2 = t->t2();
- t3 = t->t3();
-
- if (t1 != NULL && !IS_BIT(t1, 5)) todo.appendHead(t1);
- if (t2 != NULL && !IS_BIT(t2, 5)) todo.appendHead(t2);
- if (t3 != NULL && !IS_BIT(t3, 5)) todo.appendHead(t3);
-
- MARK_BIT(t, 5);
- component->appendTail(t);
- }
- }
- todo.removeNodes();
- for (; n != NULL; n=n->next()) {t = ((Triangle *)n->data); if (!IS_BIT(t, 5)) break;}
- }
- while (n != NULL);
-
- int num_comps = components.numels();
-
- FOREACHNODE(components, n)
- if ((nt = ((List *)n->data)->numels()) > gnt) {gnt=nt; biggest = (List *)n->data;}
-
- FOREACHTRIANGLE(t, n) UNMARK_BIT(t, 5);
-
- nt = 0;
- FOREACHNODE(components, n)
- if (((List *)n->data) != biggest)
- FOREACHVTTRIANGLE(((List *)n->data), t, m)
- {
- if (t->e1->v1 != NULL) t->e1->v1->e0 = NULL;
- if (t->e1->v2 != NULL) t->e1->v2->e0 = NULL;
- if (t->e2->v1 != NULL) t->e2->v1->e0 = NULL;
- if (t->e2->v2 != NULL) t->e2->v2->e0 = NULL;
- if (t->e3->v1 != NULL) t->e3->v1->e0 = NULL;
- if (t->e3->v2 != NULL) t->e3->v2->e0 = NULL;
- t->e1->v1 = t->e1->v2 = t->e2->v1 = t->e2->v2 = t->e3->v1 = t->e3->v2 = NULL;
- t->e1 = t->e2 = t->e3 = NULL;
- nt++;
- }
-
- FOREACHNODE(components, n) delete((List *)n->data);
-
- if (nt)
- {
- d_boundaries = d_handles = d_shells = 1;
- removeUnlinkedElements();
- return num_comps-1;
- }
-
- return 0;
-}
-
-
-//// Remove components whose area is < eps_area
-
-int Basic_TMesh::removeSmallestComponents(double eps_area)
-{
- Node *n;
- List todo, component;
- Triangle *t, *s;
- int rem_comps=0;
- double pa;
-
- if (T.numels() == 0) return 0;
-
- FOREACHTRIANGLE(t, n) UNMARK_BIT(t, 5);
- t = ((Triangle *)T.head()->data);
- n = T.head();
- do
- {
- todo.appendTail(t); MARK_BIT(t, 5);
- pa = 0.0;
- while ((t=(Triangle *)todo.popHead())!=NULL)
- {
- s = t->t1(); if (s != NULL && !IS_BIT(s, 5)) { todo.appendTail(s); MARK_BIT(s, 5); }
- s = t->t2(); if (s != NULL && !IS_BIT(s, 5)) { todo.appendTail(s); MARK_BIT(s, 5); }
- s = t->t3(); if (s != NULL && !IS_BIT(s, 5)) { todo.appendTail(s); MARK_BIT(s, 5); }
- component.appendTail(t);
- pa += t->area();
- }
- if (pa < eps_area) { rem_comps++; while ((t = (Triangle *)component.popHead()) != NULL) unlinkTriangle(t); }
- else component.removeNodes();
-
- for (; n != NULL; n = n->next()) { t = ((Triangle *)n->data); if (!IS_BIT(t, 5)) break; }
- } while (n != NULL);
-
- FOREACHTRIANGLE(t, n) UNMARK_BIT(t, 5);
-
- if (rem_comps)
- {
- d_boundaries = d_handles = d_shells = 1;
- removeUnlinkedElements();
- }
-
- return rem_comps;
-}
-
-
-//// Traverses the triangulation and inverts normals in order ////
-//// to make the adjacences consistent. ////
-//// returns:
-//// 0 = mesh was oriented, nothing done
-//// 1 = some triangles were flipped to achieve orientation
-//// >1 = mesh was not orientable. Cuts were necessary
-
-int Basic_TMesh::forceNormalConsistence()
-{
- int ret = 0;
- Node *n;
- Triangle *t;
-
- FOREACHTRIANGLE(t, n) if (!IS_BIT(t, 5))
- ret |= forceNormalConsistence(t);
- FOREACHTRIANGLE(t, n) UNMARK_BIT(t, 5);
- return ret;
-}
-
-int Basic_TMesh::forceNormalConsistence(Triangle *t0)
-{
- Node *n;
- Edge *e;
- List todo, elist;
- Triangle *t, *t1, *t2, *t3;
- int tmp1, tmp2, r=0, wrn = 0, isclosed = 1;
-
- todo.appendHead(t0);
-
- while (todo.numels())
- {
- t = (Triangle *)todo.head()->data;
- todo.removeCell(todo.head());
- if (!IS_BIT(t, 5))
- {
- t1 = t->t1(); t2 = t->t2(); t3 = t->t3();
- if (!IS_BIT(t->e1, 5)) { MARK_BIT(t->e1, 5); elist.appendHead(t->e1); }
- if (!IS_BIT(t->e2, 5)) { MARK_BIT(t->e2, 5); elist.appendHead(t->e2); }
- if (!IS_BIT(t->e3, 5)) { MARK_BIT(t->e3, 5); elist.appendHead(t->e3); }
-
- if (t1 != NULL && !IS_BIT(t1, 5)) { todo.appendHead(t1); if (!t->checkAdjNor(t1)) { t1->invert(); r = 1; } }
- if (t2 != NULL && !IS_BIT(t2, 5)) { todo.appendHead(t2); if (!t->checkAdjNor(t2)) { t2->invert(); r = 1; } }
- if (t3 != NULL && !IS_BIT(t3, 5)) { todo.appendHead(t3); if (!t->checkAdjNor(t3)) { t3->invert(); r = 1; } }
-
- MARK_BIT(t, 5);
- }
- }
-
- FOREACHVEEDGE((&(elist)), e, n)
- {
- UNMARK_BIT(e, 5);
- if (isclosed && e->isOnBoundary()) isclosed = 0;
- tmp1 = (e->t1 != NULL)?((e->commonVertex(e->t1->nextEdge(e)) == e->v1)?(-1):(1)):(0);
- tmp2 = (e->t2 != NULL)?((e->commonVertex(e->t2->nextEdge(e)) == e->v2)?(-1):(1)):(0);
-
- if (tmp1*tmp2 < 0)
- {
- wrn++;
- if (tmp1 == -1) p_swap((void **)(&(e->v1)), (void **)(&(e->v2)));
- Edge *ne = newEdge(e->v2, e->v1);
- E.appendHead(ne);
- e->t2->replaceEdge(e, ne);
- ne->t2 = e->t2; e->t2 = NULL;
- } else if (tmp1 == -1 || tmp2 == -1) p_swap((void **)(&(e->v1)), (void **)(&(e->v2)));
- }
-
- if (wrn)
- {
- d_boundaries = d_handles = d_shells = 1;
- TMesh::warning("forceNormalConsistence: Basic_TMesh was not orientable. Cut performed.\n");
- }
-
- // Though useful in some easy cases, the flip below destroys the orientation
- // when it is set on purpose (e.g. for internal cavities)
-
- //if (isclosed)
- //{
- // t = topTriangle(t0);
- // if (t->getNormal().z < 0) {flipNormals(t0); r=1;}
- //}
-
- if (wrn) r |= 2;
-
- return r;
-}
-
-
-// If possible, swap edges to remove overlaps. When it is not
-// enough, remove the overlapping triangles from the mesh.
-// return the number of triangles that was necessary to remove.
-
-int Basic_TMesh::removeOverlappingTriangles()
-{
- Node *n;
- Edge *e;
- List oved;
-
- FOREACHEDGE(e, n) if (e->overlaps()) oved.appendHead(e);
- oved.sort(edgeCompare);
-
- for (n=oved.tail(); n!=NULL; n=n->prev())
- {
- e = (Edge *)n->data;
- if (e->overlaps() && e->swap())
- {
- if (e->t1->isExactlyDegenerate() || e->t2->isExactlyDegenerate()) {e->swap(1); continue;}
- if (e->t1->nextEdge(e)->overlaps()) { e->swap(1); continue; }
- if (e->t1->prevEdge(e)->overlaps()) { e->swap(1); continue; }
- if (e->t2->nextEdge(e)->overlaps()) { e->swap(1); continue; }
- if (e->t2->prevEdge(e)->overlaps()) { e->swap(1); continue; }
- }
- }
-
- int nr = 0;
- for (n=oved.tail(); n!=NULL; n=n->prev())
- {
- e = (Edge *)n->data;
- if (e->overlaps()) { unlinkTriangle(e->t1); unlinkTriangle(e->t2); nr++; }
- }
- if (nr)
- {
- removeUnlinkedElements();
- d_boundaries = d_handles = d_shells = 1;
- }
-
- return nr*2;
-}
-
-
-bool Basic_TMesh::meshclean(int max_iters, int inner_loops)
-{
- bool ni, nd;
- Triangle *t;
- Node *m;
-
- deselectTriangles();
- invertSelection();
-
- for (int n=0; nisExactlyDegenerate()) ni=false;
- if (ni) return true;
- }
- }
-
- return false;
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/Algorithms/detectIntersections.cpp b/src/mesh_fix/src/Algorithms/detectIntersections.cpp
deleted file mode 100644
index 24444997f..000000000
--- a/src/mesh_fix/src/Algorithms/detectIntersections.cpp
+++ /dev/null
@@ -1,395 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "detectIntersections.h"
-#include
-#include
-#include "jqsort.h"
-
-namespace T_MESH
-{
- di_cell::di_cell(Basic_TMesh *tin, bool useAll)
- {
- Node *n;
- Vertex *v;
- Triangle *t;
- Mp.x = -DBL_MAX, mp.x = DBL_MAX;
- Mp.y = -DBL_MAX, mp.y = DBL_MAX;
- Mp.z = -DBL_MAX, mp.z = DBL_MAX;
- FOREACHVVVERTEX((&(tin->V)), v, n) if (useAll || IS_BIT(v,5))
- {
- if (v->x < mp.x) mp.x = v->x;
- if (v->x > Mp.x) Mp.x = v->x;
- if (v->y < mp.y) mp.y = v->y;
- if (v->y > Mp.y) Mp.y = v->y;
- if (v->z < mp.z) mp.z = v->z;
- if (v->z > Mp.z) Mp.z = v->z;
- }
-
- mp -= DI_EPSILON_POINT;
- Mp += DI_EPSILON_POINT;
-
- FOREACHVTTRIANGLE((&(tin->T)), t, n) if (useAll || IS_VISITED(t)) triangles.appendTail(t);
- }
-
- bool di_cell::is_triangleBB_in_cell(Triangle *t) const
- {
- Vertex *v1 = t->v1(), *v2 = t->v2(), *v3 = t->v3();
- coord mx = MIN(v1->x, MIN(v2->x, v3->x));
- coord Mx = MAX(v1->x, MAX(v2->x, v3->x));
- coord my = MIN(v1->y, MIN(v2->y, v3->y));
- coord My = MAX(v1->y, MAX(v2->y, v3->y));
- coord mz = MIN(v1->z, MIN(v2->z, v3->z));
- coord Mz = MAX(v1->z, MAX(v2->z, v3->z));
-
- // Triangle BB is not entirely out of cell
- if (!(MxMp.x || MyMp.y || MzMp.z)) return true;
- else return false;
- }
-
- di_cell *di_cell::fork()
- {
- Node *n;
- Triangle *t;
- Point e = Mp - mp;
- di_cell *nc = new di_cell;
- char which_coord = 2;
-
- if (e.x >= e.y && e.x >= e.z) which_coord = 0;
- else if (e.y >= e.x && e.y >= e.z) which_coord = 1;
- nc->mp = mp; nc->Mp = Mp;
- nc->Mp[which_coord] -= (e[which_coord] / 2); mp[which_coord] = nc->Mp[which_coord];
-
- n = triangles.head();
- while (n != NULL)
- {
- t = (Triangle *)n->data;
- n = n->next();
- if (!is_triangleBB_in_cell(t))
- {
- triangles.moveNodeTo((n != NULL) ? (n->prev()) : triangles.tail(), &(nc->triangles));
- }
- else if (nc->is_triangleBB_in_cell(t)) nc->triangles.appendHead(t);
- }
-
- return nc;
- }
-
-
- // Brute force all-with-all intersection test of the triangles in 'triangles'.
- void di_cell::selectIntersections(bool justproper)
- {
- Triangle *t, *y;
- Node *n, *m;
- List *ts;
-
- for (n = triangles.head(); n != NULL; n = n->next())
- for (m = n->next(); m != NULL; m = m->next())
- {
- t = (Triangle *)n->data;
- y = (Triangle *)m->data; // For any pair (t,y) of triangles in the cell
- // The same triangle pair can be in different cells. The following avoids redoing the check.
- if (t->info == NULL || y->info == NULL || (((List *)t->info)->containsNode(y) == NULL))
- {
- if (t->intersects(y, justproper))
- {
- MARK_VISIT(t); MARK_VISIT(y);
- ts = ((t->info != NULL) ? ((List *)t->info) : (new List)); ts->appendTail(y); t->info = ts;
- ts = ((y->info != NULL) ? ((List *)y->info) : (new List)); ts->appendTail(t); y->info = ts;
- }
- }
- }
- }
-
-
-/////////////////////////////////////////////////////////////////////////
-// ||
-////////////////////// Select Intersections ///////////////////////////
-// ||
-/////////////////////////////////////////////////////////////////////////
-
-int Basic_TMesh::selectIntersectingTriangles(UINT16 tris_per_cell, bool justproper)
-{
- Triangle *t;
- Vertex *v;
- Node *n;
- bool isSelection=0;
- List *selT = new List, *selV = new List;
-
- TMesh::begin_progress();
- TMesh::report_progress(NULL);
-
- FOREACHTRIANGLE(t, n) if (IS_VISITED(t))
- {
- isSelection=1;
- selT->appendTail(t);
- v=t->v1(); if (!IS_BIT(v,5)) {MARK_BIT(v,5); selV->appendTail(v);}
- v=t->v2(); if (!IS_BIT(v,5)) {MARK_BIT(v,5); selV->appendTail(v);}
- v=t->v3(); if (!IS_BIT(v,5)) {MARK_BIT(v,5); selV->appendTail(v);}
- }
- TMesh::report_progress(NULL);
-
- if (!isSelection) {delete(selT); delete(selV); selT=&T; selV=&V;}
-
- di_cell *c2, *c = new di_cell(this, !isSelection);
- List cells, todo(c);
- int i=0;
-
- while ((c = (di_cell *)todo.popHead()) != NULL)
- {
- if (i>DI_MAX_NUMBER_OF_CELLS || c->triangles.numels() <= tris_per_cell) cells.appendHead(c);
- else
- {
- if (!(i % 1000)) TMesh::report_progress(NULL);
- i++;
- c2 = c->fork();
- todo.appendTail(c);
- todo.appendTail(c2);
- }
- }
-
- // Deselect everything and select only intersecting triangles
- deselectTriangles();
- FOREACHTRIANGLE(t, n) t->info = NULL;
- i=0; FOREACHNODE(cells, n)
- {
- (((di_cell *)n->data)->selectIntersections(justproper));
- if (!(i % 100)) TMesh::report_progress("%d %% done ", ((i)* 100) / cells.numels());
- i++;
- }
- TMesh::end_progress();
-
- // Dispose memory allocated for cells
- FOREACHVTTRIANGLE(selT, t, n) { if (t->info!=NULL) delete((List *)t->info); t->info = NULL; }
- while (cells.numels()) delete((di_cell *)cells.popHead());
-
- // Count selected triangles for final report and delete stored normals
- int its=0;
- FOREACHVTTRIANGLE(selT, t, n) { if (IS_VISITED(t)) its++;}
-
- if (its) TMesh::info("%d intersecting triangles have been selected.\n",its);
- else TMesh::info("No intersections detected.\n");
-
- FOREACHVVVERTEX(selV, v, n) UNMARK_BIT(v,5);
- if (isSelection) {delete(selT); delete(selV);}
-
- return its;
-}
-
-void jitterIncrease(char *f)
-{
- bool isnegative = (f[0] == '-');
- int l = strlen(f);
-
- if (isnegative)
- {
- for (int i = l - 1; i >= 1; i--)
- if (f[i] == '0') f[i] = '9';
- else if (f[i] == '.') continue;
- else { f[i]--; break; }
- } else
- {
- for (int i = l - 1; i >= 0; i--)
- if (f[i] == '9') f[i] = '0';
- else if (f[i] == '.') continue;
- else { f[i]++; break; }
- }
-}
-
-void jitterDecrease(char *f)
-{
- bool isnegative = (f[0] == '-');
- int l = strlen(f);
-
- if (isnegative)
- {
- for (int i = l - 1; i >= 1; i--)
- if (f[i] == '9') f[i] = '0';
- else if (f[i] == '.') continue;
- else { f[i]++; break; }
- } else
- {
- for (int i = l - 1; i >= 0; i--)
- if (f[i] == '0') f[i] = '9';
- else if (f[i] == '.') continue;
- else { f[i]--; break; }
- }
-}
-
-void jitterCoordinate(coord& c, int j)
-{
- char floatver[32];
- float x;
-
- sprintf(floatver, "%f", TMESH_TO_FLOAT(c));
- if (j > 0) jitterIncrease(floatver);
- else if (j<0) jitterDecrease(floatver);
- sscanf(floatver, "%f", &x); c = x;
-}
-
-bool Basic_TMesh::safeCoordBackApproximation()
-{
- Node *n;
- Vertex *v;
-
- deselectTriangles();
-
- FOREACHVERTEX(v, n)
- {
- jitterCoordinate(v->x, 0);
- jitterCoordinate(v->y, 0);
- jitterCoordinate(v->z, 0);
- }
-
- Edge *e;
- Vertex *ov1, *ov2;
-
- int pnos = 0, nos;
- nos = 0; FOREACHEDGE(e, n) if (e->overlaps()) nos++;
-
- do
- {
- pnos = nos;
- FOREACHEDGE(e, n) if (e->overlaps())
- {
- ov1 = e->t1->oppositeVertex(e);
- ov2 = e->t2->oppositeVertex(e);
- v = (Point::squaredTriangleArea3D(e->v1, e->v2, ov1) < Point::squaredTriangleArea3D(e->v1, e->v2, ov2)) ? (ov1) : (ov2);
- for (int a = -1; a <= 1; a++) for (int b = -1; b <= 1; b++) for (int c = -1; c <= 1; c++)
- {
- jitterCoordinate(v->x, a); jitterCoordinate(v->y, b); jitterCoordinate(v->z, c);
- if (e->overlaps())
- {
- jitterCoordinate(v->x, -a); jitterCoordinate(v->y, -b); jitterCoordinate(v->z, -c);
- } else a = b = c = 2;
- }
- }
- nos = 0; FOREACHEDGE(e, n) if (e->overlaps()) nos++;
- } while (nos < pnos);
-
-// if (nos) TMesh::warning("%d overlaps could not be removed.\n", nos);
- return (nos == 0);
-}
-
-
-
-
-
-
-
-
-bool remints_appendCubeToList(Triangle *t0, List& l)
-{
- if (!IS_VISITED(t0) || IS_BIT(t0, 6)) return false;
-
- Triangle *t, *s;
- Vertex *v;
- List triList(t0);
- MARK_BIT(t0,6);
- coord minx = DBL_MAX, maxx = -DBL_MAX, miny = DBL_MAX, maxy = -DBL_MAX, minz = DBL_MAX, maxz = -DBL_MAX;
-
- while(triList.numels())
- {
- t = (Triangle *)triList.popHead();
- v = t->v1();
- minx=MIN(minx,v->x); miny=MIN(miny,v->y); minz=MIN(minz,v->z);
- maxx=MAX(maxx,v->x); maxy=MAX(maxy,v->y); maxz=MAX(maxz,v->z);
- v = t->v2();
- minx=MIN(minx,v->x); miny=MIN(miny,v->y); minz=MIN(minz,v->z);
- maxx=MAX(maxx,v->x); maxy=MAX(maxy,v->y); maxz=MAX(maxz,v->z);
- v = t->v3();
- minx=MIN(minx,v->x); miny=MIN(miny,v->y); minz=MIN(minz,v->z);
- maxx=MAX(maxx,v->x); maxy=MAX(maxy,v->y); maxz=MAX(maxz,v->z);
- if ((s = t->t1()) != NULL && !IS_BIT(s, 6) && IS_VISITED(s)) {triList.appendHead(s); MARK_BIT(s,6);}
- if ((s = t->t2()) != NULL && !IS_BIT(s, 6) && IS_VISITED(s)) {triList.appendHead(s); MARK_BIT(s,6);}
- if ((s = t->t3()) != NULL && !IS_BIT(s, 6) && IS_VISITED(s)) {triList.appendHead(s); MARK_BIT(s,6);}
- }
-
- l.appendTail(new Point(minx, miny, minz));
- l.appendTail(new Point(maxx, maxy, maxz));
- return true;
-}
-
-bool remints_isVertexInCube(Vertex *v, List& loc)
-{
- Node *n;
- Point *p1, *p2;
- FOREACHNODE(loc, n)
- {
- p1 = (Point *)n->data; n=n->next(); p2 = (Point *)n->data;
- if (!(v->x < p1->x || v->y < p1->y || v->z < p1->z ||
- v->x > p2->x || v->y > p2->y || v->z > p2->z)) return true;
- }
-
- return false;
-}
-
-void remints_selectTrianglesInCubes(Basic_TMesh *tin)
-{
- Triangle *t;
- Vertex *v;
- Node *n;
- List loc;
- FOREACHVTTRIANGLE((&(tin->T)), t, n) remints_appendCubeToList(t, loc);
- FOREACHVVVERTEX((&(tin->V)), v, n) if (remints_isVertexInCube(v, loc)) MARK_BIT(v, 5);
- FOREACHVTTRIANGLE((&(tin->T)), t, n)
- {
- UNMARK_BIT(t, 6);
- if (IS_BIT(t->v1(), 5) || IS_BIT(t->v2(), 5) || IS_BIT(t->v3(), 5)) MARK_VISIT(t);
- }
- FOREACHVVVERTEX((&(tin->V)), v, n) UNMARK_BIT(v, 5);
- loc.freeNodes();
-}
-
-
-// returns true on success
-
-bool Basic_TMesh::strongIntersectionRemoval(int max_iters)
-{
- int n, iter_count = 0;
- bool qstatus = TMesh::quiet;
-
- TMesh::info("Removing self-intersections...\n");
-
- while ((++iter_count) <= max_iters && selectIntersectingTriangles())
- {
- for (n=1; n max_iters) return false;
- return true;
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/Algorithms/holeFilling.cpp b/src/mesh_fix/src/Algorithms/holeFilling.cpp
deleted file mode 100644
index c19557ec6..000000000
--- a/src/mesh_fix/src/Algorithms/holeFilling.cpp
+++ /dev/null
@@ -1,797 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "tin.h"
-#include
-
-namespace T_MESH
-{
-
-//////////////////////////////////////////////////////////////////
-// //
-// T R I A N G U L A T I O N M E T H O D S //
-// //
-//////////////////////////////////////////////////////////////////
-
-
-/////// Computes the center of mass of the hole and star-patches ////////
-
-int Basic_TMesh::StarTriangulateHole(Edge *e)
-{
- if (!e->isOnBoundary()) return 0;
-
- List bvs;
- Node *n;
- Edge *e1, *e2, *e3;
- Point np;
- Vertex *v, *nv, *v1, *v2;
- int nt=0;
-
- v = e->v1;
-
- do
- {
- bvs.appendHead(v);
- v = v->nextOnBoundary();
- //MARK_BIT(v,5); // < AMF_ADD - since IMAT-STL 2.4-1 >
- } while (v != e->v1);
-
- FOREACHVVVERTEX((&(bvs)), v, n) np = np+(*v);
-
- np = np/bvs.numels();
- nv = newVertex(&np);
- V.appendHead(nv);
-
- v1 = ((Vertex *)bvs.head()->data);
- Edge *ep = v1->e0; // AMF_ADD - since IMAT-STL 2.4-2
- e1 = CreateEdge(nv, v1);
- v1->e0 = ep; // AMF_ADD - since IMAT-STL 2.4-2
- for (n=bvs.head()->next(); n!=NULL; n=n->next())
- {
- v2 = ((Vertex *)n->data);
- e2 = CreateEdge(nv, v2);
- e3 = v1->getEdge(v2);
- CreateTriangle(e1, e2, e3);
- nt++;
- v1 = v2;
- e1 = e2;
- }
- v2 = ((Vertex *)bvs.head()->data);
- e2 = nv->getEdge(v2);
- e3 = v1->getEdge(v2);
- CreateTriangle(e1, e2, e3);
- nt++;
-
- return nt;
-}
-
-
-///// Patch holes using 2D Delaunay triangulation on the plane 'nor' /////
-
-int Basic_TMesh::TriangulateHole(Edge *e, Point *nor)
-{
- if (!e->isOnBoundary()) return 0;
-
- List bvs;
- Node *n, *gn = NULL;
- Edge *e1, *e2;
- Vertex *v, *v1, *v2;
- double ang, gang;
- int nt = 0;
-
- v = e->v1;
- do
- {
- bvs.appendHead(v);
- v = v->nextOnBoundary();
- } while (v != e->v1);
-
- while (bvs.numels() > 2)
- {
- gang = DBL_MAX;
- FOREACHVVVERTEX((&(bvs)), v, n)
- if (!IS_BIT(v, 5) && v->e0 && (ang = v->getAngleOnAveragePlane(nor)) < gang)
- {gang = ang; gn = n;}
- if (gang == DBL_MAX)
- {
- TMesh::warning("TriangulateHole: Can't complete the triangulation.\n");
- FOREACHVVVERTEX((&(bvs)), v, n) UNMARK_BIT(v, 5);
- return 0;
- }
- v = ((Vertex *)gn->data);
- v1 = (Vertex *)((gn->next() != NULL)?(gn->next()):(bvs.head()))->data;
- v2 = (Vertex *)((gn->prev() != NULL)?(gn->prev()):(bvs.tail()))->data;
- e1 = v->getEdge(v1);
- e2 = v->getEdge(v2);
- if (!EulerEdgeTriangle(e1, e2)) MARK_BIT(v, 5);
- else { bvs.removeCell(gn); UNMARK_BIT(v1, 5); UNMARK_BIT(v2, 5); nt++; }
- }
-
- int i, skips;
- do
- {
- skips = 0;
- for (n=E.head(), i=2*nt*nt; inext(), i--)
- {
- e = ((Edge *)n->data);
- ang = e->delaunayMinAngle();
- if (e->swap())
- {if (e->delaunayMinAngle() <= ang) e->swap(1); else skips++;}
- }
- if (i < 0) {TMesh::warning("Optimization is taking too long. I give up.\n"); break;}
- } while (skips);
-
- return nt;
-}
-
-
-///// Triangulates a hole using the additional vertices in 'vl' /////
-
-int Basic_TMesh::TriangulateHole(Edge *e, List *vl)
-{
- if (!e->isOnBoundary()) return 0;
-
- List bvs, ovbs, nedg;
- Node *n, *gn = NULL;
- Edge *e1, *e2;
- Vertex *v, *v1, *v2;
- double ang, gang;
- int nt = 0, neb;
-
- v = e->v1;
-
- do
- {
- bvs.appendHead(v);
- v = v->nextOnBoundary();
- } while (v != e->v1);
- ovbs.appendList(&bvs);
-
- while (bvs.numels() > 2) // While there are more than two boundary vertices
- {
- gang = DBL_MAX;
- FOREACHVVVERTEX((&(bvs)), v, n)
- if (!IS_BIT(v, 5) && v->e0 && (ang = v->getAngleForTriangulation()) < gang)
- {gang = ang; gn = n;}
- if (gang == DBL_MAX)
- {
- TMesh::warning("TriangulateHole: Can't complete the triangulation.\n");
- FOREACHVVVERTEX((&(bvs)), v, n) UNMARK_BIT(v, 5);
- return 0;
- }
- v = ((Vertex *)gn->data);
- v1 = (Vertex *)((gn->next() != NULL)?(gn->next()):(bvs.head()))->data;
- v2 = (Vertex *)((gn->prev() != NULL)?(gn->prev()):(bvs.tail()))->data;
- e1 = v->getEdge(v1);
- e2 = v->getEdge(v2);
- neb = E.numels();
- if (!EulerEdgeTriangle(e1, e2)) MARK_BIT(v, 5);
- else
- {
- bvs.removeCell(gn);
- UNMARK_BIT(v1, 5);
- UNMARK_BIT(v2, 5);
- nt++;
- if (E.numels() > neb) nedg.appendHead(E.head()->data);
- }
- }
-
-// if (nt < 2) return nt;
-
- // Calcolo una normale per il buco come media dei nuovi triangoli
- int i;
- Point nor;
-
- for (i=0, n=T.head(); inext()) nor = nor+((Triangle *)n->data)->getNormal();
- if (nor.isNull())
- {
- TMesh::warning("TriangulateHole: Unable to compute an average normal. Can't optimize.\n");
- return nt;
- }
- nor.normalize();
-
- // Memorizzo da qualche parte la posizione originale dei vertici
- // e Proietto il boundary sul piano con normale quella appena calcolata
- //coord *ovps = (coord *)malloc((ovbs.numels())*3*sizeof(coord)); // AMF_CHANGE - since IMAT-STL 2.4-2
- coord *ovps = new coord[3*(ovbs.numels())]; // AMF_CHANGE - since IMAT-STL 2.4-2
- int j = 0;
- FOREACHVVVERTEX((&(ovbs)), v, n)
- {
- ovps[j++] = v->x;
- ovps[j++] = v->y;
- ovps[j++] = v->z;
- v->project(&nor);
- }
-
- // Proietto i punti interni sul piano d'appoggio
- Point *p;
- //coord *ovpsi = (coord *)malloc((vl->numels())*3*sizeof(coord)); // AMF_CHANGE - since IMAT-STL 2.4-2
- coord *ovpsi = new coord[3*(vl->numels())]; // AMF_CHANGE - since IMAT-STL 2.4-2
- j = 0;
- FOREACHNODE((*vl), n)
- {
- p = ((Point *)n->data);
- ovpsi[j++] = p->x; ovpsi[j++] = p->y; ovpsi[j++] = p->z;
- }
- FOREACHNODE((*vl), n)
- {
- p = ((Point *)n->data);
- p->project(&nor);
- }
-
- // Ottimizzo secondo Delaunay vincolato al boundary la nuova regione
-
- int sw;
- do
- {
- sw = 0;
- FOREACHVEEDGE((&(nedg)), e1, n)
- {
- ang = e1->delaunayMinAngle();
- if (e1->swap())
- {if (e1->delaunayMinAngle() <= ang) e1->swap(1); else sw++;}
- }
- } while (sw);
-
- // Inserisco i punti interni
- int ntt = T.numels()-nt;
- List ivs;
-
- FOREACHNODE((*vl), n)
- {
- p = ((Point *)n->data);
- ivs.appendTail(watsonInsert(p, &T, T.numels()-ntt));
- }
- nt = (T.numels() - ntt);
-
- // Riporto i vertici interni al loro posto
- j=0; FOREACHVVVERTEX((&(ivs)), v, n)
- {
- if (v != NULL)
- {
- v->x = ovpsi[j++]; v->y = ovpsi[j++]; v->z = ovpsi[j++];
- } else j+=3;
- }
- delete [] ovpsi; //free(ovpsi); // AMF_CHANGE - since IMAT-STL 2.4-2
-
- // Riporto i vertici del boundary al loro posto
- j=0; FOREACHVVVERTEX((&(ovbs)), v, n)
- {
- v->x = ovps[j++]; v->y = ovps[j++]; v->z = ovps[j++];
- }
- delete [] ovps; //free(ovps); // AMF_CHANGE - since IMAT-STL 2.4-2
-
- return nt;
-}
-
-
-////// Inserts the point 'p' in the Delaunay triangulation 'tR' with 'nt' triangles ////
-
-Vertex *Basic_TMesh::watsonInsert(Point *p, List *tR, int nt)
-{
- Node *n, *m;
- Edge *e;
- Triangle *t;
- List bdr, bdrs, todo, *ve;
- Vertex *v1, *v2, *v3;
- int i;
-
- for (i=0, n = T.head(); inext(), i++)
- {
- t = ((Triangle *)n->data);
- if (t->e1 != NULL && t->inSphere(p))
- {
- v1 = t->v1(); v2 = t->v2(); v3 = t->v3();
- if (!IS_BIT(v1, 5)) bdr.appendHead(v1);
- if (!IS_BIT(v2, 5)) bdr.appendHead(v2);
- if (!IS_BIT(v3, 5)) bdr.appendHead(v3);
- MARK_BIT(v1, 5); MARK_BIT(v2, 5); MARK_BIT(v3, 5);
- MARK_BIT(t, 6);
- todo.appendHead(t);
- }
- }
- if (bdr.numels() == 0) return NULL;
-
- FOREACHVVVERTEX((&(bdr)), v1, n)
- {
- ve = v1->VE();
- FOREACHVEEDGE(ve, e, m) if (!IS_BIT(e->t1, 6) || !IS_BIT(e->t2, 6)) v1->e0 = e;
- delete(ve);
- }
-
- while (todo.numels())
- {
- t = ((Triangle *)todo.head()->data);
- todo.removeCell(todo.head());
- unlinkTriangleNoManifold(t);
- }
-
- Node *tmp;
- for (i=0, n = T.head(); idata);
- if (t->e1 == NULL) {tmp = n; n=n->next(); T.freeCell(tmp);}
- else n=n->next();
- }
-
- for (n = bdr.head(); n!=NULL;)
- {
- v1 = ((Vertex *)n->data);
- if (v1->e0 == NULL) {tmp = n; n=n->next(); bdr.removeCell(tmp);}
- else n=n->next();
- }
-
- v1 = v2 = ((Vertex *)bdr.head()->data);
- do
- {
- bdrs.appendHead(v1);
- v1 = v1->nextOnBoundary();
- } while (v1 != v2);
-
- Vertex *v = newVertex(p->x, p->y, p->z);
- V.appendHead(v);
-
- v1 = ((Vertex *)bdrs.head()->data);
- v->e0 = e = newEdge(v, v1);
- UNMARK_BIT(v1, 5);
- E.appendHead(e);
-
- for (n = bdrs.head()->next(); n!=NULL; n=n->next())
- {
- v1 = ((Vertex *)n->data);
- UNMARK_BIT(v1, 5);
- v2 = ((Vertex *)n->prev()->data);
- e = newEdge(v, v1);
- CreateTriangle(e, v1->getEdge(v2), (Edge *)E.head()->data);
- E.appendHead(e);
- }
- EulerEdgeTriangle(v->e0, (Edge *)E.head()->data);
-
- return v;
-}
-
-
-//// Removes a vertex and retriangulates its VT ////
-
-int Basic_TMesh::retriangulateVT(Vertex *v)
-{
- Point nor;
- Edge *e, *e0 = v->e0->t1->oppositeEdge(v);
- List *vt = v->VT();
- List oe;
- Triangle *t;
- Node *m, *n;
- int i, nt;
-
- FOREACHVTTRIANGLE(vt, t, m)
- {
- e = t->oppositeEdge(v);
- oe.appendTail(t->prevEdge(e));
- oe.appendTail(e);
- oe.appendTail(t->nextEdge(e));
- nor = nor+t->getNormal();
- unlinkTriangle(t);
- }
- removeUnlinkedElements(); // AMF_CHANGE - since IMAT-STL 2.4-2
- nor.normalize();
- nt = TriangulateHole(e0, &nor);
-
- for (m=T.head(), i=0; inext())
- {
- t = ((Triangle *)m->data);
- if (t->overlaps() || t->isExactlyDegenerate()) break;
- }
- if (inext())
- unlinkTriangle(((Triangle *)m->data));
- n = oe.head();
- FOREACHVTTRIANGLE(vt, t, m)
- {
- t->e1 = ((Edge *)n->data); n=n->next();
- t->e2 = ((Edge *)n->data); n=n->next();
- t->e3 = ((Edge *)n->data); n=n->next();
- t->e1->v1 = v; t->e1->v2 = (t->e2->t1 == NULL)?(t->e2->v1):(t->e2->v2);
- t->e3->v1 = v; t->e3->v2 = (t->e2->t1 == NULL)?(t->e2->v2):(t->e2->v1);
- ((t->e2->t1 == NULL)?(t->e2->t1):(t->e2->t2)) = t;
- t->e1->t1 = t;
- t->e3->t2 = t;
- }
- v->e0 = ((Triangle *)vt->head()->data)->e1;
- }
- delete(vt);
-
- return 1;
-}
-
-
-////////// Generic method for patching holes. Heuristic. /////////////
-////////// Small angles are patched first, if possible. /////////////
-
-int Basic_TMesh::TriangulateHole(Edge *e)
-{
- if (!e->isOnBoundary()) return 0;
-
- List bvs;
- Node *n, *gn = NULL;
- Edge *e1, *e2;
- Vertex *v, *v1, *v2;
- double ang, gang;
- int nt = 0;
- Triangle *t;
- v = e->v1;
-
- t = (e->t1!=NULL)?(e->t1):(e->t2);
- if (t->nextEdge(e)->isOnBoundary() && t->prevEdge(e)->isOnBoundary()) return 0;
-
- do
- {
- bvs.appendHead(v);
- v = v->nextOnBoundary();
- } while (v != e->v1);
-
- while (bvs.numels() > 2)
- {
- gang = DBL_MAX;
- FOREACHVVVERTEX((&bvs), v, n)
- if (!IS_BIT(v, 5) && v->e0 && (ang = v->getAngleForTriangulation()) < gang)
- {gang = ang; gn = n;}
- if (gang == DBL_MAX)
- {
- TMesh::warning("TriangulateHole: Can't complete the triangulation.\n");
- FOREACHVVVERTEX((&bvs), v, n) UNMARK_BIT(v, 5);
- int i=0; FOREACHTRIANGLE(t, n) if (i++==nt) break; else unlinkTriangle(t);
- removeUnlinkedElements();
- return 0;
- }
- v = ((Vertex *)gn->data);
- v1 = (Vertex *)((gn->next() != NULL)?(gn->next()):(bvs.head()))->data;
- v2 = (Vertex *)((gn->prev() != NULL)?(gn->prev()):(bvs.tail()))->data;
- e1 = v->getEdge(v1);
- e2 = v->getEdge(v2);
- if ((t=EulerEdgeTriangle(e1,e2))==NULL) MARK_BIT(v, 5);
- else { bvs.removeCell(gn); UNMARK_BIT(v1, 5); UNMARK_BIT(v2, 5); MARK_VISIT(t); nt++; }
- }
-
- return nt;
-}
-
-
-// Fills the hole identified by 'e' and leaves the new triangle selected.
-// 'refine' is for internal vertex insertion.
-
-void Basic_TMesh::FillHole(Edge *e, bool refine)
-{
- int i, nt;
- Node *n;
- Triangle *t;
- Vertex *v;
-
- deselectTriangles();
- FOREACHVERTEX(v, n) UNMARK_BIT(v, 5);
- nt = TriangulateHole(e);
- if (!nt) return;
-
- i=0; FOREACHTRIANGLE(t, n) if (i++==nt) break; else MARK_VISIT(t);
-
- if (refine)
- refineSelectedHolePatches((Triangle *)T.head()->data);
-}
-
-//// Triangulate Small Boundaries (with less than 'nbe' edges) /////
-
-int Basic_TMesh::fillSmallBoundaries(int nbe, bool refine_patches)
-{
- if (nbe == 0) nbe = E.numels();
- Vertex *v,*w;
- Triangle *t;
- Node *n;
- int grd, is_selection=0, tbds = 0, pct = 100;
- List bdrs;
-
- TMesh::begin_progress();
- TMesh::report_progress("0%% done ");
-
- FOREACHTRIANGLE(t, n) if (IS_VISITED(t)) {is_selection=1; break;}
-
- if (is_selection) {
- FOREACHTRIANGLE(t, n) if (!IS_VISITED(t))
- {
- MARK_BIT(t->v1(), 6); MARK_BIT(t->v2(), 6); MARK_BIT(t->v3(), 6);
- }
- }
- else FOREACHVERTEX(v, n) UNMARK_BIT(v, 6);
-
- FOREACHVERTEX(v, n)
- {
- grd = 0;
- if (!IS_BIT(v, 6) && v->isOnBoundary())
- {
- tbds++;
- w = v;
- do
- {
- if (IS_BIT(w, 6)) grd=nbe+1;
- MARK_BIT(w, 6);
- grd++;
- w = w->nextOnBoundary();
- } while (w != v);
- if (grd <= nbe) bdrs.appendHead(w->nextBoundaryEdge());
- }
- }
- FOREACHVERTEX(v, n) { UNMARK_BIT(v, 5); UNMARK_BIT(v, 6); }
-
- deselectTriangles();
-
- pct=0; FOREACHNODE(bdrs, n)
- {
- if (TriangulateHole((Edge *)n->data) && refine_patches)
- {
- t = (Triangle *)T.head()->data;
- refineSelectedHolePatches(t);
- }
- TMesh::report_progress("%d%% done ",((++pct)*100)/bdrs.numels());
- }
-
- grd = bdrs.numels();
-
- TMesh::end_progress();
-
- return grd;
-}
-
-
-// Inserts new vertices in the current selection so as
-// to reflect the density of the surrounding mesh.
-// This method assumes that the selection has no internal vertices.
-
-int Basic_TMesh::refineSelectedHolePatches(Triangle *t0)
-{
- Node *n, *m;
- Triangle *t, *t1, *t2;
- Edge *e, *f;
- Vertex *v;
- List *ve, toswap, reg, all_edges, interior_edges, boundary_edges, boundary_vertices, interior_vertices;
- doubleWrapper sigma, l, sv1, sv2, sv3, dv1, dv2, dv3;
- int swaps, totits, nee, ntb, nnt=-1, pnnt, gits=0;
- const double alpha = sqrt(2.0);
- Point vc;
-
- if (t0 != NULL)
- {
- if (!IS_VISITED(t0)) TMesh::error("refineSelectedHolePatches: unexpected unselected t0 !");
- UNMARK_VISIT(t0); toswap.appendHead(t0);
- while ((t=(Triangle *)toswap.popHead()) != NULL)
- {
- reg.appendHead(t);
- t1=t->t1(); if (IS_VISITED(t1)) {UNMARK_VISIT(t1); toswap.appendHead(t1);}
- t1=t->t2(); if (IS_VISITED(t1)) {UNMARK_VISIT(t1); toswap.appendHead(t1);}
- t1=t->t3(); if (IS_VISITED(t1)) {UNMARK_VISIT(t1); toswap.appendHead(t1);}
- }
- FOREACHVTTRIANGLE((®), t, n) MARK_VISIT(t);
- }
- else FOREACHTRIANGLE(t, n) if (IS_VISITED(t)) reg.appendHead(t);
-
- printf("%d\n",reg.numels());
-
- FOREACHVTTRIANGLE((®), t, n)
- {
- e = t->e1; if (!IS_BIT(e, 5)) {MARK_BIT(e, 5); all_edges.appendHead(e);} else UNMARK_BIT(e, 5);
- e = t->e2; if (!IS_BIT(e, 5)) {MARK_BIT(e, 5); all_edges.appendHead(e);} else UNMARK_BIT(e, 5);
- e = t->e3; if (!IS_BIT(e, 5)) {MARK_BIT(e, 5); all_edges.appendHead(e);} else UNMARK_BIT(e, 5);
- }
-
- while (all_edges.numels())
- {
- e = (Edge *)all_edges.popHead();
- if (IS_BIT(e, 5)) { boundary_edges.appendHead(e); UNMARK_BIT(e, 5); }
- else { interior_edges.appendHead(e); MARK_BIT(e, 5); }
- }
-
- FOREACHVEEDGE((&boundary_edges), e, n)
- {
- v = e->v1; if (!IS_BIT(v, 5)) { MARK_BIT(v, 5); boundary_vertices.appendHead(v);}
- v = e->v2; if (!IS_BIT(v, 5)) { MARK_BIT(v, 5); boundary_vertices.appendHead(v);}
- }
-
- FOREACHVVVERTEX((&boundary_vertices), v, n) UNMARK_BIT(v, 5);
-
- // Due to the above definitions, interior edges are BIT
-
- FOREACHVVVERTEX((&boundary_vertices), v, n)
- {
- ve = v->VE();
- sigma=0; nee=0; FOREACHVEEDGE(ve, e, m) if (!IS_BIT(e, 5)) {nee++; sigma += e->length();}
- sigma /= double(nee); v->info = new doubleWrapper(sigma);
- delete(ve);
- }
-
- FOREACHVEEDGE((&interior_edges), e, n) UNMARK_BIT(e, 5);
- FOREACHVEEDGE((&boundary_edges), e, n) MARK_BIT(e, 6);
-
- do
- {
- pnnt=nnt;
- nnt=0;
- FOREACHVTTRIANGLE((®), t, n)
- {
- vc = t->getCenter();
- sv1 = (*(doubleWrapper *)t->v1()->info);
- sv2 = (*(doubleWrapper *)t->v2()->info);
- sv3 = (*(doubleWrapper *)t->v3()->info);
- sigma = (sv1+sv2+sv3)/3.0;
- dv1 = alpha*(t->v1()->distance(&vc));
- dv2 = alpha*(t->v2()->distance(&vc));
- dv3 = alpha*(t->v3()->distance(&vc));
- if (dv1>sigma && dv1>sv1 && dv2>sigma && dv2>sv2 && dv3>sigma && dv3>sv3)
- {
- ntb = T.numels();
- v = splitTriangle(t,&vc,1);
- nnt += (T.numels()-ntb);
- if (T.numels() == ntb+2)
- {
- v->info = new doubleWrapper(sigma);
- interior_vertices.appendHead(v);
- interior_edges.appendHead(v->e0);
- interior_edges.appendHead(v->e0->leftTriangle(v)->prevEdge(v->e0));
- interior_edges.appendHead(v->e0->rightTriangle(v)->nextEdge(v->e0));
- t1 = ((Triangle *)T.head()->data);
- t2 = ((Triangle *)T.head()->next()->data);
- t1->mask = t2->mask = t->mask;
- reg.appendHead(t1); reg.appendHead(t2);
- }
- }
- }
-
- FOREACHVEEDGE((&interior_edges), e, n) {MARK_BIT(e, 5); toswap.appendHead(e);}
- totits=0; swaps=1;
- while (swaps && totits++ < 10)
- {
- swaps = 0;
- while ((e=(Edge *)toswap.popHead())!=NULL)
- {
- UNMARK_BIT(e, 5);
- l = e->squaredLength();
- if (e->swap())
- {
- if (e->squaredLength() >= l*0.999999) e->swap(1);
- else
- {
- swaps++;
- toswap.appendTail(e);
- f = e->t1->nextEdge(e); if (!IS_BIT(f, 5) && !IS_BIT(f, 6)) { MARK_BIT(f, 5); toswap.appendTail(f); }
- f = e->t1->prevEdge(e); if (!IS_BIT(f, 5) && !IS_BIT(f, 6)) { MARK_BIT(f, 5); toswap.appendTail(f); }
- f = e->t2->nextEdge(e); if (!IS_BIT(f, 5) && !IS_BIT(f, 6)) { MARK_BIT(f, 5); toswap.appendTail(f); }
- f = e->t2->prevEdge(e); if (!IS_BIT(f, 5) && !IS_BIT(f, 6)) { MARK_BIT(f, 5); toswap.appendTail(f); }
- }
- }
- }
- }
-
- if (pnnt==nnt) gits++;
- } while (nnt && gits<10);
-
- //FOREACHVEEDGE((&boundary_edges), e, n) UNMARK_BIT(e, 6);
- FOREACHVVVERTEX((&boundary_vertices), v, n) { delete((Data *)v->info); v->info = NULL; MARK_BIT(v, 5);}
- FOREACHVVVERTEX((&interior_vertices), v, n) { delete((Data *)v->info); v->info = NULL; MARK_BIT(v, 6);}
-
- if (gits>=10) {TMesh::warning("Fill holes: Refinement stage failed to converge. Breaking.\n"); return 1;}
-
- return 0;
-}
-
-// Joins the two boundary vertices gv and gw through an edge. A pair of triangles is
-// added to properly change the topology of the mesh.
-// On success, the return value is the new edge connecting the two vertices.
-// NULL is returned on failure.
-// Failure occurs if gv and gw are not both on boundary.
-// If 'justconnect' is false, the remaining hole is filled with new triangles, unless
-// gv and gw are contiguous on the boundary loop (failure).
-// If 'justconnect' is true, gv and gw must not belong to the same boundary loop (failure).
-// If 'refine', the patching triangles are refined to reproduce neighboring density.
-
-Edge *Basic_TMesh::joinBoundaryLoops(Vertex *gv, Vertex *gw, bool justconnect, bool refine)
-{
- Vertex *v, *gvn, *gwn;
- Edge *e, *gve, *gwe;
- Triangle *t;
- Node *n;
- double tl1 = 0.0, tl2 = 0.0, pl1, pl2;
-
- if (gv == NULL || gw == NULL || !gv->isOnBoundary() || !gw->isOnBoundary()) return NULL;
-
- FOREACHVERTEX(v, n) UNMARK_VISIT(v);
- deselectTriangles();
-
- v = gv;
- if (!justconnect)
- {
- do { v = v->nextOnBoundary(); if (v == gw) return NULL; } while (v != gv);
- } else
- {
- gvn = gv->nextOnBoundary(); gwn = gv->prevOnBoundary();
- if (gw == gvn || gw == gwn) return NULL;
- if (gw == gvn->nextOnBoundary())
- {
- t = EulerEdgeTriangle(gvn->prevBoundaryEdge(), gvn->nextBoundaryEdge()); MARK_VISIT(t); return t->oppositeEdge(gvn);
- }
- if (gw == gwn->prevOnBoundary())
- {
- t = EulerEdgeTriangle(gwn->prevBoundaryEdge(), gwn->nextBoundaryEdge()); MARK_VISIT(t); return t->oppositeEdge(gwn);
- }
- }
-
- gve = gv->prevBoundaryEdge();
- gvn = gve->oppositeVertex(gv);
- gwe = gw->nextBoundaryEdge();
- gwn = gwe->oppositeVertex(gw);
-
- Edge *je = CreateEdge(gv, gw);
- Edge *je1 = CreateEdge(gv, gwn);
- Edge *je2 = CreateEdge(gwn, gvn);
-
- t = CreateTriangle(je, gwe, je1); MARK_VISIT(t);
- t = CreateTriangle(je1, je2, gve); MARK_VISIT(t);
-
- if (justconnect) return je;
-
- v = gv; do { e = v->nextBoundaryEdge(); v = e->oppositeVertex(v); tl1 += e->length(); } while (v != gv);
- v = gw; do { e = v->nextBoundaryEdge(); v = e->oppositeVertex(v); tl2 += e->length(); } while (v != gw);
- pl1 = tl1; pl2 = tl2;
-
- double c1, c2;
-
- e = je;
- while (e->isOnBoundary())
- {
- gv = (e->t2 != NULL) ? (e->v2) : (e->v1); gve = gv->nextBoundaryEdge();
- gw = (e->t1 != NULL) ? (e->v2) : (e->v1); gwe = gw->prevBoundaryEdge();
- c1 = fabs((pl1 - gve->length())*tl2 - pl2*tl1);
- c2 = fabs((pl2 - gwe->length())*tl1 - pl1*tl2);
- if (c1length();
- e = t->nextEdge(gve);
- } else
- {
- t = EulerEdgeTriangle(gwe, e); MARK_VISIT(t);
- pl2 -= gwe->length();
- e = t->prevEdge(gwe);
- }
- }
-
- if (refine) refineSelectedHolePatches();
-
- return je;
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/Algorithms/marchIntersections.cpp b/src/mesh_fix/src/Algorithms/marchIntersections.cpp
deleted file mode 100644
index 8da0f440c..000000000
--- a/src/mesh_fix/src/Algorithms/marchIntersections.cpp
+++ /dev/null
@@ -1,1039 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "marchIntersections.h"
-
-namespace T_MESH
-{
-
-int mc_ints::compare(const Data *e1, const Data *e2)
-{
- mc_ints *a = (mc_ints *)e1;
- mc_ints *b = (mc_ints *)e2;
- coord& l1 = a->ic;
- coord& l2 = b->ic;
- if (l1 < l2) return -1;
- if (l2 < l1) return 1;
-
- return 0;
-}
-
-UBYTE mc_cell::lookup() const
-{
- UBYTE l = 0;
- int v[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }, m;
-
- if (ints[0]) if (ints[0]->sg) v[1] = 1; else v[0] = 1;
- if (ints[1]) if (ints[1]->sg) v[2] = 1; else v[1] = 1;
- if (ints[2]) if (ints[2]->sg) v[2] = 1; else v[3] = 1;
- if (ints[3]) if (ints[3]->sg) v[3] = 1; else v[0] = 1;
-
- if (ints[4]) if (ints[4]->sg) v[5] = 1; else v[4] = 1;
- if (ints[5]) if (ints[5]->sg) v[6] = 1; else v[5] = 1;
- if (ints[6]) if (ints[6]->sg) v[6] = 1; else v[7] = 1;
- if (ints[7]) if (ints[7]->sg) v[7] = 1; else v[4] = 1;
-
- if (ints[8]) if (ints[8]->sg) v[4] = 1; else v[0] = 1;
- if (ints[9]) if (ints[9]->sg) v[5] = 1; else v[1] = 1;
- if (ints[10]) if (ints[10]->sg) v[6] = 1; else v[2] = 1;
- if (ints[11]) if (ints[11]->sg) v[7] = 1; else v[3] = 1;
-
- if (v[0] && !ints[0]) v[1] = 1;
- if (v[0] && !ints[3]) v[3] = 1;
- if (v[0] && !ints[8]) v[4] = 1;
-
- if (v[1] && !ints[0]) v[0] = 1;
- if (v[1] && !ints[1]) v[2] = 1;
- if (v[1] && !ints[9]) v[5] = 1;
-
- if (v[2] && !ints[1]) v[1] = 1;
- if (v[2] && !ints[2]) v[3] = 1;
- if (v[2] && !ints[10]) v[6] = 1;
-
- if (v[3] && !ints[2]) v[2] = 1;
- if (v[3] && !ints[3]) v[0] = 1;
- if (v[3] && !ints[11]) v[7] = 1;
-
- if (v[4] && !ints[4]) v[5] = 1;
- if (v[4] && !ints[7]) v[7] = 1;
- if (v[4] && !ints[8]) v[0] = 1;
-
- if (v[5] && !ints[4]) v[4] = 1;
- if (v[5] && !ints[5]) v[6] = 1;
- if (v[5] && !ints[9]) v[1] = 1;
-
- if (v[6] && !ints[5]) v[5] = 1;
- if (v[6] && !ints[6]) v[7] = 1;
- if (v[6] && !ints[10]) v[2] = 1;
-
- if (v[7] && !ints[6]) v[6] = 1;
- if (v[7] && !ints[7]) v[4] = 1;
- if (v[7] && !ints[11]) v[3] = 1;
-
- for (m = 0; m<8; m++) l |= (((UBYTE)((v[m]) ? (1) : (0))) << m);
-
- return l;
-}
-
-
-UBYTE mc_cell::lookdown()
-{
- int v[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }, m;
- UBYTE i;
- const UBYTE c1[12] = { 0, 1, 3, 0, 4, 5, 7, 4, 0, 1, 2, 3 };
- const UBYTE c2[12] = { 1, 2, 2, 3, 5, 6, 6, 7, 4, 5, 6, 7 };
- const UBYTE e1[8] = { 0, 0, 2, 2, 4, 4, 6, 6 };
- const UBYTE e2[8] = { 3, 1, 1, 3, 7, 5, 5, 7 };
- const UBYTE e3[8] = { 8, 9, 10, 11, 8, 9, 10, 11 };
-
- for (i = 0; i < 12; i++) if (ints[i])
- {
- if (ints[i]->sg) v[c2[i]] = 1; else v[c1[i]] = 1;
- }
-
- for (m = 0; m < 8; m++) if (v[m])
- {
- if (!ints[e1[m]] && !v[c1[e1[m]]]) { v[c1[e1[m]]] = 1; if (c1[e1[m]] < m) { m = -1; continue; } }
- if (!ints[e1[m]] && !v[c2[e1[m]]]) { v[c2[e1[m]]] = 1; if (c2[e1[m]] < m) { m = -1; continue; } }
- if (!ints[e2[m]] && !v[c1[e2[m]]]) { v[c1[e2[m]]] = 1; if (c1[e2[m]] < m) { m = -1; continue; } }
- if (!ints[e2[m]] && !v[c2[e2[m]]]) { v[c2[e2[m]]] = 1; if (c2[e2[m]] < m) { m = -1; continue; } }
- if (!ints[e3[m]] && !v[c1[e3[m]]]) { v[c1[e3[m]]] = 1; if (c1[e3[m]] < m) { m = -1; continue; } }
- if (!ints[e3[m]] && !v[c2[e3[m]]]) { v[c2[e3[m]]] = 1; if (c2[e3[m]] < m) { m = -1; continue; } }
- }
-
- i = 0;
- for (m = 0; m<8; m++) i |= (((UBYTE)((v[m]) ? (1) : (0))) << m);
-
- return i;
-}
-
-int mc_cell::compare(const Data *e1, const Data *e2)
-{
- mc_cell *a = (mc_cell *)e1;
- mc_cell *b = (mc_cell *)e2;
- int c;
-
- if ((c=(a->x - b->x)) < 0) return -1;
- if (c > 0) return 1;
- if ((c=(a->y - b->y)) < 0) return -1;
- if (c > 0) return 1;
- if ((c=(a->z - b->z)) < 0) return -1;
- if (c > 0) return 1;
-
- return 0;
-}
-
-
-
-void mc_cell::polygonize(Basic_TMesh *tin)
-{
- ExtVertex *v[12];
- Edge *e1,*e2,*e3;
- int i,t[3];
- unsigned char lu = lookdown();
-
- static const char mc_triTable[256][20] =
- {
- {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 8, 3, -1, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 8, 3, -1, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 2, 10, -1, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 2, 8, 3, -1, 2, 10, 8, -1, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 11, 2, -1, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 9, 0, -1, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 11, 2, -1, 1, 9, 11, -1, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 10, 1, -1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 10, 1, -1, 0, 8, 10, -1, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 9, 0, -1, 3, 11, 9, -1, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 8, 10, -1, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 3, 0, -1, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 1, 9, -1, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 1, 9, -1, 4, 7, 1, -1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 2, 10, -1, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 4, 7, -1, 3, 0, 4, -1, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 2, 10, -1, 9, 0, 2, -1, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 2, 10, 9, -1, 2, 9, 7, -1, 2, 7, 3, -1, 7, 9, 4, -1, -1, -1, -1, -1},
- { 8, 4, 7, -1, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {11, 4, 7, -1, 11, 2, 4, -1, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 0, 1, -1, 8, 4, 7, -1, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 7, 11, -1, 9, 4, 11, -1, 9, 11, 2, -1, 9, 2, 1, -1, -1, -1, -1, -1},
- { 3, 10, 1, -1, 3, 11, 10, -1, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 11, 10, -1, 1, 4, 11, -1, 1, 0, 4, -1, 7, 11, 4, -1, -1, -1, -1, -1},
- { 4, 7, 8, -1, 9, 0, 11, -1, 9, 11, 10, -1, 11, 0, 3, -1, -1, -1, -1, -1},
- { 4, 7, 11, -1, 4, 11, 9, -1, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 5, 4, -1, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 5, 4, -1, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 8, 5, 4, -1, 8, 3, 5, -1, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 2, 10, -1, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 0, 8, -1, 1, 2, 10, -1, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 5, 2, 10, -1, 5, 4, 2, -1, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 2, 10, 5, -1, 3, 2, 5, -1, 3, 5, 4, -1, 3, 4, 8, -1, -1, -1, -1, -1},
- { 9, 5, 4, -1, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 11, 2, -1, 0, 8, 11, -1, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 5, 4, -1, 0, 1, 5, -1, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 2, 1, 5, -1, 2, 5, 8, -1, 2, 8, 11, -1, 4, 8, 5, -1, -1, -1, -1, -1},
- {10, 3, 11, -1, 10, 1, 3, -1, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 9, 5, -1, 0, 8, 1, -1, 8, 10, 1, -1, 8, 11, 10, -1, -1, -1, -1, -1},
- { 5, 4, 0, -1, 5, 0, 11, -1, 5, 11, 10, -1, 11, 0, 3, -1, -1, -1, -1, -1},
- { 5, 4, 8, -1, 5, 8, 10, -1, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 7, 8, -1, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 3, 0, -1, 9, 5, 3, -1, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 7, 8, -1, 0, 1, 7, -1, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 5, 3, -1, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 7, 8, -1, 9, 5, 7, -1, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {10, 1, 2, -1, 9, 5, 0, -1, 5, 3, 0, -1, 5, 7, 3, -1, -1, -1, -1, -1},
- { 8, 0, 2, -1, 8, 2, 5, -1, 8, 5, 7, -1, 10, 5, 2, -1, -1, -1, -1, -1},
- { 2, 10, 5, -1, 2, 5, 3, -1, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 7, 9, 5, -1, 7, 8, 9, -1, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 5, 7, -1, 9, 7, 2, -1, 9, 2, 0, -1, 2, 7, 11, -1, -1, -1, -1, -1},
- { 2, 3, 11, -1, 0, 1, 8, -1, 1, 7, 8, -1, 1, 5, 7, -1, -1, -1, -1, -1},
- {11, 2, 1, -1, 11, 1, 7, -1, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 5, 8, -1, 8, 5, 7, -1, 10, 1, 3, -1, 10, 3, 11, -1, -1, -1, -1, -1},
- { 5, 7, 0, -1, 5, 0, 9, -1, 7, 11, 0, -1, 1, 0, 10, -1, 11, 10, 0, -1},
- {11, 10, 0, -1, 11, 0, 3, -1, 10, 5, 0, -1, 8, 0, 7, -1, 5, 7, 0, -1},
- {11, 10, 5, -1, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 8, 3, -1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 0, 1, -1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 8, 3, -1, 1, 9, 8, -1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 6, 5, -1, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 6, 5, -1, 1, 2, 6, -1, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 6, 5, -1, 9, 0, 6, -1, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 5, 9, 8, -1, 5, 8, 2, -1, 5, 2, 6, -1, 3, 2, 8, -1, -1, -1, -1, -1},
- { 2, 3, 11, -1, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {11, 0, 8, -1, 11, 2, 0, -1, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 1, 9, -1, 2, 3, 11, -1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 5, 10, 6, -1, 1, 9, 2, -1, 9, 11, 2, -1, 9, 8, 11, -1, -1, -1, -1, -1},
- { 6, 3, 11, -1, 6, 5, 3, -1, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 8, 11, -1, 0, 11, 5, -1, 0, 5, 1, -1, 5, 11, 6, -1, -1, -1, -1, -1},
- { 3, 11, 6, -1, 0, 3, 6, -1, 0, 6, 5, -1, 0, 5, 9, -1, -1, -1, -1, -1},
- { 6, 5, 9, -1, 6, 9, 11, -1, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 5, 10, 6, -1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 3, 0, -1, 4, 7, 3, -1, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 9, 0, -1, 5, 10, 6, -1, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {10, 6, 5, -1, 1, 9, 7, -1, 1, 7, 3, -1, 7, 9, 4, -1, -1, -1, -1, -1},
- { 6, 1, 2, -1, 6, 5, 1, -1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 2, 5, -1, 5, 2, 6, -1, 3, 0, 4, -1, 3, 4, 7, -1, -1, -1, -1, -1},
- { 8, 4, 7, -1, 9, 0, 5, -1, 0, 6, 5, -1, 0, 2, 6, -1, -1, -1, -1, -1},
- { 7, 3, 9, -1, 7, 9, 4, -1, 3, 2, 9, -1, 5, 9, 6, -1, 2, 6, 9, -1},
- { 3, 11, 2, -1, 7, 8, 4, -1, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 5, 10, 6, -1, 4, 7, 2, -1, 4, 2, 0, -1, 2, 7, 11, -1, -1, -1, -1, -1},
- { 0, 1, 9, -1, 4, 7, 8, -1, 2, 3, 11, -1, 5, 10, 6, -1, -1, -1, -1, -1},
- { 9, 2, 1, -1, 9, 11, 2, -1, 9, 4, 11, -1, 7, 11, 4, -1, 5, 10, 6, -1},
- { 8, 4, 7, -1, 3, 11, 5, -1, 3, 5, 1, -1, 5, 11, 6, -1, -1, -1, -1, -1},
- { 5, 1, 11, -1, 5, 11, 6, -1, 1, 0, 11, -1, 7, 11, 4, -1, 0, 4, 11, -1},
- { 0, 5, 9, -1, 0, 6, 5, -1, 0, 3, 6, -1, 11, 6, 3, -1, 8, 4, 7, -1},
- { 6, 5, 9, -1, 6, 9, 11, -1, 4, 7, 9, -1, 7, 11, 9, -1, -1, -1, -1, -1},
- {10, 4, 9, -1, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 10, 6, -1, 4, 9, 10, -1, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {10, 0, 1, -1, 10, 6, 0, -1, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 8, 3, 1, -1, 8, 1, 6, -1, 8, 6, 4, -1, 6, 1, 10, -1, -1, -1, -1, -1},
- { 1, 4, 9, -1, 1, 2, 4, -1, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 0, 8, -1, 1, 2, 9, -1, 2, 4, 9, -1, 2, 6, 4, -1, -1, -1, -1, -1},
- { 0, 2, 4, -1, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 8, 3, 2, -1, 8, 2, 4, -1, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {10, 4, 9, -1, 10, 6, 4, -1, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 8, 2, -1, 2, 8, 11, -1, 4, 9, 10, -1, 4, 10, 6, -1, -1, -1, -1, -1},
- { 3, 11, 2, -1, 0, 1, 6, -1, 0, 6, 4, -1, 6, 1, 10, -1, -1, -1, -1, -1},
- { 6, 4, 1, -1, 6, 1, 10, -1, 4, 8, 1, -1, 2, 1, 11, -1, 8, 11, 1, -1},
- { 9, 6, 4, -1, 9, 3, 6, -1, 9, 1, 3, -1, 11, 6, 3, -1, -1, -1, -1, -1},
- { 8, 11, 1, -1, 8, 1, 0, -1, 11, 6, 1, -1, 9, 1, 4, -1, 6, 4, 1, -1},
- { 3, 11, 6, -1, 3, 6, 0, -1, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 6, 4, 8, -1, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 7, 10, 6, -1, 7, 8, 10, -1, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 7, 3, -1, 0, 10, 7, -1, 0, 9, 10, -1, 6, 7, 10, -1, -1, -1, -1, -1},
- {10, 6, 7, -1, 1, 10, 7, -1, 1, 7, 8, -1, 1, 8, 0, -1, -1, -1, -1, -1},
- {10, 6, 7, -1, 10, 7, 1, -1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 2, 6, -1, 1, 6, 8, -1, 1, 8, 9, -1, 8, 6, 7, -1, -1, -1, -1, -1},
- { 2, 6, 9, -1, 2, 9, 1, -1, 6, 7, 9, -1, 0, 9, 3, -1, 7, 3, 9, -1},
- { 7, 8, 0, -1, 7, 0, 6, -1, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 7, 3, 2, -1, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 2, 3, 11, -1, 10, 6, 8, -1, 10, 8, 9, -1, 8, 6, 7, -1, -1, -1, -1, -1},
- { 2, 0, 7, -1, 2, 7, 11, -1, 0, 9, 7, -1, 6, 7, 10, -1, 9, 10, 7, -1},
- { 1, 8, 0, -1, 1, 7, 8, -1, 1, 10, 7, -1, 6, 7, 10, -1, 2, 3, 11, -1},
- {11, 2, 1, -1, 11, 1, 7, -1, 10, 6, 1, -1, 6, 7, 1, -1, -1, -1, -1, -1},
- { 8, 9, 6, -1, 8, 6, 7, -1, 9, 1, 6, -1, 11, 6, 3, -1, 1, 3, 6, -1},
- { 0, 9, 1, -1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 7, 8, 0, -1, 7, 0, 6, -1, 3, 11, 0, -1, 11, 6, 0, -1, -1, -1, -1, -1},
- { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 0, 8, -1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 1, 9, -1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 8, 1, 9, -1, 8, 3, 1, -1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {10, 1, 2, -1, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 2, 10, -1, 3, 0, 8, -1, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 2, 9, 0, -1, 2, 10, 9, -1, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 6, 11, 7, -1, 2, 10, 3, -1, 10, 8, 3, -1, 10, 9, 8, -1, -1, -1, -1, -1},
- { 7, 2, 3, -1, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 7, 0, 8, -1, 7, 6, 0, -1, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 2, 7, 6, -1, 2, 3, 7, -1, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 6, 2, -1, 1, 8, 6, -1, 1, 9, 8, -1, 8, 7, 6, -1, -1, -1, -1, -1},
- {10, 7, 6, -1, 10, 1, 7, -1, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {10, 7, 6, -1, 1, 7, 10, -1, 1, 8, 7, -1, 1, 0, 8, -1, -1, -1, -1, -1},
- { 0, 3, 7, -1, 0, 7, 10, -1, 0, 10, 9, -1, 6, 10, 7, -1, -1, -1, -1, -1},
- { 7, 6, 10, -1, 7, 10, 8, -1, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 6, 8, 4, -1, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 6, 11, -1, 3, 0, 6, -1, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 8, 6, 11, -1, 8, 4, 6, -1, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 4, 6, -1, 9, 6, 3, -1, 9, 3, 1, -1, 11, 3, 6, -1, -1, -1, -1, -1},
- { 6, 8, 4, -1, 6, 11, 8, -1, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 2, 10, -1, 3, 0, 11, -1, 0, 6, 11, -1, 0, 4, 6, -1, -1, -1, -1, -1},
- { 4, 11, 8, -1, 4, 6, 11, -1, 0, 2, 9, -1, 2, 10, 9, -1, -1, -1, -1, -1},
- {10, 9, 3, -1, 10, 3, 2, -1, 9, 4, 3, -1, 11, 3, 6, -1, 4, 6, 3, -1},
- { 8, 2, 3, -1, 8, 4, 2, -1, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 4, 2, -1, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 9, 0, -1, 2, 3, 4, -1, 2, 4, 6, -1, 4, 3, 8, -1, -1, -1, -1, -1},
- { 1, 9, 4, -1, 1, 4, 2, -1, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 8, 1, 3, -1, 8, 6, 1, -1, 8, 4, 6, -1, 6, 10, 1, -1, -1, -1, -1, -1},
- {10, 1, 0, -1, 10, 0, 6, -1, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 6, 3, -1, 4, 3, 8, -1, 6, 10, 3, -1, 0, 3, 9, -1, 10, 9, 3, -1},
- {10, 9, 4, -1, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 9, 5, -1, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 8, 3, -1, 4, 9, 5, -1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 5, 0, 1, -1, 5, 4, 0, -1, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {11, 7, 6, -1, 8, 3, 4, -1, 3, 5, 4, -1, 3, 1, 5, -1, -1, -1, -1, -1},
- { 9, 5, 4, -1, 10, 1, 2, -1, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 6, 11, 7, -1, 1, 2, 10, -1, 0, 8, 3, -1, 4, 9, 5, -1, -1, -1, -1, -1},
- { 7, 6, 11, -1, 5, 4, 10, -1, 4, 2, 10, -1, 4, 0, 2, -1, -1, -1, -1, -1},
- { 3, 4, 8, -1, 3, 5, 4, -1, 3, 2, 5, -1, 10, 5, 2, -1, 11, 7, 6, -1},
- { 7, 2, 3, -1, 7, 6, 2, -1, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 5, 4, -1, 0, 8, 6, -1, 0, 6, 2, -1, 6, 8, 7, -1, -1, -1, -1, -1},
- { 3, 6, 2, -1, 3, 7, 6, -1, 1, 5, 0, -1, 5, 4, 0, -1, -1, -1, -1, -1},
- { 6, 2, 8, -1, 6, 8, 7, -1, 2, 1, 8, -1, 4, 8, 5, -1, 1, 5, 8, -1},
- { 9, 5, 4, -1, 10, 1, 6, -1, 1, 7, 6, -1, 1, 3, 7, -1, -1, -1, -1, -1},
- { 1, 6, 10, -1, 1, 7, 6, -1, 1, 0, 7, -1, 8, 7, 0, -1, 9, 5, 4, -1},
- { 4, 0, 10, -1, 4, 10, 5, -1, 0, 3, 10, -1, 6, 10, 7, -1, 3, 7, 10, -1},
- { 7, 6, 10, -1, 7, 10, 8, -1, 5, 4, 10, -1, 4, 8, 10, -1, -1, -1, -1, -1},
- { 6, 9, 5, -1, 6, 11, 9, -1, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 6, 11, -1, 0, 6, 3, -1, 0, 5, 6, -1, 0, 9, 5, -1, -1, -1, -1, -1},
- { 0, 11, 8, -1, 0, 5, 11, -1, 0, 1, 5, -1, 5, 6, 11, -1, -1, -1, -1, -1},
- { 6, 11, 3, -1, 6, 3, 5, -1, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 2, 10, -1, 9, 5, 11, -1, 9, 11, 8, -1, 11, 5, 6, -1, -1, -1, -1, -1},
- { 0, 11, 3, -1, 0, 6, 11, -1, 0, 9, 6, -1, 5, 6, 9, -1, 1, 2, 10, -1},
- {11, 8, 5, -1, 11, 5, 6, -1, 8, 0, 5, -1, 10, 5, 2, -1, 0, 2, 5, -1},
- { 6, 11, 3, -1, 6, 3, 5, -1, 2, 10, 3, -1, 10, 5, 3, -1, -1, -1, -1, -1},
- { 5, 8, 9, -1, 5, 2, 8, -1, 5, 6, 2, -1, 3, 8, 2, -1, -1, -1, -1, -1},
- { 9, 5, 6, -1, 9, 6, 0, -1, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 5, 8, -1, 1, 8, 0, -1, 5, 6, 8, -1, 3, 8, 2, -1, 6, 2, 8, -1},
- { 1, 5, 6, -1, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 3, 6, -1, 1, 6, 10, -1, 3, 8, 6, -1, 5, 6, 9, -1, 8, 9, 6, -1},
- {10, 1, 0, -1, 10, 0, 6, -1, 9, 5, 0, -1, 5, 6, 0, -1, -1, -1, -1, -1},
- { 0, 3, 8, -1, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {11, 5, 10, -1, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {11, 5, 10, -1, 11, 7, 5, -1, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 5, 11, 7, -1, 5, 10, 11, -1, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {10, 7, 5, -1, 10, 11, 7, -1, 9, 8, 1, -1, 8, 3, 1, -1, -1, -1, -1, -1},
- {11, 1, 2, -1, 11, 7, 1, -1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 8, 3, -1, 1, 2, 7, -1, 1, 7, 5, -1, 7, 2, 11, -1, -1, -1, -1, -1},
- { 9, 7, 5, -1, 9, 2, 7, -1, 9, 0, 2, -1, 2, 11, 7, -1, -1, -1, -1, -1},
- { 7, 5, 2, -1, 7, 2, 11, -1, 5, 9, 2, -1, 3, 2, 8, -1, 9, 8, 2, -1},
- { 2, 5, 10, -1, 2, 3, 5, -1, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 8, 2, 0, -1, 8, 5, 2, -1, 8, 7, 5, -1, 10, 2, 5, -1, -1, -1, -1, -1},
- { 9, 0, 1, -1, 5, 10, 3, -1, 5, 3, 7, -1, 3, 10, 2, -1, -1, -1, -1, -1},
- { 9, 8, 2, -1, 9, 2, 1, -1, 8, 7, 2, -1, 10, 2, 5, -1, 7, 5, 2, -1},
- { 1, 3, 5, -1, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 8, 7, -1, 0, 7, 1, -1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 0, 3, -1, 9, 3, 5, -1, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 8, 7, -1, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 5, 8, 4, -1, 5, 10, 8, -1, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 5, 0, 4, -1, 5, 11, 0, -1, 5, 10, 11, -1, 11, 3, 0, -1, -1, -1, -1, -1},
- { 0, 1, 9, -1, 8, 4, 10, -1, 8, 10, 11, -1, 10, 4, 5, -1, -1, -1, -1, -1},
- {10, 11, 4, -1, 10, 4, 5, -1, 11, 3, 4, -1, 9, 4, 1, -1, 3, 1, 4, -1},
- { 2, 5, 1, -1, 2, 8, 5, -1, 2, 11, 8, -1, 4, 5, 8, -1, -1, -1, -1, -1},
- { 0, 4, 11, -1, 0, 11, 3, -1, 4, 5, 11, -1, 2, 11, 1, -1, 5, 1, 11, -1},
- { 0, 2, 5, -1, 0, 5, 9, -1, 2, 11, 5, -1, 4, 5, 8, -1, 11, 8, 5, -1},
- { 9, 4, 5, -1, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 2, 5, 10, -1, 3, 5, 2, -1, 3, 4, 5, -1, 3, 8, 4, -1, -1, -1, -1, -1},
- { 5, 10, 2, -1, 5, 2, 4, -1, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 10, 2, -1, 3, 5, 10, -1, 3, 8, 5, -1, 4, 5, 8, -1, 0, 1, 9, -1},
- { 5, 10, 2, -1, 5, 2, 4, -1, 1, 9, 2, -1, 9, 4, 2, -1, -1, -1, -1, -1},
- { 8, 4, 5, -1, 8, 5, 3, -1, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 4, 5, -1, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 8, 4, 5, -1, 8, 5, 3, -1, 9, 0, 5, -1, 0, 3, 5, -1, -1, -1, -1, -1},
- { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 11, 7, -1, 4, 9, 11, -1, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 8, 3, -1, 4, 9, 7, -1, 9, 11, 7, -1, 9, 10, 11, -1, -1, -1, -1, -1},
- { 1, 10, 11, -1, 1, 11, 4, -1, 1, 4, 0, -1, 7, 4, 11, -1, -1, -1, -1, -1},
- { 3, 1, 4, -1, 3, 4, 8, -1, 1, 10, 4, -1, 7, 4, 11, -1, 10, 11, 4, -1},
- { 4, 11, 7, -1, 9, 11, 4, -1, 9, 2, 11, -1, 9, 1, 2, -1, -1, -1, -1, -1},
- { 9, 7, 4, -1, 9, 11, 7, -1, 9, 1, 11, -1, 2, 11, 1, -1, 0, 8, 3, -1},
- {11, 7, 4, -1, 11, 4, 2, -1, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {11, 7, 4, -1, 11, 4, 2, -1, 8, 3, 4, -1, 3, 2, 4, -1, -1, -1, -1, -1},
- { 2, 9, 10, -1, 2, 7, 9, -1, 2, 3, 7, -1, 7, 4, 9, -1, -1, -1, -1, -1},
- { 9, 10, 7, -1, 9, 7, 4, -1, 10, 2, 7, -1, 8, 7, 0, -1, 2, 0, 7, -1},
- { 3, 7, 10, -1, 3, 10, 2, -1, 7, 4, 10, -1, 1, 10, 0, -1, 4, 0, 10, -1},
- { 1, 10, 2, -1, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 9, 1, -1, 4, 1, 7, -1, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 9, 1, -1, 4, 1, 7, -1, 0, 8, 1, -1, 8, 7, 1, -1, -1, -1, -1, -1},
- { 4, 0, 3, -1, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 10, 8, -1, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 0, 9, -1, 3, 9, 11, -1, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 1, 10, -1, 0, 10, 8, -1, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 1, 10, -1, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 2, 11, -1, 1, 11, 9, -1, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 0, 9, -1, 3, 9, 11, -1, 1, 2, 9, -1, 2, 11, 9, -1, -1, -1, -1, -1},
- { 0, 2, 11, -1, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 2, 3, 8, -1, 2, 8, 10, -1, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 9, 10, 2, -1, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 2, 3, 8, -1, 2, 8, 10, -1, 0, 1, 8, -1, 1, 10, 8, -1, -1, -1, -1, -1},
- { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 1, 3, 8, -1, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
- {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
- };
-
- for (i=0; i<12; i++) v[i] = (ints[i])?(ints[i]->v):(NULL);
- for (i=0; i<20; i+=4)
- {
- if (mc_triTable[lu][i] != -1)
- {
- t[0] = mc_triTable[lu][i];
- t[1] = mc_triTable[lu][i+1];
- t[2] = mc_triTable[lu][i+2];
- if (v[t[0]] && v[t[1]] && v[t[2]])
- {
- e1 = tin->CreateEdge(v[t[0]], v[t[1]]);
- e2 = tin->CreateEdge(v[t[1]], v[t[2]]);
- e3 = tin->CreateEdge(v[t[2]], v[t[0]]);
- if (tin->CreateTriangle(e1, e2, e3)==NULL)
- {
- TMesh::warning("mc_grid::polygonize: triangle failed.\n");
- }
- }
- else
- {
- TMesh::warning("mc_grid::polygonize: should not happen.\n");
- for (int i = 0; i < 12; i++) printf("%c ", (ints[i] == NULL) ? ('N') : ((ints[i]->sg) ? ('I') : ('O')));
- printf("\n");
- }
- }
- }
-}
-
-
-bool mc_grid::segmentIntersectsTriangle(Point& ev1, Point& ev2, Triangle *t, Point& op)
-{
- coord d1, d2, o1, o2, o3;
- Vertex *v1 = t->v1(), *v2 = t->v2(), *v3 = t->v3();
-
- d1 = ev1.exactOrientation(v1,v2,v3);
- d2 = ev2.exactOrientation(v1,v2,v3);
- if ((d1==0 && d2==0) || (d1>0 && d2>0) || (d1<0 && d2<0)) return false;
- o1 = ev1.exactOrientation(&ev2, v1, v2);
- o2 = ev1.exactOrientation(&ev2, v2, v3);
- if ((o1>0 && o2<0) || (o1<0 && o2>0)) return false;
- o3 = ev1.exactOrientation(&ev2, v3, v1);
- if ((o1>0 && o3<0) || (o1<0 && o3>0)) return false;
- if ((o2>0 && o3<0) || (o2<0 && o3>0)) return false;
-
- //bool orat = coord::use_rationals;
- //coord::use_rationals = true;
- op = Point::linePlaneIntersection(ev1, ev2, v1, v2, v3);
-// coord::use_rationals = orat;
-
- //d1 = FABS(d1); d2 = FABS(d2);
- //op = ((ev1*d2)+(ev2*d1))/(d1+d2);
-
- return true;
-}
-
-void mc_grid::sample_triangle(Triangle *t)
-{
- Vertex *v1 = t->v1(), *v2 = t->v2(), *v3 = t->v3();
- coord minx = MIN(v1->x, MIN(v2->x, v3->x)); minx = ceil(minx);
- coord Mx = MAX(v1->x, MAX(v2->x, v3->x)); Mx = floor(Mx);
- coord miny = MIN(v1->y, MIN(v2->y, v3->y)); miny = ceil(miny);
- coord My = MAX(v1->y, MAX(v2->y, v3->y)); My = floor(My);
- coord minz = MIN(v1->z, MIN(v2->z, v3->z)); minz = ceil(minz);
- coord Mz = MAX(v1->z, MAX(v2->z, v3->z)); Mz = floor(Mz);
- int i, j;
- Point p;
- UBYTE sg;
- Point normal(t->getVector());
-
- p = (*v1)+Point(0,0,1); sg = (p.exactOrientation(v1, v2, v3) < 0)?(1):(0);
- for (i = TMESH_TO_INT(minx); i <= TMESH_TO_INT(Mx); i++)
- for (j = TMESH_TO_INT(miny); j <= TMESH_TO_INT(My); j++)
- {
- Point P1(i,j,minz-1), P2(i,j,Mz+1);
- if (segmentIntersectsTriangle(P1, P2, t, p))
- {xy[i+numrays*j-1-numrays].appendTail(newMcInts(p.z, sg, t)); }
-
- }
-
- p = (*v1)+Point(0,1,0); sg = (p.exactOrientation(v1, v2, v3) < 0)?(1):(0);
- for (i = TMESH_TO_INT(minx); i <= TMESH_TO_INT(Mx); i++)
- for (j = TMESH_TO_INT(minz); j <= TMESH_TO_INT(Mz); j++)
- {
- Point P1(i,miny-1,j), P2(i,My+1,j);
- if (segmentIntersectsTriangle(P1, P2, t, p))
- {xz[i+numrays*j-1-numrays].appendTail(newMcInts(p.y, sg, t)); }
- }
-
- p = (*v1)+Point(1,0,0); sg = (p.exactOrientation(v1, v2, v3) < 0)?(1):(0);
- for (i = TMESH_TO_INT(minz); i <= TMESH_TO_INT(Mz); i++)
- for (j = TMESH_TO_INT(miny); j <= TMESH_TO_INT(My); j++)
- {
- Point P1(minx-1,j,i), P2(Mx+1,j,i);
- if (segmentIntersectsTriangle(P1, P2, t, p))
- {zy[i+numrays*j-1-numrays].appendTail(newMcInts(p.x, sg, t)); }
- }
-}
-
-void mc_grid::sort()
-{
- int i,j;
-
- for (i=0; inumels() < 2) return;
- //for (n = l->head(); n != NULL; n = n->next()) if (((mc_ints *)n->data)->sg == 1) in++; else in--;
- //if (in==0)
- //{
- // for (n = l->head(); n != NULL; n = n->next())
- // {
- // mc1 = (mc_ints *)n->data;
- // if (mc1->sg == 1) { if (in != 0) mc1->ic = -1; in++; } else if (mc1->sg == 0) { if (in != 1) mc1->ic = -1; in--; }
- // }
- //}
- //// Actual removal from list
- //for (n = l->head(); n->next() != NULL;)
- //if ((mc1 = (mc_ints *)n->data)->ic == -1) { n = n->next(); l->removeCell(n->prev()); delete mc1; } else n = n->next();
- //if (l->numels() && (mc1 = (mc_ints *)l->tail()->data)->ic == -1) { l->removeCell(l->tail()); delete mc1; }
-
-
- for (int i = 0; i < numcells; i++) count[i] = 0;
-
- // For each cell
- // Keep only first entering intersection and last existing one
-
- int ac, lc = -1;
- if (l->numels() < 2) return;
- for (n=l->head(); n != NULL; n=n->next())
- {
- mc1 = (mc_ints *)n->data;
- if (mc1->sg==1) // Only entering
- {
- if ((ac = TMESH_TO_INT(floor(mc1->ic))) == lc) mc1->ic = -1;
- else lc = ac;
- count[ac]++;
- }
- }
- lc = numcells+1;
- for (n=l->tail(); n != NULL; n=n->prev())
- {
- mc1 = (mc_ints *)n->data;
- if (mc1->sg==0) // Only exiting
- {
- if ((ac = TMESH_TO_INT(floor(mc1->ic))) == lc) mc1->ic = -1;
- else lc = ac;
- count[ac]--;
- }
- }
-
- // Actual removal from list
- for (n = l->head(); n->next() != NULL;)
- if ((mc1 = (mc_ints *)n->data)->ic == -1) { n = n->next(); l->removeCell(n->prev()); delete mc1; }
- else n = n->next();
- if (l->numels() && (mc1 = (mc_ints *)l->tail()->data)->ic == -1) { l->removeCell(l->tail()); delete mc1; }
-
- // Remove discordant intersections
- if (l->numels() < 2) return;
- for (n = l->head(); n->next() != NULL; n = n->next())
- {
- mc1 = (mc_ints *)n->data;
- mc2 = (mc_ints *)n->next()->data;
- int mc1c = TMESH_TO_INT(floor(mc1->ic));
- int mc2c = TMESH_TO_INT(floor(mc2->ic));
- if (mc1c == mc2c && mc1->sg != mc2->sg)
- {
- if ((count[mc1c] >= 0 && mc1->sg == 1) || (count[mc1c] <= 0 && mc1->sg == 0)) mc2->ic = -1;
- if ((count[mc2c] >= 0 && mc2->sg == 1) || (count[mc2c] <= 0 && mc2->sg == 0)) mc1->ic = -1;
- }
- }
- //for (n = l->head()->next(); n != l->tail(); n = n->next())
- //{
- // mc1 = (mc_ints *)n->data;
- // mc1->ic = -1;
- //}
-
- // Actual removal from list
- for (n = l->head(); n->next() != NULL;)
- if ((mc1 = (mc_ints *)n->data)->ic == -1) { n = n->next(); l->removeCell(n->prev()); delete mc1; }
- else n = n->next();
- if (l->numels() && (mc1 = (mc_ints *)l->tail()->data)->ic == -1) { l->removeCell(l->tail()); delete mc1; }
-}
-
-void mc_grid::purge()
-{
- int i,j;
-
- for (i=0; idata;
- trdc = mc->ic;
- if (!k) v = tin->newVertex(i, j, trdc);
- else if (!j) v = tin->newVertex(i, trdc, k);
- else v = tin->newVertex(trdc, k, j);
- mc->v = new ExtVertex(v);
- tin->V.appendHead(v);
- v->info = mc->source;
- }
-}
-
-void mc_grid::createVertices()
-{
- int i,j;
-
- for (i=0; iints[i] != NULL) ints[i] = m->ints[i];
- m->x = -1;
-}
-
-List *mc_grid::createCells()
-{
- int i,j,k=numrays+1;
- mc_ints *m;
- Node *n;
- List *ac = new List;
-
- for (i=0; idata);
- k = TMESH_TO_INT(floor(m->ic));
- ac->appendTail(new mc_cell(i,j,k,m,5));
- ac->appendTail(new mc_cell(i,j+1,k,m,1));
- ac->appendTail(new mc_cell(i+1,j,k,m,7));
- ac->appendTail(new mc_cell(i+1,j+1,k,m,3));
- }
- FOREACHNODE(xz[i+numrays*j], n)
- {
- m = ((mc_ints *)n->data);
- k = TMESH_TO_INT(floor(m->ic));
- ac->appendTail(new mc_cell(i, k, j, m, 10));
- ac->appendTail(new mc_cell(i,k,j+1,m,9));
- ac->appendTail(new mc_cell(i+1,k,j,m,11));
- ac->appendTail(new mc_cell(i+1,k,j+1,m,8));
- }
- FOREACHNODE(zy[i+numrays*j], n)
- {
- m = ((mc_ints *)n->data);
- k = TMESH_TO_INT(floor(m->ic));
- ac->appendTail(new mc_cell(k, j, i, m, 6));
- ac->appendTail(new mc_cell(k,j+1,i,m,2));
- ac->appendTail(new mc_cell(k,j,i+1,m,4));
- ac->appendTail(new mc_cell(k,j+1,i+1,m,0));
- }
- }
-
- ac->sort(mc_cell::compare);
- mc_cell *mcc, *last = NULL;
- //int x,y,z;
- //x=y=z=-1;
-
- last = (mc_cell *)ac->head()->data;
- for (n = ac->head()->next(); n != NULL; n = n->next())
- {
- mcc = (mc_cell *)n->data;
- if (mcc->x == last->x && mcc->y == last->y && mcc->z == last->z) last->merge(mcc);
- else last = mcc;
- }
-
- //FOREACHNODE((*ac), n)
- //{
- // mcc = (mc_cell *)n->data;
- // if (mcc->x == x && mcc->y == y && mcc->z == z)
- // {
- // if (last != NULL)
- // {
- // for (i=0; i<12; i++) if (mcc->ints[i] != NULL) last->ints[i] = mcc->ints[i];
- // }
- // x = mcc->x; mcc->x = -1;
- // }
- // else {x = mcc->x; last = mcc;}
- // y = mcc->y; z = mcc->z;
- //}
-
- n = ac->head();
- do
- {
- mcc = (mc_cell *)n->data;
- n = n->next();
- if (mcc->x == -1) { ac->removeCell((n != NULL) ? (n->prev()) : ac->tail()); delete (mcc); }
- } while (n != NULL);
-
- return ac;
-}
-
-void mc_grid::trackOuterHull()
-{
- int i, j, numcells = numrays + 1;
- mc_ints *m1, *m2;
- Edge *e0;
- Triangle *t0;
- List *ac;
-
- for (i = 0; inumels()>1)
- {
- m1 = ((mc_ints *)ac->head()->data);
- m2 = ((mc_ints *)ac->tail()->data);
- e0 = m1->v->v->e0; t0 = (e0 && e0->t1) ? (e0->t1) : ((e0 && e0->t2) ? (e0->t2) : (NULL)); if (t0 && !IS_VISITED(t0)) tin->selectConnectedComponent(t0);
- e0 = m2->v->v->e0; t0 = (e0 && e0->t1) ? (e0->t1) : ((e0 && e0->t2) ? (e0->t2) : (NULL)); if (t0 && !IS_VISITED(t0)) tin->selectConnectedComponent(t0);
- }
- ac = &xz[i + numrays*j];
- if (ac->numels()>1)
- {
- m1 = ((mc_ints *)ac->head()->data);
- m2 = ((mc_ints *)ac->tail()->data);
- e0 = m1->v->v->e0; t0 = (e0 && e0->t1) ? (e0->t1) : ((e0 && e0->t2) ? (e0->t2) : (NULL)); if (t0 && !IS_VISITED(t0)) tin->selectConnectedComponent(t0);
- e0 = m2->v->v->e0; t0 = (e0 && e0->t1) ? (e0->t1) : ((e0 && e0->t2) ? (e0->t2) : (NULL)); if (t0 && !IS_VISITED(t0)) tin->selectConnectedComponent(t0);
- }
- ac = &zy[i + numrays*j];
- if (ac->numels()>1)
- {
- m1 = ((mc_ints *)ac->head()->data);
- m2 = ((mc_ints *)ac->tail()->data);
- e0 = m1->v->v->e0; t0 = (e0 && e0->t1) ? (e0->t1) : ((e0 && e0->t2) ? (e0->t2) : (NULL)); if (t0 && !IS_VISITED(t0)) tin->selectConnectedComponent(t0);
- e0 = m2->v->v->e0; t0 = (e0 && e0->t1) ? (e0->t1) : ((e0 && e0->t2) ? (e0->t2) : (NULL)); if (t0 && !IS_VISITED(t0)) tin->selectConnectedComponent(t0);
- }
- }
- tin->invertSelection();
- tin->removeSelectedTriangles();
-}
-
-
-mc_grid::mc_grid(Basic_TMesh *_tin, int n)
-{
- numrays=n;
- xy=new List[n*n];
- xz=new List[n*n];
- zy=new List[n*n];
- tin = _tin;
-
- Point top;
- tin->getBoundingBox(origin, top);
- top-=origin;
- norm = MAX(top.x,MAX(top.y,top.z));
- norm /= (n+1);
- origin -= Point(norm/2, norm/2, norm/2);
- norm = MAX(top.x,MAX(top.y,top.z))/numrays;
-}
-
-
-void mc_grid::remesh(bool simplify_result)
-{
- Vertex *v;
- Triangle *t;
- Node *n;
- Basic_TMesh ntin;
- ntin.V.joinTailList(&(tin->V));
- ntin.E.joinTailList(&(tin->E));
- ntin.T.joinTailList(&(tin->T));
-
- FOREACHVVVERTEX((&(ntin.V)), v, n) v->setValue(((*v)-origin)/norm); // Shift and normalize
-
- TMesh::begin_progress();
- int i=0;
- FOREACHVTTRIANGLE((&ntin.T), t, n)
- {
- sample_triangle(t); t->info=NULL;
- if (!((i++)%1000)) TMesh::report_progress("%d %% done ",(i*50)/ntin.T.numels());
- }
-
- sort(); // Sort the intersections
- TMesh::report_progress("60 %% done ");
- purge(); // Remove unused intersections
- TMesh::report_progress("70 %% done ");
- createVertices(); // Create the new samples
- TMesh::report_progress("80 %% done ");
-
- // Compute the list of active cells
- List *activeCells = createCells();
- TMesh::report_progress("90 %% done ");
- mc_cell *c;
- while ((c=(mc_cell *)activeCells->popHead())!=NULL) c->polygonize(tin);
- TMesh::report_progress("95 %% done ");
-
-
- tin->removeVertices();
- int count = tin->duplicateNonManifoldVertices();
- TMesh::info("Duplicated %d non-manifold vertices.\n",count);
-
- trackOuterHull();
-
- if (simplify_result) FOREACHVVVERTEX((&ntin.V), v, n) v->setValue(((*v)*norm) + origin); // Shift and normalize
- FOREACHVVVERTEX((&tin->V), v, n) v->setValue(((*v)*norm) + origin); // Shift and normalize
-
- tin->safeCoordBackApproximation();
-
- if (simplify_result) simplify();
- TMesh::report_progress("99 %% done ");
-
- FOREACHVVVERTEX((&tin->V), v, n){
-
- v->info = NULL;
- }
- FOREACHVTTRIANGLE((&ntin.T), t, n) if (t->info) { delete ((Point *)t->info); t->info = NULL; }
- TMesh::end_progress();
-}
-
-
-
-
-
-
-
-
-
-
-
-bool mc_safeCollapse(Edge *e)
-{
- Point orig(e->v2);
- List *vt = e->v2->VT();
- Triangle *t;
- Node *n;
- Point nor;
-
- nor.setValue((Point *)e->v2->info);
- e->v2->setValue(e->v1);
- FOREACHVTTRIANGLE(vt, t, n) if (!t->hasEdge(e))
- {
- if (((*(t->v3())) + nor).exactOrientation(t->v1(), t->v2(), t->v3()) <= 0) break;
- if (t->nextVertex(e->v2)->info != e->v2->info) { if (((*(t->v3())) + (*(((Point *)t->nextVertex(e->v2)->info)))).exactOrientation(t->v1(), t->v2(), t->v3()) <= 0) break; }
- if (t->prevVertex(e->v2)->info != e->v2->info) { if (((*(t->v3())) + (*(((Point *)t->prevVertex(e->v2)->info)))).exactOrientation(t->v1(), t->v2(), t->v3()) <= 0) break; }
- }
- delete vt;
- e->v2->setValue(orig);
- orig.setValue(e->v1);
- return (n == NULL && e->collapse(orig));
-}
-
-//void mi_saveVRMLBorders(const char *filename, Basic_TMesh& tin)
-//{
-// FILE *fp;
-// int i;
-// if ((fp = fopen(filename, "w")) == NULL) { TMesh::warning("Couldn't save graph!\n"); return; }
-//
-// fprintf(fp, "#VRML V1.0 ascii\nSeparator {\nMaterial { diffuseColor 1 0 0 }\nCoordinate3 {\npoint [\n");
-// Node *n;
-// Edge *e;
-// Vertex *v;
-// i = 0;
-// FOREACHVVVERTEX((&tin.V), v, n)
-// {
-// v->printPoint(fp);
-// v->info = (void *)i;
-// i++;
-// }
-// fprintf(fp, "]\n}\n");
-//
-// fprintf(fp, "Material { diffuseColor 0.7 0.7 1 }\n");
-// fprintf(fp, "IndexedLineSet {\ncoordIndex [\n");
-// FOREACHVEEDGE((&tin.E), e, n) if (!IS_SHARPEDGE(e))
-// fprintf(fp, "%ld, %ld, -1,\n", (j_voidint)e->v1->info, (j_voidint)e->v2->info);
-// fprintf(fp, "]\n}\n");
-//
-// fprintf(fp, "Material { diffuseColor 1 0 0 }\n");
-// fprintf(fp, "IndexedLineSet {\ncoordIndex [\n");
-// FOREACHVEEDGE((&tin.E), e, n) if (IS_SHARPEDGE(e))
-// fprintf(fp, "%ld, %ld, -1,\n", (j_voidint)e->v1->info, (j_voidint)e->v2->info);
-// fprintf(fp, "]\n}\n");
-//
-// fprintf(fp, "Material { diffuseColor 0 1 0 }\nDrawStyle { pointSize 4 }\n");
-//
-// fprintf(fp, "Separator {\nCoordinate3 {\npoint [\n");
-// FOREACHVVVERTEX((&tin.V), v, n) if (IS_VISITED2(v)) v->printPoint(fp);
-// fprintf(fp, "]\n}\nPointSet {}\n}\n");
-//
-// fprintf(fp, "}\n");
-// fclose(fp);
-//}
-
-//bool mi_getCenterPosition(Triangle *t, Vertex **cp)
-//{
-// Vertex *v1 = t->v1(), *v2 = t->v2(), *v3 = t->v3();
-// Triangle *ot1 = (Triangle *)(((Point *)v1->info)->info);
-// Triangle *ot2 = (Triangle *)(((Point *)v2->info)->info);
-// Triangle *ot3 = (Triangle *)(((Point *)v3->info)->info);
-//
-// Vertex *cv = ot1->v1();
-// if (!ot2->hasVertex(cv) || !ot3->hasVertex(cv)) cv = ot1->v2();
-// if (!ot2->hasVertex(cv) || !ot3->hasVertex(cv)) cv = ot1->v3();
-// if (!ot2->hasVertex(cv) || !ot3->hasVertex(cv)) return false;
-//
-// *cp = cv;
-// return true;
-//}
-
-//Point mi_getCenterPosition(Edge *e)
-//{
-// Vertex *v1 = e->v1, *v2 = e->v2;
-// Triangle *ot1 = (Triangle *)(((Point *)v1->info)->info);
-// Triangle *ot2 = (Triangle *)(((Point *)v2->info)->info);
-// if (ot1->commonEdge(ot2) == NULL) return e->getMidPoint();
-//
-// Point nor1((Point *)v1->info), nor2((Point *)v2->info);
-// if (nor1*nor2 < 0 || nor1.getAngle(nor2)<0.01) return e->getMidPoint();
-//
-// Point nor3 = e->toVector()&nor1;
-// Point d;
-// d.x = (nor1*(*v1));
-// d.y = (nor2*(*v2));
-// d.z = (nor3*(*v2));
-// return d.linearSystem(nor1, nor2, nor3);
-//}
-
-void mc_grid::simplify()
-{
- Vertex *v;
- Triangle *t;
- Edge *e;
- Node *n;
- Point *nnor;
-
-
- // This turns info-pointed triangles to info-pointed normals.
- // In their turn, normals info-point their triangles.
- FOREACHVVVERTEX((&tin->V), v, n)
- {
- t = ((Triangle *)v->info);
- if (t->info != NULL) nnor = (Point *)t->info;
- else t->info = nnor = new Point(t->getVector());
- v->info = nnor;
- nnor->info = t;
- }
-
- FOREACHVEEDGE((&tin->E), e, n) if (e->isOnBoundary() || e->v1->info != e->v2->info) { MARK_VISIT(e); MARK_VISIT(e->v1); MARK_VISIT(e->v2); }
- FOREACHVTTRIANGLE((&tin->T), t, n) if (IS_VISITED(t->e1) && IS_VISITED(t->e2) && IS_VISITED(t->e3))
- { MARK_VISIT2(t->v1()); MARK_VISIT2(t->v2()); MARK_VISIT2(t->v3()); }
-
- List ies;
- FOREACHVEEDGE((&tin->E), e, n)
- if (!e->isOnBoundary() && e->v1->info == e->v2->info) ies.appendTail(e);
- else if (e->isOnBoundary()) { MARK_VISIT2(e->v1); MARK_VISIT2(e->v2); }
- Point nor;
- int c;
- do
- {
- c = 0;
- FOREACHVEEDGE((&ies), e, n) if (e->isLinked() && !e->isOnBoundary() && e->v1->info == e->v2->info)
- {
- if (IS_VISITED2(e->v1) && IS_VISITED2(e->v2)) continue;
- if (IS_VISITED(e->v1) && IS_VISITED(e->v2) && e->t1->oppositeVertex(e)->info == e->v1->info && e->t2->oppositeVertex(e)->info == e->v1->info) continue;
-
- if (IS_VISITED2(e->v2)) e->invert();
- else if (IS_VISITED(e->v2) && !IS_VISITED2(e->v1)) e->invert();
- if (mc_safeCollapse(e)) c++;
- }
-
- //FOREACHVEEDGE((&ies), e, n) if (e->isLinked() && !(IS_VISITED(e->v1) && IS_VISITED(e->v2)))
- //{
- // double a = e->delaunayMinAngle();
- // nor.setValue((Point *)e->v2->info);
- // if (e->swap()) { if ((e->t1->getVector()*nor<0) || (e->t2->getVector()*nor<0) || e->delaunayMinAngle() <= a) e->swap(true); }
- //}
- } while (c);
-
- tin->removeUnlinkedElements();
- tin->deselectTriangles();
- FOREACHVEEDGE((&tin->E), e, n) e->mask = 0;
- FOREACHVVVERTEX((&tin->V), v, n) v->mask = 0;
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/Algorithms/subdivision.cpp b/src/mesh_fix/src/Algorithms/subdivision.cpp
deleted file mode 100644
index 5f7198f73..000000000
--- a/src/mesh_fix/src/Algorithms/subdivision.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "tmesh.h"
-
-using namespace T_MESH;
-
-//////////////////// Loop's Subdivision Scheme //////////////////
-
-class loopSplit
-{
- public:
- Edge *e;
- Point p;
-
- loopSplit(Edge *_e, int md)
- {
- e = _e;
- if (e->t1 == NULL || e->t2 == NULL || md) p = ((*e->v1)+(*e->v2))/2.0;
- else
- {
- Vertex *ov1 = e->t1->oppositeVertex(e);
- Vertex *ov2 = e->t2->oppositeVertex(e);
- p = ((((*e->v1)+(*e->v2))*3.0)+((*ov1)+(*ov2)))/8.0;
- }
- }
-};
-
-double subsurfbeta_loop(int k)
-{
- double beta = (cos((2.0*M_PI)/((double)k))/4.0)+(3.0/8.0);
- return ((5.0/8.0)-(beta*beta))/((double)k);
-}
-
-
-void loopRelaxOriginal(Vertex *v)
-{
- Node *n;
- Edge *e;
- List *ve;
- Point np;
- int k;
- double beta;
-
- if (v->isOnBoundary())
- {
- ve = v->VE();
- np = (*(((Edge *)ve->head()->data)->oppositeVertex(v)));
- np += (*(((Edge *)ve->tail()->data)->oppositeVertex(v)));
- np = (((*v)*6.0)+np)/8.0;
- delete(ve);
- }
- else
- {
- ve = v->VE();
- k = ve->numels();
- beta = subsurfbeta_loop(k);
- FOREACHVEEDGE(ve, e, n) np += (*(e->oppositeVertex(v)));
- np = ((*v)*(1.0-k*beta))+(np*beta);
- delete(ve);
- }
-
- v->info = new Point(&np);
-}
-
-
-//// Performs one subdivision step using Loop's scheme ////
-//// If 'md' is set the method does not alter the geometry ////
-
-void Basic_TMesh::loopSubdivision(bool midpoint)
-{
- List nvs;
- Edge *e, *e1, *e2;
- Node *n;
- Vertex *v;
- Triangle *t;
- loopSplit *ls;
- int k, detected_sharp=0, is_selection=0;
- if (!midpoint) FOREACHVERTEX(v, n) loopRelaxOriginal(v);
-
- FOREACHTRIANGLE(t, n) if (IS_VISITED(t)) {is_selection=1; break;}
- if (is_selection) {FOREACHTRIANGLE(t, n) if (IS_VISITED(t)) {MARK_BIT(t->e1, 3); MARK_BIT(t->e2, 3); MARK_BIT(t->e3, 3);}}
- else FOREACHEDGE(e, n) MARK_BIT(e, 3);
-
- FOREACHEDGE(e, n) if (IS_BIT(e, 3))
- {
- MARK_BIT(e->v1, 3); MARK_BIT(e->v2, 3);
- if (!midpoint && IS_SHARPEDGE(e)) detected_sharp = 1;
- nvs.appendHead(new loopSplit(e, midpoint));
- }
-
- if (detected_sharp)
- TMesh::warning("loopSubdivision: Crease-preservation is not supported.\n");
-
- FOREACHNODE(nvs, n)
- {
- ls = ((loopSplit *)n->data);
- k = ls->e->isOnBoundary();
- v = splitEdge(ls->e, &(ls->p));
- e1 = (Edge *)E.head()->data;
- e2 = (Edge *)E.head()->next()->data;
- MARK_VISIT2(v); MARK_VISIT2(e1); if (!k) MARK_VISIT2(e2);
-
- if (ls->e->t2)
- {
- if (IS_VISITED(ls->e->t2)) {t=(Triangle *)T.head()->data; MARK_VISIT(t);}
- if (ls->e->t1 && IS_VISITED(ls->e->t1)) {t=(Triangle *)T.head()->next()->data; MARK_VISIT(t);}
- }
- else if (IS_VISITED(ls->e->t1)) {t=(Triangle *)T.head()->data; MARK_VISIT(t);}
-
- if (IS_SHARPEDGE(ls->e))
- {
- if (k) TAG_SHARPEDGE(e2);
- else TAG_SHARPEDGE((Edge *)E.head()->next()->next()->data);
- }
- }
-
- nvs.freeNodes();
-
- FOREACHEDGE(e, n)
- if (IS_VISITED2(e))
- {
- UNMARK_VISIT2(e);
- if ((IS_VISITED2(e->v1) && !IS_VISITED2(e->v2)) ||
- (!IS_VISITED2(e->v1) && IS_VISITED2(e->v2)))
- if (e->swap(1) && (!IS_VISITED2(e->v1) || !IS_VISITED2(e->v2))) e->swap(1);
- }
-
- FOREACHVERTEX(v, n) if (!IS_VISITED2(v) && !midpoint && IS_BIT(v, 3))
- {
- v->setValue((Point *)v->info);
- delete((Point *)v->info);
- v->info = NULL;
- }
- FOREACHVERTEX(v, n) {UNMARK_VISIT2(v); UNMARK_BIT(v, 3);}
-
- if (detected_sharp)
- TMesh::warning("loopSubdivision: Tagged sharp edges have been smoothed.\n");
-
- FOREACHEDGE(e, n) UNMARK_BIT(e, 3);
-}
diff --git a/src/mesh_fix/src/Kernel/coordinates.cpp b/src/mesh_fix/src/Kernel/coordinates.cpp
deleted file mode 100644
index 6c5ffd796..000000000
--- a/src/mesh_fix/src/Kernel/coordinates.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "coordinates.h"
-#include
-#include
-
-
-namespace T_MESH
-{
-#ifndef NAN
-#define NAN std::numeric_limits::quiet_NaN()
-#endif
-
-#ifdef USE_HYBRID_KERNEL
-
-// Default behaviour = FILTERED KERNEL
-bool PM_Rational::use_rationals = false;
-bool PM_Rational::use_filtering = true;
-
-void PM_Rational::switchToDouble()
-{
- if (_whv)
- {
- EXACT_NT * ov = (EXACT_NT *)_val;
- double d = (double)((EXACT_NT_DENOMINATOR(ov) != 0) ? (EXACT_NT_TO_DOUBLE((*ov))) : (NAN));
- _val = d2int64t(d);
- delete ov;
- _whv = false;
- }
-}
-
-void PM_Rational::switchToRational()
-{
- if (!_whv)
- {
- double od = int64t2d(_val);
- if (od == NAN) _val = (int64_t)new EXACT_NT(0, 0);
- else _val = (int64_t)new EXACT_NT(od);
- _whv = true;
- }
-}
-
- void PM_Rational::operator+=(const PM_Rational& a)
-{
- if (use_rationals) { switchToRational(); getVal() += a.toRational(); }
- else { switchToDouble(); getDVal() += a.toDouble(); }
-}
-
- void PM_Rational::operator-=(const PM_Rational& a)
-{
- if (use_rationals) { switchToRational(); getVal() -= a.toRational(); }
- else { switchToDouble(); getDVal() -= a.toDouble(); }
-}
-
- void PM_Rational::operator*=(const PM_Rational& a)
-{
- if (use_rationals) { switchToRational(); getVal() *= a.toRational(); }
- else { switchToDouble(); getDVal() *= a.toDouble(); }
-}
-
- void PM_Rational::operator/=(const PM_Rational& a)
-{
- if (use_rationals) { switchToRational(); getVal() /= a.toRational(); }
- else { switchToDouble(); getDVal() /= a.toDouble(); }
-}
-
- PM_Rational PM_Rational::operator+(const PM_Rational& a) const
-{
- if (use_rationals) return PM_Rational(toRational() + a.toRational());
- else return PM_Rational(toDouble() + a.toDouble());
-}
-
- PM_Rational PM_Rational::operator-(const PM_Rational& a) const
-{
- if (use_rationals) return PM_Rational(toRational() - a.toRational());
- else return PM_Rational(toDouble() - a.toDouble());
-}
-
- PM_Rational PM_Rational::operator*(const PM_Rational& a) const
-{
- if (use_rationals) return PM_Rational(toRational() * a.toRational());
- else return PM_Rational(toDouble() * a.toDouble());
-}
-
- PM_Rational PM_Rational::operator/(const PM_Rational& a) const
-{
- if (use_rationals) return PM_Rational(toRational() / a.toRational());
- else return PM_Rational(toDouble() / a.toDouble());
-}
-
- bool PM_Rational::operator==(const PM_Rational& a) const
-{
- if (_whv || a._whv /*use_rationals*/) return (toRational() == a.toRational());
- else return (toDouble() == a.toDouble());
- }
-
- bool PM_Rational::operator!=(const PM_Rational& a) const
-{
- if (_whv || a._whv /*use_rationals*/) return (toRational() != a.toRational());
- else return (toDouble() != a.toDouble());
-}
-
- PM_Rational& PM_Rational::operator=(const PM_Rational& a)
- {
- if (_whv) delete ((EXACT_NT *)_val);
- _whv = a._whv; _val = (_whv) ? ((int64_t)new EXACT_NT(a.getVal())) : (a._val);
- return *this;
- }
-
- void PM_Rational::setFromRational(const EXACT_NT& a)
- {
- if (_whv) delete ((EXACT_NT *)_val);
- _whv = 1; _val = (int64_t)new EXACT_NT(a);
- }
-
- bool PM_Rational::operator<(const PM_Rational& a) const
- {
- if (_whv || a._whv) return (toRational() < a.toRational());
- else return (toDouble() < a.toDouble());
- }
-
-bool PM_Rational::operator>(const PM_Rational& a) const
-{
- if (_whv || a._whv) return (toRational() > a.toRational());
- else return (toDouble() > a.toDouble());
-}
-
-PM_Rational operator-(const PM_Rational& a) // This might be probably changed... do not understand why to switch..
-{
- if (PM_Rational::isUsingRationals()) return PM_Rational(-(a.toRational()));
- else return PM_Rational(-(a.toDouble()));
-}
-
-PM_Rational ceil(const PM_Rational& a)
-{
- if (PM_Rational::isUsingRationals())
- {
- mpz_t n, d, f;
- mpz_init(n); mpz_init(d); mpz_init(f);
-#ifdef USE_CGAL_LAZYNT
- mpz_set(n, a.toRational().exact().numerator().mpz());
- mpz_set(d, a.toRational().exact().denominator().mpz());
- mpz_cdiv_q(f, n, d);
- mpz_clear(n); mpz_clear(d);
- return PM_Rational(EXACT_NT(CGAL::Gmpz(f)));
-#else
- mpz_set(n, a.toRational().get_num_mpz_t());
- mpz_set(d, a.toRational().get_den_mpz_t());
- mpz_cdiv_q(f, n, d);
- mpz_clear(n); mpz_clear(d);
- return PM_Rational(mpq_class(mpz_class(f)));
-#endif
- }
- else
- return PM_Rational(::ceil(a.toDouble()));
-}
-
-PM_Rational floor(const PM_Rational& a)
-{
- if (PM_Rational::isUsingRationals())
- {
- mpz_t n, d, f;
- mpz_init(n); mpz_init(d); mpz_init(f);
-#ifdef USE_CGAL_LAZYNT
- mpz_set(n, a.toRational().exact().numerator().mpz());
- mpz_set(d, a.toRational().exact().denominator().mpz());
- mpz_fdiv_q(f, n, d);
- mpz_clear(n); mpz_clear(d);
- return PM_Rational(EXACT_NT(CGAL::Gmpz(f)));
-#else
- mpz_set(n, a.toRational().get_num_mpz_t());
- mpz_set(d, a.toRational().get_den_mpz_t());
- mpz_fdiv_q(f, n, d);
- mpz_clear(n); mpz_clear(d);
- return PM_Rational(mpq_class(mpz_class(f)));
-#endif
- } else
- return PM_Rational(::floor(a.toDouble()));
-}
-
-PM_Rational round(const PM_Rational& a)
-{
- if (PM_Rational::isUsingRationals())
- {
- mpz_t n, d, f, c;
- mpz_init(n); mpz_init(d); mpz_init(f); mpz_init(c);
-#ifdef USE_CGAL_LAZYNT
- mpz_set(n, a.toRational().exact().numerator().mpz());
- mpz_set(d, a.toRational().exact().denominator().mpz());
- mpz_fdiv_q(f, n, d);
- mpz_cdiv_q(c, n, d);
- mpz_clear(n); mpz_clear(d);
- PM_Rational fr = PM_Rational(EXACT_NT(CGAL::Gmpz(f)));
- PM_Rational cr = PM_Rational(EXACT_NT(CGAL::Gmpz(c)));
- mpz_clear(f); mpz_clear(c);
- return ((a - fr) < (cr - a)) ? (fr) : (cr);
-#else
- mpz_set(n, a.toRational().get_num_mpz_t());
- mpz_set(d, a.toRational().get_den_mpz_t());
- mpz_fdiv_q(f, n, d);
- mpz_cdiv_q(c, n, d);
- mpz_clear(n); mpz_clear(d);
- PM_Rational fr = PM_Rational(mpq_class(mpz_class(f)));
- PM_Rational cr = PM_Rational(mpq_class(mpz_class(c)));
- mpz_clear(f); mpz_clear(c);
- return ((a - fr) < (cr - a)) ? (fr) : (cr);
-#endif
- } else
- return PM_Rational(::round(a.toDouble()));
-}
-
-#endif
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/Kernel/graph.cpp b/src/mesh_fix/src/Kernel/graph.cpp
deleted file mode 100644
index d8fc5b084..000000000
--- a/src/mesh_fix/src/Kernel/graph.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "graph.h"
-
-namespace T_MESH
-{
-
-graphEdge *graphNode::getEdge(graphNode *gn)
-{
- graphEdge *ge;
- Node *n = edges.head();
- while (n!=NULL)
- if ((ge=((graphEdge *)n->data))->oppositeNode(this)==gn) return ge;
- else n=n->next();
- return NULL;
-}
-
-graphEdge::graphEdge(graphNode *a, graphNode *b)
-{
- n1=a; n2=b;
- n1->edges.appendHead(this);
- n2->edges.appendHead(this);
-}
-
-
-graphEdge *Graph::createEdge(graphNode *n1, graphNode *n2)
-{
- Node *n;
- FOREACHNODE(n1->edges, n)
- if (((graphEdge *)n->data)->hasNode(n2))
- return (graphEdge *)n->data;
-
- edges.appendHead(new graphEdge(n1, n2));
- return (graphEdge *)edges.head()->data;
-}
-
-
-void graphEdge::collapse()
-{
- Node *n;
- graphEdge *e;
- graphNode *nx;
-
- while ((e = (graphEdge *)n2->edges.popHead()) != NULL)
- if (e != this)
- {
- ((e->n1 == n2)?(e->n1):(e->n2)) = n1;
- n1->edges.appendHead(e);
- }
-
- FOREACHNODE(n1->edges, n)
- {
- e = (graphEdge *)n->data;
- if (!e->isUnlinked()) e->oppositeNode(n1)->mask = 0;
- }
-
- n2->mask = 1;
- FOREACHNODE(n1->edges, n)
- {
- e = (graphEdge *)n->data;
- if (e != this)
- {
- nx = e->oppositeNode(n1);
- if (nx->mask) {nx->edges.removeNode(e); e->makeUnlinked();}
- nx->mask = 1;
- }
- }
-
- n = n1->edges.head();
- while (n != NULL)
- {
- e = (graphEdge *)n->data;
- n = n->next();
- if (e->isUnlinked()) n1->edges.removeCell((n!=NULL)?(n->prev()):n1->edges.tail());
- }
-
- FOREACHNODE(n1->edges, n)
- ((graphEdge *)n->data)->oppositeNode(n1)->mask = 0;
-
- n1->edges.removeNode(this);
-
- makeUnlinked();
-}
-
-
-Graph::~Graph()
-{
- graphNode *gn;
- graphEdge *ge;
- while ((gn=(graphNode *)nodes.popHead())!=NULL) delete gn;
- while ((ge=(graphEdge *)edges.popHead())!=NULL) delete ge;
-}
-
-void Graph::deleteUnlinkedElements()
-{
- Node *n;
- graphNode *gn;
- graphEdge *ge;
-
- n = nodes.head();
- while (n != NULL)
- {
- gn = (graphNode *)n->data;
- n = n->next();
- if (gn->isIsolated())
- {
- nodes.removeCell((n!=NULL)?(n->prev()):nodes.tail());
- delete(gn);
- }
- }
-
- n = edges.head();
- while (n != NULL)
- {
- ge = (graphEdge *)n->data;
- n = n->next();
- if (ge->isUnlinked())
- {
- edges.removeCell((n!=NULL)?(n->prev()):edges.tail());
- delete(ge);
- }
- }
-}
-
-void Graph::unlinkEdge(graphEdge *e)
-{
- e->n1->edges.removeNode(e);
- e->n2->edges.removeNode(e);
- e->makeUnlinked();
-}
-
-void Graph::destroyEdge(graphEdge *e)
-{
- unlinkEdge(e);
- edges.removeNode(e);
- delete e;
-}
-
-graphNode *Graph::unlinkNode(graphNode *a)
-{
- graphEdge *e;
- while ((e = (graphEdge *)a->edges.popHead())!=NULL) unlinkEdge(e);
- return a;
-}
-
-void graphEdge::invert()
-{
- graphNode *tmp = n1;
- n1 = n2;
- n2 = tmp;
-}
-
-bool Graph::isConnected()
-{
- if (nodes.numels() < 2) return true;
-
- unsigned char *nmask = new unsigned char[nodes.numels()];
- Node *n;
- graphNode *p, *q;
- int i;
-
- for (i=0, n=nodes.head(); n!=NULL; n=n->next(), i++)
- {
- p = (graphNode *)n->data;
- nmask[i]=p->mask;
- p->mask=0;
- }
-
- p = (graphNode *)nodes.head()->data;
- List todo(p); p->mask = 1;
- while ((p = (graphNode *)todo.popHead())!=NULL)
- {
- for (n=p->edges.head(); n!=NULL; n=n->next())
- {
- q = ((graphEdge *)n->data)->oppositeNode(p);
- if (q->mask==0) {todo.appendTail(q); q->mask=1;}
- }
- }
-
- bool is_connected = true;
- for (i=0, n=nodes.head(); n!=NULL; n=n->next(), i++)
- {
- p = (graphNode *)n->data;
- if (p->mask==0) is_connected=false;
- p->mask = nmask[i];
- }
-
- return is_connected;
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/Kernel/heap.cpp b/src/mesh_fix/src/Kernel/heap.cpp
deleted file mode 100644
index 59fc5a418..000000000
--- a/src/mesh_fix/src/Kernel/heap.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include
-#include
-#include "heap.h"
-
-namespace T_MESH
-{
-
-abstractHeap::abstractHeap(int size)
-{
- heap = new Data *[size+1];
- numels = 0;
- maxels = size;
- positions = NULL;
-}
-
-abstractHeap::~abstractHeap()
-{
- delete(heap);
-}
-
-int abstractHeap::upheap(int k)
-{
- if (k < 2) return k;
-
- Data *t = heap[k];
- int fk = (k%2)?((k-1)/2):(k/2);
- Data *f = heap[fk];
-
- if (compare(t, f) <= 0)
- {
- heap[k] = f;
- heap[fk] = t;
- if (positions != NULL)
- {
- positions[to_int(f)] = k;
- positions[to_int(t)] = fk;
- }
- return upheap(fk);
- }
- return k;
-}
-
-int abstractHeap::downheap(int k)
-{
- int j;
-
- Data *t = heap[k];
- int fk = (numels%2)?((numels-1)/2):(numels/2);
- if (k > fk) return k;
-
- j = k+k;
- if (j < numels && compare(heap[j], heap[j+1]) >= 0) j++;
- Data *f = heap[j];
- if (compare(t, f) >= 0)
- {
- heap[k] = f;
- heap[j] = t;
- if (positions != NULL)
- {
- positions[to_int(f)] = k;
- positions[to_int(t)] = j;
- }
- return downheap(j);
- }
-
- return k;
-}
-
-int abstractHeap::insert(Data *t)
-{
- if (numels == maxels) return -1;
-
- heap[++numels] = t;
- if (positions != NULL) positions[to_int(t)] = numels;
- return upheap(numels);
-}
-
-Data *abstractHeap::removeHead()
-{
- Data *t = heap[1];
- if (positions != NULL) positions[to_int(t)] = 0;
- heap[1] = heap[numels--];
- if (numels)
- {
- if (positions != NULL) positions[to_int(heap[1])] = 1;
- downheap(1);
- }
-
- return t;
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/Kernel/jqsort.cpp b/src/mesh_fix/src/Kernel/jqsort.cpp
deleted file mode 100644
index 554cbc9e5..000000000
--- a/src/mesh_fix/src/Kernel/jqsort.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#define USE_STD_SORT
-
-#ifdef USE_STD_SORT
-#include
-#include
-#endif
-
-#include "basics.h"
-
-namespace T_MESH
-{
-
-#ifndef USE_STD_SORT
-inline void jswap(void *v[], int i, int j)
-{
- void *temp = v[i];
- v[i] = v[j];
- v[j] = temp;
-}
-
-void jqsort_prv(void *v[], int left, int right, int (*comp)(const void *, const void *))
-{
- register int i, last;
-
- if (left >= right) return;
- jswap(v, left, (left+right)/2);
- last = left;
- for (i = left+1; i <= right; i++)
- if ((*comp)(v[i], v[left]) < 0) jswap(v, ++last, i);
- jswap(v, left, last);
- jqsort_prv(v, left, last-1, comp);
- jqsort_prv(v, last+1, right, comp);
-}
-
-void jqsort(void *v[], int numels, int(*comp)(const void *, const void *))
-{
- jqsort_prv(v, 0, numels-1, comp);
-}
-#else
-
-class compobj
-{
- int(*comp)(const Data *, const Data *);
-
-public:
- compobj(int(*c)(const Data *, const Data *)) { comp = c; }
-
- bool operator()(Data *a, Data *b) { return (comp(a, b) < 0); }
-};
-
-void jqsort(Data *v[], int numels, int(*comp)(const Data *, const Data *))
-{
- compobj a(comp);
- std::sort(v, v + numels, a);
-}
-#endif
-
-} //namespace T_MESH
-
diff --git a/src/mesh_fix/src/Kernel/list.cpp b/src/mesh_fix/src/Kernel/list.cpp
deleted file mode 100644
index d5a0e3764..000000000
--- a/src/mesh_fix/src/Kernel/list.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include
-#include
-#include "list.h"
-#include "jqsort.h"
-
-namespace T_MESH
-{
-
-// Create a new node containing 'd', and link it to //
-// 'p' on the left (prev) and to 'n' on the right (next). //
-
-Node::Node(const Node *p, const Data *d, const Node *n)
-{
- data=(Data *)d;
- if ((n_prev=(Node *)p) != NULL) n_prev->n_next = this;
- if ((n_next=(Node *)n) != NULL) n_next->n_prev = this;
-}
-
-
-// Destroy and unlink the node
-
-Node::~Node()
-{
- if (n_prev != NULL) n_prev->n_next = n_next;
- if (n_next != NULL) n_next->n_prev = n_prev;
-}
-
-
-/////////// Constructor from list ///////////////////
-
-List::List(const Data **d, int n)
-{
- l_head = l_tail = NULL; l_numels = 0;
- for (int i=0; inext());
- if (b == l_tail) l_tail = nn;
- l_numels++;
-}
-
-////////////////// Appends a list //////////////////
-
-void List::appendList(const List *l)
-{
- Node *n = l->l_tail;
-
- while (n != NULL)
- {
- appendHead(n->data);
- n=n->prev();
- }
-}
-
-////////////////// Joins a list to the l_tail //////////////////
-
-void List::joinTailList(List *l)
-{
- if (l->l_numels == 0) return;
- if (l_tail != NULL)
- {
- l_tail->n_next = l->l_head; l->l_head->n_prev = l_tail; l_tail = l->l_tail;
- l_numels += l->l_numels;
- }
- else
- {
- l_head = l->l_head; l_tail = l->l_tail; l_numels = l->l_numels;
- }
- l->l_head = l->l_tail = NULL; l->l_numels = 0;
-}
-
-//// Moves node 'n' from this list to the end of 'l'. \n O(1).
-void List::moveNodeTo(Node *n, List *l)
-{
- Node *pn = n->n_prev, *nn = n->n_next;
- n->n_prev = l->l_tail; n->n_next = NULL;
-
- if (l->l_numels) l->l_tail->n_next = n; else l->l_head = n;
- l->l_tail = n;
- l->l_numels++;
-
- l_numels--;
- if (pn != NULL) pn->n_next = nn; else l_head = nn;
- if (nn != NULL) nn->n_prev = pn; else l_tail = pn;
-}
-
-//// Removes the first node and returns the corresponding data /////
-
-Data *List::popHead()
-{
- Data *data = (l_head != NULL)?(l_head->data):(NULL);
- if (l_head != NULL) removeCell(l_head);
- return data;
-}
-
-//// Removes the last node and returns the corresponding data /////
-
-Data *List::popTail()
-{
- Data *data = (l_tail != NULL)?(l_tail->data):(NULL);
- if (l_tail != NULL) removeCell(l_tail);
- return data;
-}
-
-//////////////////// Removes an element //////////////////
-
-int List::removeNode(const Data *d)
-{
- Node *tmp = l_head;
- int i=1;
-
- while (tmp != NULL)
- if (tmp->data == d)
- {
- removeCell(tmp);
- return i;
- }
- else {tmp=tmp->n_next; i++;}
-
- return 0;
-}
-
-
-//////////////////// Removes an element //////////////////
-
-int List::removeNode(int i)
-{
- Node *tmp = l_head;
-
- while (tmp!=NULL && i--) tmp=tmp->n_next;
- if (tmp==NULL) return 0;
-
- removeCell(tmp);
- return 1;
-}
-
-
-//////////////////// Gets a node //////////////////
-
-Node *List::getNode(int i) const
-{
- Node *tmp = l_head;
-
- while (tmp!=NULL && i--) tmp=tmp->n_next;
- return tmp;
-}
-
-
-//////////////////// Removes a node //////////////////
-
-void List::removeCell(Node *n)
-{
- if (n==l_head) l_head = n->n_next;
- if (n==l_tail) l_tail = n->n_prev;
- delete(n);
- l_numels--;
-}
-
-
-////////////////// Garbage collection //////////////
-
-void List::freeCell(Node *n)
-{
- delete(n->data);
- removeCell(n);
-}
-
-void List::freeNode(Data *d)
-{
- delete(d);
- removeNode(d);
-}
-
-//////////////////// Belonging check /////////////////
-
-Node *List::containsNode(const Data *d) const
-{
- Node *tmp = l_head;
-
- while (tmp != NULL)
- if (tmp->data == d) return tmp;
- else tmp=tmp->n_next;
-
- return NULL;
-}
-
-//////////////////// Replaces a node /////////////////
-
-Node *List::replaceNode(const Data *od, const Data *nd)
-{
- Node *tmp = containsNode(od);
- if (tmp != NULL) { tmp->data = (Data *)nd; return tmp;}
- appendTail(nd);
- return l_tail;
-}
-
-//////////////////////// Garbage collector /////////////////////
-
-void List::freeNodes()
-{
- while (l_head != NULL) freeCell(l_head);
-}
-
-//////////////////////// Garbage collector /////////////////////
-
-void List::removeNodes()
-{
- while (l_head != NULL) removeCell(l_head);
-}
-
-
-///// Conversion to array ///////
-
-Data **List::toArray() const
-{
- Node *n = l_head;
- int i;
- Data **array;
-
- if (l_numels == 0) return NULL;
- array = (Data **)malloc(sizeof(Data *)*l_numels);
- if (array == NULL) return NULL;
- for (i=0; in_next) array[i] = n->data;
-
- return array;
-}
-
-///// Sorts the list /////////
-
-int List::sort(int (*comp)(const Data *, const Data *))
-{
- Data **array;
- int ne = l_numels-1;
-
- if (l_numels < 2) return 0;
- if ((array = toArray()) == NULL) return 1;
-
- jqsort(array, l_numels, comp);
- removeNodes();
- for (; ne >= 0; ne--) appendHead(array[ne]);
- free(array);
-
- return 0;
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/Kernel/matrix.cpp b/src/mesh_fix/src/Kernel/matrix.cpp
deleted file mode 100644
index 0ff18e249..000000000
--- a/src/mesh_fix/src/Kernel/matrix.cpp
+++ /dev/null
@@ -1,794 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include
-#include "matrix.h"
-
-namespace T_MESH
-{
-
-#define FABS(a) (((a)<0)?(-(a)):((a)))
-
-//////////////////////////////////////////////////////////////////////////
-//
-// Generic 3x3 matrix
-//
-//////////////////////////////////////////////////////////////////////////
-
-// Plain constructor
-
-Matrix3x3::Matrix3x3(const double& a11, const double& a12, const double& a13,
- const double& a21, const double& a22, const double& a23,
- const double& a31, const double& a32, const double& a33)
-{
- M[0] = a11; M[1] = a12; M[2] = a13;
- M[3] = a21; M[4] = a22; M[5] = a23;
- M[6] = a31; M[7] = a32; M[8] = a33;
-}
-
-
-// Matrix T(v1,v2,v3)*(w1,w2,w3).
-
-Matrix3x3::Matrix3x3(const double& v1, const double& v2, const double& v3,
- const double& w1, const double& w2, const double& w3)
-{
- M[0] = v1*w1; M[1] = v1*w2; M[2] = v1*w3;
- M[3] = v2*w1; M[4] = v2*w2; M[5] = v2*w3;
- M[6] = v3*w1; M[7] = v3*w2; M[8] = v3*w3;
-}
-
-
-// Symmetric matrix T(x,y,z)*(x,y,z)
-
-Matrix3x3::Matrix3x3(const double& x, const double& y, const double& z)
-{
- M[0] = x*x; M[1] = x*y; M[2] = x*z;
- M[3] = M[1]; M[4] = y*y; M[5] = y*z;
- M[6] = M[2]; M[7] = M[5]; M[8] = z*z;
-}
-
-
-// Self-sum
-
-void Matrix3x3::operator+=(const Matrix3x3& s)
-{
- M[0] += s.M[0]; M[1] += s.M[1]; M[2] += s.M[2];
- M[3] += s.M[3]; M[4] += s.M[4]; M[5] += s.M[5];
- M[6] += s.M[6]; M[7] += s.M[7]; M[8] += s.M[8];
-}
-
-
-// Self-subtraction
-
-void Matrix3x3::operator-=(const Matrix3x3& s)
-{
- M[0] -= s.M[0]; M[1] -= s.M[1]; M[2] -= s.M[2];
- M[3] -= s.M[3]; M[4] -= s.M[4]; M[5] -= s.M[5];
- M[6] -= s.M[6]; M[7] -= s.M[7]; M[8] -= s.M[8];
-}
-
-
-// Self-multiplication
-
-void Matrix3x3::operator*=(const double& d)
-{
- M[0] *= d; M[1] *= d; M[2] *= d;
- M[3] *= d; M[4] *= d; M[5] *= d;
- M[6] *= d; M[7] *= d; M[8] *= d;
-}
-
-
-// Sum
-
-Matrix3x3 Matrix3x3::operator+(const Matrix3x3& s) const
-{
- return Matrix3x3(M[0]+s.M[0], M[1]+s.M[1], M[2]+s.M[2],
- M[3]+s.M[3], M[4]+s.M[4], M[5]+s.M[5],
- M[6]+s.M[6], M[7]+s.M[7], M[8]+s.M[8]);
-}
-
-
-// Scalar Multiplication
-
-Matrix3x3 Matrix3x3::operator*(const double& d) const
-{
- return Matrix3x3(M[0]*d, M[1]*d, M[2]*d,
- M[3]*d, M[4]*d, M[5]*d,
- M[6]*d, M[7]*d, M[8]*d);
-}
-
-
-// Matrix multiplication
-
-Matrix3x3 Matrix3x3::operator*(const Matrix3x3& q) const
-{
- return Matrix3x3(
- M[0]*q.M[0]+M[1]*q.M[3]+M[2]*q.M[6], M[0]*q.M[1]+M[1]*q.M[4]+M[2]*q.M[7], M[0]*q.M[2]+M[1]*q.M[5]+M[2]*q.M[8],
- M[3]*q.M[0]+M[4]*q.M[3]+M[5]*q.M[6], M[3]*q.M[1]+M[4]*q.M[4]+M[5]*q.M[7], M[3]*q.M[2]+M[4]*q.M[5]+M[5]*q.M[8],
- M[6]*q.M[0]+M[7]*q.M[3]+M[8]*q.M[6], M[6]*q.M[1]+M[7]*q.M[4]+M[8]*q.M[7], M[6]*q.M[2]+M[7]*q.M[5]+M[8]*q.M[8]
- );
-}
-
-
-// Matrix transpose
-
-Matrix3x3 Matrix3x3::operator~() const
-{
- return Matrix3x3(M[0],M[3],M[6],M[1],M[4],M[7],M[2],M[5],M[8]);
-}
-
-
-// Computes (x,y,z)*M*(x,y,z)
-
-double Matrix3x3::lrMultiply(const double& x, const double& y, const double& z) const
-{
- return (x*(x*M[0] + y*M[3] + z*M[6]) + y*(x*M[1] + y*M[4] + z*M[7]) + z*(x*M[2] + y*M[5] + z*M[8]));
-}
-
-
-// Computes v*M*w
-double Matrix3x3::lrMultiply(const double& v1, const double& v2, const double& v3,
- const double& w1, const double& w2, const double& w3) const
-{
- return (w1*(v1*M[0] + v2*M[3] + v3*M[6]) + w2*(v1*M[1] + v2*M[4] + v3*M[7]) + w3*(v1*M[2] + v2*M[5] + v3*M[8]));
-}
-
-Matrix3x3 Matrix3x3::transpose() const
-{
- return Matrix3x3(M[0], M[3], M[6],
- M[1], M[4], M[7],
- M[2], M[5], M[8]);
-}
-
-//////////////////////////////////////////////////////////////////////////
-//
-// Symmetric 3x3 matrix
-//
-//////////////////////////////////////////////////////////////////////////
-
-// Plain constructor
-
-SymMatrix3x3::SymMatrix3x3(const double&a11, const double&a12, const double&a22,
- const double&a13, const double&a23, const double&a33)
-{
- M[0] = a11; M[1] = a12; M[3] = a13;
- M[2] = a22; M[4] = a23;
- M[5] = a33;
-}
-
-
-// Symmetric matrix T(x,y,z)*(x,y,z)
-
-SymMatrix3x3::SymMatrix3x3(const double& x, const double& y, const double& z)
-{
- M[0] = x*x; M[1] = x*y; M[3] = x*z;
- M[2] = y*y; M[4] = y*z;
- M[5] = z*z;
-}
-
-
-// Constructor from generic matrix
-
-SymMatrix3x3::SymMatrix3x3(const Matrix3x3& q)
-{
- M[0] = q.M[0]; M[1] = q.M[1]; M[3] = q.M[2];
- M[2] = q.M[4]; M[4] = q.M[5];
- M[5] = q.M[8];
-}
-
-
-// Self-sum
-
-void SymMatrix3x3::operator+=(const SymMatrix3x3& s)
-{
- M[0] += s.M[0]; M[1] += s.M[1]; M[2] += s.M[2];
- M[3] += s.M[3]; M[4] += s.M[4]; M[5] += s.M[5];
-}
-
-
-// Self-subtraction
-
-void SymMatrix3x3::operator-=(const SymMatrix3x3& s)
-{
- M[0] -= s.M[0]; M[1] -= s.M[1]; M[2] -= s.M[2];
- M[3] -= s.M[3]; M[4] -= s.M[4]; M[5] -= s.M[5];
-}
-
-
-// Self-multiplication
-
-void SymMatrix3x3::operator*=(const double& d)
-{
- M[0] *= d; M[1] *= d; M[2] *= d;
- M[3] *= d; M[4] *= d; M[5] *= d;
-}
-
-
-// Sum
-
-SymMatrix3x3 SymMatrix3x3::operator+(const SymMatrix3x3& s) const
-{
- return SymMatrix3x3(M[0]+s.M[0], M[1]+s.M[1], M[2]+s.M[2],
- M[3]+s.M[3], M[4]+s.M[4], M[5]+s.M[5]);
-}
-
-
-// Multiplication
-
-SymMatrix3x3 SymMatrix3x3::operator*(const double& d) const
-{
- return SymMatrix3x3(M[0]*d, M[1]*d, M[2]*d, M[3]*d, M[4]*d, M[5]*d);
-}
-
-
-// Computes (x,y,z)*M*(x,y,z)
-
-double SymMatrix3x3::lrMultiply(const double& x, const double& y, const double& z) const
-{
- double a,b,c;
- a = x*M[0] + y*M[1] + z*M[3];
- b = x*M[1] + y*M[2] + z*M[4];
- c = x*M[3] + y*M[4] + z*M[5];
- return (x*a + y*b + z*c);
-}
-
-
-
-// Computes v*M*w
-double SymMatrix3x3::lrMultiply(const double& v1, const double& v2, const double& v3,
- const double& w1, const double& w2, const double& w3) const
-{
- return (w1*(v1*M[0] + v2*M[1] + v3*M[3]) + w2*(v1*M[1] + v2*M[2] + v3*M[4]) + w3*(v1*M[3] + v2*M[4] + v3*M[5]));
-}
-
-// Invert the matrix. If singular return FALSE
-
-bool SymMatrix3x3::invert()
-{
- double det, pos, neg, t, out[6];
-
- pos = neg = 0.0;
- t = M[0]*M[2]*M[5]; ((t >= 0.0)?(pos):(neg)) += t;
- t = M[1]*M[4]*M[3]; ((t >= 0.0)?(pos):(neg)) += t;
- t = M[3]*M[1]*M[4]; ((t >= 0.0)?(pos):(neg)) += t;
- t = -M[3]*M[2]*M[3]; ((t >= 0.0)?(pos):(neg)) += t;
- t = -M[1]*M[1]*M[5]; ((t >= 0.0)?(pos):(neg)) += t;
- t = -M[0]*M[4]*M[4]; ((t >= 0.0)?(pos):(neg)) += t;
- det = pos+neg;
-
- t = det/(pos-neg);
- if (FABS(t) >= 1.0e-15)
- {
- out[0] = (M[2] * M[5] - M[4] * M[4]) /det;
- out[1] = -(M[1] * M[5] - M[4] * M[3]) /det;
- out[2] = (M[0] * M[5] - M[3] * M[3]) /det;
- out[3] = (M[1] * M[4] - M[2] * M[3]) /det;
- out[4] = -(M[0] * M[4] - M[1] * M[3]) /det;
- out[5] = (M[0] * M[2] - M[1] * M[1]) /det;
- M[0] = out[0]; M[1] = out[1]; M[2] = out[2];
- M[3] = out[3]; M[4] = out[4]; M[5] = out[5];
- return 1;
- }
-
- return 0;
-}
-
-
-// Compute eigenvalues and eigenvectors of the matrix (JACOBI method).
-// The calling function is responsible of verifying that the matrix
-// is diagonalizable.
-//
-// This routine was inspired from a software to estimate curvature
-// tensors developed at INRIA. Visit the following link for details:
-// http://www-sop.inria.fr/geometrica/team/Pierre.Alliez/demos/curvature/
-//
-// This version has been slightly optimized.
-//
-
-void SymMatrix3x3::diagonalize(double *eigen_val, double *eigen_vec) const
-{
- static const double EPS = 0.00001;
- static const double cos_pi_4 = 0.70710678;
- static const int MAX_ITER = 100;
- double a_P[6], v_P[9];
- double *a = a_P, *v = v_P;
- double a_norm,a_normEPS,thr,thr_nn;
- int nb_iter = 0;
- int i,j,k,ij,jj,ik,l,m,lm,mq,lq,ll,mm,imv,im,iq,ilv,il;
- int index_P[3];
- int *index = index_P;
- double a_ij,a_lm,a_ll,a_mm,a_im,a_il,a_lm_2,v_ilv,v_imv,x;
- double sinx,sinx_2,cosx,cosx_2,sincos,delta;
-
- a[0] = M[0]; a[1] = M[1]; a[2] = M[2];
- a[3] = M[3]; a[4] = M[4]; a[5] = M[5];
- a--;
-
- // Step 2 : Init diagonalization matrix as the unit matrix
-
- for (ij=0, i=0; i<3; i++) for (j=0; j<3; j++) v[ij++] = (i==j)?(1.0):(0.0);
- v--;
-
- // Step 3 : compute the weight of the non diagonal terms
-
- a_norm = 0.0;
- for (i=1, ij=1; i<=3; i++) for (j=1; j<=i; j++, ij++) if( i!=j ) {a_ij = a[ij]; a_norm += a_ij*a_ij;}
-
- if( a_norm != 0.0 )
- {
- a_normEPS = a_norm*EPS;
- thr = a_norm ;
-
- // Step 4 : rotations
- while (thr > a_normEPS && nb_iter < MAX_ITER)
- {
- nb_iter++;
- thr_nn = thr / 6;
-
- for (l=1; l<3; l++)
- for (m=l+1; m<=3; m++)
- {
- // compute sinx and cosx
-
- lq = (l*l-l)/2; mq = (m*m-m)/2;
- lm = l+mq; a_lm = a[lm];
- a_lm_2 = a_lm*a_lm;
-
- if( a_lm_2 < thr_nn ) continue;
-
- ll = l+lq; mm = m+mq;
- a_ll = a[ll]; a_mm = a[mm];
- delta = a_ll - a_mm;
-
- if (delta==0.0) {sinx = -cos_pi_4; cosx = cos_pi_4;}
- else {x = -atan( (a_lm+a_lm) / delta )/2.0; sinx=sin(x); cosx=cos(x);}
-
- sinx_2 = sinx*sinx;
- cosx_2 = cosx*cosx;
- sincos = sinx*cosx;
-
- // rotate L and M columns
-
- ilv = 3*(l-1); imv = 3*(m-1);
-
- for( i=1; i<=3;i++ )
- {
- if( (i!=l) && (i!=m) )
- {
- iq = (i*i-i)/2;
- im = (i1.0e-12) {*L1 = *L2 = *L3 = a11; return;} // Evecs = (1,0,0), (0,1,0), (0,0,1)
-
- double l1, l2, l3; // Eigenvalues to be computed
-
- if (Q>=0) {double p=(b>0)?(pow(b/2, 1.0/3.0)):(0); l1=l2=((c2/3.0)+p); l3=((c2/3.0)-2.0*p);}
- else
- {
- double t = atan2(sqrt(-Q), -b/2.0)/3.0, r = pow(((b*b)/4.0)-Q, 1.0/6.0);
- double cos_t = cos(t), sin_t = sin(t);
- const double sq3 = sqrt(3.0);
- l1 = l2 = l3 = (c2/3.0);
- l1 += (2*r*cos_t);
- l2 -= r*(cos_t+sq3*sin_t);
- l3 -= r*(cos_t-sq3*sin_t);
- }
-
- if (l1<=l2 && l1<=l3) {*L1=l1; *L2=(l2=l2 && l1>=l3) {c0=u11; c1=u12; c2=u13; l=l1;}
- else if (l2>=l1 && l2>=l3) {c0=u12; c1=u22; c2=u23; l=l2;}
- else {c0=u13; c1=u23; c2=u33; l=l3;}
-
- l1 = sqrt(l); *x = c0/l1; *y = c1/l1; *z = c2/l1;
-
- return l;
-}
-
-
-// Computes the eigenvector corresp. to the maximum eigenvalue
-
-void SymMatrix3x3::getMaxEigenvector(double *x, double *y, double *z) const
-{
- SymMatrix3x3(-M[0], -M[1], -M[2], -M[3], -M[4], -M[5]).getMinEigenvector(x, y, z);
-}
-
-// Prints the matrix values
-
-void SymMatrix3x3::print(FILE *fp) const
-{
- fprintf(fp,"%e %e %e\n",M[0],M[1],M[3]);
- fprintf(fp,"%e %e %e\n",M[1],M[2],M[4]);
- fprintf(fp,"%e %e %e\n",M[3],M[4],M[5]);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//
-// Symmetric 4x4 matrix
-//
-//////////////////////////////////////////////////////////////////////////
-
-// Extend a 3x3 matrix
-
-SymMatrix4x4::SymMatrix4x4(const SymMatrix3x3& q)
-{
- a2 = q.M[0]; ab = q.M[1]; ac = q.M[3]; ad = 0;
- b2 = q.M[2]; bc = q.M[4]; bd = 0;
- c2 = q.M[5]; cd = 0; d2 = 1;
-}
-
-
-// Build a quadric
-
-SymMatrix4x4::SymMatrix4x4(const coord& a, const coord& b, const coord& c, const coord& d)
-{
- a2 = a*a; ab = a*b; ac = a*c; ad = a*d;
- b2 = b*b; bc = b*c; bd = b*d;
- c2 = c*c; cd = c*d; d2 = d*d;
-}
-
-// True iff equal
-
-bool SymMatrix4x4::operator==(const SymMatrix4x4& q)
-{
- return (
- a2 == q.a2 && ab == q.ab && ac == q.ac && ad == q.ad &&\
- b2 == q.b2 && bc == q.bc && bd == q.bd &&\
- c2 == q.c2 && cd == q.cd && d2 == q.d2);
-}
-
-// True iff different
-
-bool SymMatrix4x4::operator!=(const SymMatrix4x4& q)
-{
- return (
- a2 != q.a2 || ab != q.ab || ac != q.ac || ad != q.ad ||\
- b2 != q.b2 || bc != q.bc || bd != q.bd ||\
- c2 != q.c2 || cd != q.cd || d2 != q.d2);
-}
-
-// Sum the matrix 'q' to the current matrix
-
-void SymMatrix4x4::operator+=(const SymMatrix4x4& q)
-{
- a2 += q.a2; ab += q.ab; ac += q.ac; ad += q.ad;
- b2 += q.b2; bc += q.bc; bd += q.bd;
- c2 += q.c2; cd += q.cd; d2 += q.d2;
-}
-
-// Returns the sum of the matrix with another matrix 'q'
-
-SymMatrix4x4 SymMatrix4x4::operator+(const SymMatrix4x4& q) const
-{
- SymMatrix4x4 n;
-
- n.a2=a2+q.a2; n.ab=ab+q.ab; n.ac=ac+q.ac; n.ad=ad+q.ad;
- n.b2=b2+q.b2; n.bc=bc+q.bc; n.bd=bd+q.bd;
- n.c2=c2+q.c2; n.cd=cd+q.cd; n.d2=d2+q.d2;
-
- return n;
-}
-
-// Returns the product of the matrix with a scalar
-
-SymMatrix4x4 SymMatrix4x4::operator*(const coord& d) const
-{
- SymMatrix4x4 n;
-
- n.a2=a2*d; n.ab=ab*d; n.ac=ac*d; n.ad=ad*d;
- n.b2=b2*d; n.bc=bc*d; n.bd=bd*d;
- n.c2=c2*d; n.cd=cd*d; n.d2=d2*d;
-
- return n;
-}
-
-void SymMatrix4x4::add(const coord& a, const coord& b, const coord& c, const coord& d)
-{
- a2 += a*a; ab += a*b; ac += a*c; ad += a*d;
- b2 += b*b; bc += b*c; bd += b*d;
- c2 += c*c; cd += c*d; d2 += d*d;
-}
-
-
-// Computes (a,b,c,w)*M*(a,b,c,w)
-
-coord SymMatrix4x4::lrMultiply(const coord& x, const coord& y, const coord& z, const coord& w) const
-{
- coord a,b,c,d;
- a = x*a2 + y*ab + z*ac + w*ad;
- b = x*ab + y*b2 + z*bc + w*bd;
- c = x*ac + y*bc + z*c2 + w*cd;
- d = x*ad + y*bd + z*cd + w*d2;
- return (x*a + y*b + z*c + w*d);
-}
-
-// Computes (a,b,c) s.t. (a,b,c,1)*M*(a,b,c,1) is minimized
-// Returns FALSE if the minimizer is not unique
-
-bool SymMatrix4x4::getMinimizer(coord *a, coord *b, coord *c) const
-{
- coord det, pos, neg, t;
-
- pos = neg = 0.0;
- t = a2*b2*c2; ((t >= 0.0)?(pos):(neg)) += t;
- t = ab*bc*ac; ((t >= 0.0)?(pos):(neg)) += t;
- t = ac*ab*bc; ((t >= 0.0)?(pos):(neg)) += t;
- t = -ac*b2*ac; ((t >= 0.0)?(pos):(neg)) += t;
- t = -ab*ab*c2; ((t >= 0.0)?(pos):(neg)) += t;
- t = -a2*bc*bc; ((t >= 0.0)?(pos):(neg)) += t;
- det = pos+neg;
-
- if (pos == neg) return 0;
-
- t = det/(pos-neg);
- if (
-#ifdef USE_HYBRID_KERNEL
- (coord::isUsingRationals() && t!=0) ||
-#endif
- (FABS(t) >= 1.0e-15))
- {
- *a = -(ad*( (b2*c2 - bc*bc)) + bd*(-(ab*c2 - bc*ac)) + cd*( (ab*bc - b2*ac)))/det;
- *b = -(ad*(-(ab*c2 - ac*bc)) + bd*( (a2*c2 - ac*ac)) + cd*(-(a2*bc - ab*ac)))/det;
- *c = -(ad*( (ab*bc - ac*b2)) + bd*(-(a2*bc - ac*ab)) + cd*( (a2*b2 - ab*ab)))/det;
- return 1;
- }
-
- return 0;
-}
-
-
-// Invert a symmetric 4x4 matrix using L*D*L^T decomposition.
-// The calling function is responsible of verifying that the matrix
-// is positive definite.
-//
-
-bool SymMatrix4x4::invert()
-{
- if (a2 <= 0) return false;
-
- coord d00 = coord(1.0) / a2;
- coord L10 = ab;
- coord l10 = ab*d00;
- coord L20 = ac;
- coord l20 = ac*d00;
- coord L30 = ad;
- coord l30 = ad*d00;
- coord d11 = b2-(L10*l10);
-
- if (d11 <= 0) return false; else d11 = coord(1.0)/d11;
-
- coord L21 = (bc-(L10*l20));
- coord l21 = L21*d11;
- coord L31 = (bd-(L10*l30));
- coord l31 = L31*d11;
- coord d22 = c2-(L20*l20)-(L21*l21);
-
- if (d22 <= 0) return false; else d22 = coord(1.0) / d22;
-
- coord L32 = (cd-(L20*l30)-(L21*l31));
- coord l32 = L32*d22;
- coord d33 = d2-(L30*l30)-(L31*l31)-(L32*l32);
-
- if (d33 <= 0) return false; else d33 = coord(1.0) / d33;
-
- L20 = l10*l21-l20;
- L31 = l21*l32-l31;
- L30 = l32*l20-L31*l10-l30;
-
- a2 = d00+(-l10)*((-l10)*d11)+L20*(L20*d22)+L30*(L30*d33);
- ab = ((-l10)*d11)+L20*((-l21)*d22)+L30*(L31*d33);
- b2 = d11+(-l21)*((-l21)*d22)+L31*(L31*d33);
- ac = (L20*d22)+L30*((-l32)*d33);
- bc = ((-l21)*d22)+L31*((-l32)*d33);
- c2 = d22+(-l32)*((-l32)*d33);
- ad = (L30*d33);
- bd = (L31*d33);
- cd = ((-l32)*d33);
- d2 = d33;
-
- return true;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//
-// Generic 4x4 matrix
-//
-//////////////////////////////////////////////////////////////////////////
-
-Matrix4x4::Matrix4x4() {}
-
-Matrix4x4::Matrix4x4(const double& d)
-{
- matrix[0][0] = matrix[1][1] = matrix[2][2] = matrix[3][3] = d;
- matrix[1][0] = matrix[0][1] = matrix[1][2] = matrix[1][3] = 0;
- matrix[2][0] = matrix[2][1] = matrix[0][2] = matrix[2][3] = 0;
- matrix[3][0] = matrix[3][1] = matrix[3][2] = matrix[0][3] = 0;
-}
-
-Matrix4x4::Matrix4x4(const double& a11, const double& a12, const double& a13, const double& a14,
- const double& a21, const double& a22, const double& a23, const double& a24,
- const double& a31, const double& a32, const double& a33, const double& a34,
- const double& a41, const double& a42, const double& a43, const double& a44)
-{
- matrix[0][0] = a11; matrix[0][1] = a12; matrix[0][2] = a13; matrix[0][3] = a14;
- matrix[1][0] = a21; matrix[1][1] = a22; matrix[1][2] = a23; matrix[1][3] = a24;
- matrix[2][0] = a31; matrix[2][1] = a32; matrix[2][2] = a33; matrix[2][3] = a34;
- matrix[3][0] = a41; matrix[3][1] = a42; matrix[3][2] = a43; matrix[3][3] = a44;
-}
-
-void Matrix4x4::setRotation(const double& rx, const double& ry, const double& rz, const double& rw)
-{
- matrix[0][0] = rw*rw + rx*rx - ry*ry - rz*rz;
- matrix[0][1] = 2*rx*ry + 2*rw*rz;
- matrix[0][2] = 2*rx*rz - 2*rw*ry;
- matrix[0][3] = 0.0;
-
- matrix[1][0] = 2*rx*ry-2*rw*rz;
- matrix[1][1] = rw*rw - rx*rx + ry*ry - rz*rz;
- matrix[1][2] = 2*ry*rz + 2*rw*rx;
- matrix[1][3] = 0.0;
-
- matrix[2][0] = 2*rx*rz + 2*rw*ry;
- matrix[2][1] = 2*ry*rz - 2*rw*rx;
- matrix[2][2] = rw*rw - rx*rx - ry*ry + rz*rz;
- matrix[2][3] = 0.0;
-
- matrix[3][0] = 0.0;
- matrix[3][1] = 0.0;
- matrix[3][2] = 0.0;
- matrix[3][3] = rw*rw + rx*rx + ry*ry + rz*rz;
-}
-
-void Matrix4x4::setTranslation(const double& x, const double& y, const double& z)
-{
- matrix[0][0] = matrix[1][1] = matrix[2][2] = matrix[3][3] = 1;
- matrix[1][0] = matrix[0][1] = matrix[1][2] = 0;
- matrix[2][0] = matrix[2][1] = matrix[0][2] = 0;
- matrix[3][0] = matrix[3][1] = matrix[3][2] = 0;
- matrix[0][3] = x;
- matrix[1][3] = y;
- matrix[2][3] = z;
-}
-
-Matrix4x4 Matrix4x4::operator*(const Matrix4x4& q) const
-{
- int i, j;
- Matrix4x4 m;
-
- for (i=0; i<4; i++) for (j=0; j<4; j++)
- m.matrix[i][j] = matrix[i][0]*q.matrix[0][j] + matrix[i][1]*q.matrix[1][j] + matrix[i][2]*q.matrix[2][j] + matrix[i][3]*q.matrix[3][j];
-
- return m;
-}
-
-void Matrix4x4::transform(double *x, double *y, double *z)
-{
- double w, a = *x, b = *y, c = *z;
-
- *x = matrix[0][0]*a + matrix[0][1]*b + matrix[0][2]*c + matrix[0][3];
- *y = matrix[1][0]*a + matrix[1][1]*b + matrix[1][2]*c + matrix[1][3];
- *z = matrix[2][0]*a + matrix[2][1]*b + matrix[2][2]*c + matrix[2][3];
- w = matrix[3][0]*a + matrix[3][1]*b + matrix[3][2]*c + matrix[3][3];
-
- (*x) /= w; (*y) /= w; (*z) /= w;
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/Kernel/orientation.c b/src/mesh_fix/src/Kernel/orientation.c
deleted file mode 100644
index 97a0591d2..000000000
--- a/src/mesh_fix/src/Kernel/orientation.c
+++ /dev/null
@@ -1,700 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-// This code is inspired on ideas first published in the following paper:
-// Jonathan Richard Shewchuk. Adaptive Precision Floating-Point Arithmetic
-// and Fast Robust Geometric Predicates, Discrete & Computational Geometry
-// 18(3):305–363, October 1997.
-//
-
-#include
-
-#ifdef SPECIFY_FP_PRECISION
-#include
-#endif
-
-/*****************************************************************************/
-/* */
-/* This section contains private macros and functions. */
-/* These are not part of the public interface. */
-/* */
-/*****************************************************************************/
-
-#define FABS(a) (((a)>=0.0)?(a):(-(a)))
-#define FTST(a,b,x,y) _bvr=x-a; y=b-_bvr
-#define FTS(a,b,x,y) x=(double)(a+b); FTST(a,b,x,y)
-#define TST(a,b,x,y) _bvr=(double)(x-a); _avr=x-_bvr; _brn=b-_bvr; _arn=a-_avr; y=_arn+_brn
-#define TWS(a,b,x,y) x=(double)(a+b); TST(a,b,x,y)
-#define TDT(a,b,x,y) _bvr=(double)(a-x); _avr=x+_bvr; _brn=_bvr-b; _arn=a-_avr; y=_arn+_brn
-#define TWD(a,b,x,y) x=(double)(a-b); TDT(a,b,x,y)
-#define SPLT(a,ahi,alo) c=(double)(_spl*a); abig=(double)(c-a); ahi=c-abig; alo=a-ahi
-#define TPT(a,b,x,y) SPLT(a,ahi,alo); SPLT(b,bhi,blo); err1=x-(ahi*bhi); err2=err1-(alo*bhi); err3=err2-(ahi*blo); y=(alo*blo)-err3
-#define TWP(a,b,x,y) x=(double)(a*b); TPT(a,b,x,y)
-#define TPP(a,b,bhi,blo,x,y) x=(double)(a*b); SPLT(a,ahi,alo); err1=x-(ahi*bhi); err2=err1-(alo*bhi); err3=err2-(ahi*blo); y=(alo*blo)-err3
-#define TOD(a1,a0,b,x2,x1,x0) TWD(a0,b,_i,x0); TWS(a1,_i,x2,x1)
-#define TTD(a1,a0,b1,b0,x3,x2,x1,x0) TOD(a1,a0,b0,_j,_0,x0); TOD(_j,_0,b1,x3,x2,x1)
-#define TOP(a1,a0,b,x3,x2,x1,x0) SPLT(b,bhi,blo); TPP(a0,b,bhi,blo,_i,x0); TPP(a1,b,bhi,blo,_j,_0); TWS(_i,_0,_k,x1); FTS(_j,_k,x3,x2)
-
-double _spl, _eps, _reb, _ccwebA, _ccwebB, _ccwebC, _o3ebA, _o3ebB, _o3ebC;
-double _iccebA, _iccebB, _iccebC, _ispebA, _ispebB, _ispebC;
-
-int _fesze(int elen, double *e, int flen, double *f, double *h)
-{
- double Q, Qnew, hh, _bvr, _avr, _brn, _arn, enow, fnow;
- int eindex, findex, hindex;
-
- enow = e[0];
- fnow = f[0];
- eindex = findex = 0;
- if ((fnow > enow) == (fnow > -enow)) {
- Q = enow;
- enow = e[++eindex];
- } else {
- Q = fnow;
- fnow = f[++findex];
- }
- hindex = 0;
- if ((eindex < elen) && (findex < flen)) {
- if ((fnow > enow) == (fnow > -enow)) {
- FTS(enow, Q, Qnew, hh);
- enow = e[++eindex];
- } else {
- FTS(fnow, Q, Qnew, hh);
- fnow = f[++findex];
- }
- Q = Qnew;
- if (hh != 0.0) {
- h[hindex++] = hh;
- }
- while ((eindex < elen) && (findex < flen)) {
- if ((fnow > enow) == (fnow > -enow)) {
- TWS(Q, enow, Qnew, hh);
- enow = e[++eindex];
- } else {
- TWS(Q, fnow, Qnew, hh);
- fnow = f[++findex];
- }
- Q = Qnew;
- if (hh != 0.0) {
- h[hindex++] = hh;
- }
- }
- }
- while (eindex < elen) {
- TWS(Q, enow, Qnew, hh);
- enow = e[++eindex];
- Q = Qnew;
- if (hh != 0.0) {
- h[hindex++] = hh;
- }
- }
- while (findex < flen) {
- TWS(Q, fnow, Qnew, hh);
- fnow = f[++findex];
- Q = Qnew;
- if (hh != 0.0) {
- h[hindex++] = hh;
- }
- }
- if ((Q != 0.0) || (hindex == 0)) {
- h[hindex++] = Q;
- }
- return hindex;
-}
-
-int _seze(int elen, double *e, double b, double *h)
-{
- double Q, sum, hh, product1, product0, enow, _bvr, _avr, _brn, _arn, c;
- double abig, ahi, alo, bhi, blo, err1, err2, err3;
- int eindex, hindex;
-
- SPLT(b, bhi, blo);
- TPP(e[0], b, bhi, blo, Q, hh);
- hindex = 0;
- if (hh != 0) {
- h[hindex++] = hh;
- }
- for (eindex = 1; eindex < elen; eindex++) {
- enow = e[eindex];
- TPP(enow, b, bhi, blo, product1, product0);
- TWS(Q, product0, sum, hh);
- if (hh != 0) {
- h[hindex++] = hh;
- }
- FTS(product1, sum, Q, hh);
- if (hh != 0) {
- h[hindex++] = hh;
- }
- }
- if ((Q != 0.0) || (hindex == 0)) {
- h[hindex++] = Q;
- }
- return hindex;
-}
-
-double _estm(int elen, double *e)
-{
- int eindex;
- double Q = e[0];
- for (eindex = 1; eindex < elen; eindex++) Q += e[eindex];
- return Q;
-}
-
-
-double _adaptive2dorientation(double *pa, double *pb, double *pc, double detsum)
-{
- double acx, acy, bcx, bcy,acxtail, acytail, bcxtail, bcytail, detleft, detright;
- double detlefttail, detrighttail, det, errbound, B[5], C1[8], C2[12], D[16];
- double B3, u[5], u3, s1, t1, s0, t0, _bvr, _avr, _brn, _arn, c;
- double abig, ahi, alo, bhi, blo, err1, err2, err3, _i, _j, _0;
- int C1length, C2length, Dlength;
-
- acx = (double) (pa[0] - pc[0]);
- bcx = (double) (pb[0] - pc[0]);
- acy = (double) (pa[1] - pc[1]);
- bcy = (double) (pb[1] - pc[1]);
-
- TWP(acx, bcy, detleft, detlefttail);
- TWP(acy, bcx, detright, detrighttail);
-
- TTD(detleft, detlefttail, detright, detrighttail,
- B3, B[2], B[1], B[0]);
- B[3] = B3;
-
- det = _estm(4, B);
- errbound = _ccwebB * detsum;
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- TDT(pa[0], pc[0], acx, acxtail);
- TDT(pb[0], pc[0], bcx, bcxtail);
- TDT(pa[1], pc[1], acy, acytail);
- TDT(pb[1], pc[1], bcy, bcytail);
-
- if ((acxtail == 0.0) && (acytail == 0.0)
- && (bcxtail == 0.0) && (bcytail == 0.0)) {
- return det;
- }
-
- errbound = _ccwebC * detsum + _reb * FABS(det);
- det += (acx * bcytail + bcy * acxtail)
- - (acy * bcxtail + bcx * acytail);
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- TWP(acxtail, bcy, s1, s0);
- TWP(acytail, bcx, t1, t0);
- TTD(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
- u[3] = u3;
- C1length = _fesze(4, B, 4, u, C1);
-
- TWP(acx, bcytail, s1, s0);
- TWP(acy, bcxtail, t1, t0);
- TTD(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
- u[3] = u3;
- C2length = _fesze(C1length, C1, 4, u, C2);
-
- TWP(acxtail, bcytail, s1, s0);
- TWP(acytail, bcxtail, t1, t0);
- TTD(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
- u[3] = u3;
- Dlength = _fesze(C2length, C2, 4, u, D);
-
- return(D[Dlength - 1]);
-}
-
-double _adaptive3dorientation(double *pa, double *pb, double *pc, double *pd, double permanent)
-{
- double adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz, det, errbound;
- double bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
- double bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0, bc[4], ca[4], ab[4];
- double bc3, ca3, ab3, adet[8], bdet[8], cdet[8];
- double abdet[16], *finnow, *finother, *finswap, fin1[192], fin2[192];
- double adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail, adztail, bdztail, cdztail;
- double at_blarge, at_clarge, bt_clarge, bt_alarge, ct_alarge, ct_blarge;
- double at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
- double bdxt_cdy1, cdxt_bdy1, cdxt_ady1, adxt_cdy1, adxt_bdy1, bdxt_ady1;
- double bdxt_cdy0, cdxt_bdy0, cdxt_ady0, adxt_cdy0, adxt_bdy0, bdxt_ady0;
- double bdyt_cdx1, cdyt_bdx1, cdyt_adx1, adyt_cdx1, adyt_bdx1, bdyt_adx1;
- double bdyt_cdx0, cdyt_bdx0, cdyt_adx0, adyt_cdx0, adyt_bdx0, bdyt_adx0;
- double bct[8], cat[8], abt[8], bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
- double adxt_cdyt1, adxt_bdyt1, bdxt_adyt1, bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
- double adxt_cdyt0, adxt_bdyt0, bdxt_adyt0, u[4], v[12], w[16], u3, negate;
- double _bvr, _avr, _brn, _arn, c, abig, ahi, alo, bhi, blo;
- double err1, err2, err3, _i, _j, _k, _0;
- int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen, finlength;
- int vlength, wlength, alen, blen, clen, ablen, bctlen, catlen, abtlen;
-
- adx = (double) (pa[0] - pd[0]);
- bdx = (double) (pb[0] - pd[0]);
- cdx = (double) (pc[0] - pd[0]);
- ady = (double) (pa[1] - pd[1]);
- bdy = (double) (pb[1] - pd[1]);
- cdy = (double) (pc[1] - pd[1]);
- adz = (double) (pa[2] - pd[2]);
- bdz = (double) (pb[2] - pd[2]);
- cdz = (double) (pc[2] - pd[2]);
-
- TWP(bdx, cdy, bdxcdy1, bdxcdy0);
- TWP(cdx, bdy, cdxbdy1, cdxbdy0);
- TTD(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
- bc[3] = bc3;
- alen = _seze(4, bc, adz, adet);
-
- TWP(cdx, ady, cdxady1, cdxady0);
- TWP(adx, cdy, adxcdy1, adxcdy0);
- TTD(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
- ca[3] = ca3;
- blen = _seze(4, ca, bdz, bdet);
-
- TWP(adx, bdy, adxbdy1, adxbdy0);
- TWP(bdx, ady, bdxady1, bdxady0);
- TTD(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
- ab[3] = ab3;
- clen = _seze(4, ab, cdz, cdet);
-
- ablen = _fesze(alen, adet, blen, bdet, abdet);
- finlength = _fesze(ablen, abdet, clen, cdet, fin1);
-
- det = _estm(finlength, fin1);
- errbound = _o3ebB * permanent;
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- TDT(pa[0], pd[0], adx, adxtail);
- TDT(pb[0], pd[0], bdx, bdxtail);
- TDT(pc[0], pd[0], cdx, cdxtail);
- TDT(pa[1], pd[1], ady, adytail);
- TDT(pb[1], pd[1], bdy, bdytail);
- TDT(pc[1], pd[1], cdy, cdytail);
- TDT(pa[2], pd[2], adz, adztail);
- TDT(pb[2], pd[2], bdz, bdztail);
- TDT(pc[2], pd[2], cdz, cdztail);
-
- if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
- && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)
- && (adztail == 0.0) && (bdztail == 0.0) && (cdztail == 0.0)) {
- return det;
- }
-
- errbound = _o3ebC * permanent + _reb * FABS(det);
- det += (adz * ((bdx * cdytail + cdy * bdxtail)
- - (bdy * cdxtail + cdx * bdytail))
- + adztail * (bdx * cdy - bdy * cdx))
- + (bdz * ((cdx * adytail + ady * cdxtail)
- - (cdy * adxtail + adx * cdytail))
- + bdztail * (cdx * ady - cdy * adx))
- + (cdz * ((adx * bdytail + bdy * adxtail)
- - (ady * bdxtail + bdx * adytail))
- + cdztail * (adx * bdy - ady * bdx));
- if ((det >= errbound) || (-det >= errbound)) {
- return det;
- }
-
- finnow = fin1;
- finother = fin2;
-
- if (adxtail == 0.0) {
- if (adytail == 0.0) {
- at_b[0] = 0.0;
- at_blen = 1;
- at_c[0] = 0.0;
- at_clen = 1;
- } else {
- negate = -adytail;
- TWP(negate, bdx, at_blarge, at_b[0]);
- at_b[1] = at_blarge;
- at_blen = 2;
- TWP(adytail, cdx, at_clarge, at_c[0]);
- at_c[1] = at_clarge;
- at_clen = 2;
- }
- } else {
- if (adytail == 0.0) {
- TWP(adxtail, bdy, at_blarge, at_b[0]);
- at_b[1] = at_blarge;
- at_blen = 2;
- negate = -adxtail;
- TWP(negate, cdy, at_clarge, at_c[0]);
- at_c[1] = at_clarge;
- at_clen = 2;
- } else {
- TWP(adxtail, bdy, adxt_bdy1, adxt_bdy0);
- TWP(adytail, bdx, adyt_bdx1, adyt_bdx0);
- TTD(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
- at_blarge, at_b[2], at_b[1], at_b[0]);
- at_b[3] = at_blarge;
- at_blen = 4;
- TWP(adytail, cdx, adyt_cdx1, adyt_cdx0);
- TWP(adxtail, cdy, adxt_cdy1, adxt_cdy0);
- TTD(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
- at_clarge, at_c[2], at_c[1], at_c[0]);
- at_c[3] = at_clarge;
- at_clen = 4;
- }
- }
- if (bdxtail == 0.0) {
- if (bdytail == 0.0) {
- bt_c[0] = 0.0;
- bt_clen = 1;
- bt_a[0] = 0.0;
- bt_alen = 1;
- } else {
- negate = -bdytail;
- TWP(negate, cdx, bt_clarge, bt_c[0]);
- bt_c[1] = bt_clarge;
- bt_clen = 2;
- TWP(bdytail, adx, bt_alarge, bt_a[0]);
- bt_a[1] = bt_alarge;
- bt_alen = 2;
- }
- } else {
- if (bdytail == 0.0) {
- TWP(bdxtail, cdy, bt_clarge, bt_c[0]);
- bt_c[1] = bt_clarge;
- bt_clen = 2;
- negate = -bdxtail;
- TWP(negate, ady, bt_alarge, bt_a[0]);
- bt_a[1] = bt_alarge;
- bt_alen = 2;
- } else {
- TWP(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
- TWP(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
- TTD(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
- bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
- bt_c[3] = bt_clarge;
- bt_clen = 4;
- TWP(bdytail, adx, bdyt_adx1, bdyt_adx0);
- TWP(bdxtail, ady, bdxt_ady1, bdxt_ady0);
- TTD(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
- bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
- bt_a[3] = bt_alarge;
- bt_alen = 4;
- }
- }
- if (cdxtail == 0.0) {
- if (cdytail == 0.0) {
- ct_a[0] = 0.0;
- ct_alen = 1;
- ct_b[0] = 0.0;
- ct_blen = 1;
- } else {
- negate = -cdytail;
- TWP(negate, adx, ct_alarge, ct_a[0]);
- ct_a[1] = ct_alarge;
- ct_alen = 2;
- TWP(cdytail, bdx, ct_blarge, ct_b[0]);
- ct_b[1] = ct_blarge;
- ct_blen = 2;
- }
- } else {
- if (cdytail == 0.0) {
- TWP(cdxtail, ady, ct_alarge, ct_a[0]);
- ct_a[1] = ct_alarge;
- ct_alen = 2;
- negate = -cdxtail;
- TWP(negate, bdy, ct_blarge, ct_b[0]);
- ct_b[1] = ct_blarge;
- ct_blen = 2;
- } else {
- TWP(cdxtail, ady, cdxt_ady1, cdxt_ady0);
- TWP(cdytail, adx, cdyt_adx1, cdyt_adx0);
- TTD(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
- ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
- ct_a[3] = ct_alarge;
- ct_alen = 4;
- TWP(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
- TWP(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
- TTD(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
- ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
- ct_b[3] = ct_blarge;
- ct_blen = 4;
- }
- }
-
- bctlen = _fesze(bt_clen, bt_c, ct_blen, ct_b, bct);
- wlength = _seze(bctlen, bct, adz, w);
- finlength = _fesze(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
-
- catlen = _fesze(ct_alen, ct_a, at_clen, at_c, cat);
- wlength = _seze(catlen, cat, bdz, w);
- finlength = _fesze(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
-
- abtlen = _fesze(at_blen, at_b, bt_alen, bt_a, abt);
- wlength = _seze(abtlen, abt, cdz, w);
- finlength = _fesze(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
-
- if (adztail != 0.0) {
- vlength = _seze(4, bc, adztail, v);
- finlength = _fesze(finlength, finnow, vlength, v,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (bdztail != 0.0) {
- vlength = _seze(4, ca, bdztail, v);
- finlength = _fesze(finlength, finnow, vlength, v,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (cdztail != 0.0) {
- vlength = _seze(4, ab, cdztail, v);
- finlength = _fesze(finlength, finnow, vlength, v,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
-
- if (adxtail != 0.0) {
- if (bdytail != 0.0) {
- TWP(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
- TOP(adxt_bdyt1, adxt_bdyt0, cdz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (cdztail != 0.0) {
- TOP(adxt_bdyt1, adxt_bdyt0, cdztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- if (cdytail != 0.0) {
- negate = -adxtail;
- TWP(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
- TOP(adxt_cdyt1, adxt_cdyt0, bdz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (bdztail != 0.0) {
- TOP(adxt_cdyt1, adxt_cdyt0, bdztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- }
- if (bdxtail != 0.0) {
- if (cdytail != 0.0) {
- TWP(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
- TOP(bdxt_cdyt1, bdxt_cdyt0, adz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (adztail != 0.0) {
- TOP(bdxt_cdyt1, bdxt_cdyt0, adztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- if (adytail != 0.0) {
- negate = -bdxtail;
- TWP(negate, adytail, bdxt_adyt1, bdxt_adyt0);
- TOP(bdxt_adyt1, bdxt_adyt0, cdz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (cdztail != 0.0) {
- TOP(bdxt_adyt1, bdxt_adyt0, cdztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- }
- if (cdxtail != 0.0) {
- if (adytail != 0.0) {
- TWP(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
- TOP(cdxt_adyt1, cdxt_adyt0, bdz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (bdztail != 0.0) {
- TOP(cdxt_adyt1, cdxt_adyt0, bdztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- if (bdytail != 0.0) {
- negate = -cdxtail;
- TWP(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
- TOP(cdxt_bdyt1, cdxt_bdyt0, adz, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- if (adztail != 0.0) {
- TOP(cdxt_bdyt1, cdxt_bdyt0, adztail, u3, u[2], u[1], u[0]);
- u[3] = u3;
- finlength = _fesze(finlength, finnow, 4, u,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- }
- }
-
- if (adztail != 0.0) {
- wlength = _seze(bctlen, bct, adztail, w);
- finlength = _fesze(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (bdztail != 0.0) {
- wlength = _seze(catlen, cat, bdztail, w);
- finlength = _fesze(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
- if (cdztail != 0.0) {
- wlength = _seze(abtlen, abt, cdztail, w);
- finlength = _fesze(finlength, finnow, wlength, w,
- finother);
- finswap = finnow; finnow = finother; finother = finswap;
- }
-
- return finnow[finlength - 1];
-}
-
-
-
-
-
-/*****************************************************************************/
-/* */
-/* PUBLIC FUNCTIONS */
-/* initPredicates() Sets the variables used for exact arithmetic. This */
-/* must be called once before using the other two functions. */
-/* orient2d() Computes the orientation of three 2D points. */
-/* orient3d() Computes the orientation of four 3D points. */
-/* */
-/*****************************************************************************/
-
-void initPredicates()
-{
- static char a_c=0;
- double hf, ck, lc;
- int e_o;
-
- if (a_c) return; else a_c = 1;
-
-#ifdef SPECIFY_FP_PRECISION
- unsigned int old_cfp;
- _controlfp_s(&old_cfp, _PC_53, MCW_PC);
-#endif
-
- e_o = 1;
- _eps = _spl = ck = 1.0;
- hf = 0.5;
-
- do
- {
- lc=ck;
- _eps *= hf;
- if (e_o) _spl *= 2.0;
- e_o = !e_o;
- ck = 1.0 + _eps;
- } while ((ck != 1.0) && (ck != lc));
- _spl += 1.0;
-
- _reb = (3.0 + 8.0 * _eps) * _eps;
- _ccwebA = (3.0 + 16.0 * _eps) * _eps;
- _ccwebB = (2.0 + 12.0 * _eps) * _eps;
- _ccwebC = (9.0 + 64.0 * _eps) * _eps * _eps;
- _o3ebA = (7.0 + 56.0 * _eps) * _eps;
- _o3ebB = (3.0 + 28.0 * _eps) * _eps;
- _o3ebC = (26.0 + 288.0 * _eps) * _eps * _eps;
- _iccebA = (10.0 + 96.0 * _eps) * _eps;
- _iccebB = (4.0 + 48.0 * _eps) * _eps;
- _iccebC = (44.0 + 576.0 * _eps) * _eps * _eps;
- _ispebA = (16.0 + 224.0 * _eps) * _eps;
- _ispebB = (5.0 + 72.0 * _eps) * _eps;
- _ispebC = (71.0 + 1408.0 * _eps) * _eps * _eps;
-
-#ifdef SPECIFY_FP_PRECISION
- _controlfp_s(&old_cfp, _CW_DEFAULT, MCW_PC);
-#endif
-}
-
-double orient2d(double *pa, double *pb, double *pc)
-{
- double dlf, drg, det, dsm, eb;
-
- dlf = (pa[0]-pc[0])*(pb[1]-pc[1]);
- drg = (pa[1]-pc[1])*(pb[0]-pc[0]);
- det = dlf - drg;
-
- if (dlf > 0.0) {if (drg <= 0.0) return det; else dsm = dlf + drg;}
- else if (dlf < 0.0) {if (drg >= 0.0) return det; else dsm = -dlf - drg;}
- else return det;
-
- eb = _ccwebA*dsm;
- if ((det>=eb) || (-det>=eb)) return det;
-
- return _adaptive2dorientation(pa, pb, pc, dsm);
-}
-
-double orient3d(double *pa, double *pb, double *pc, double *pd)
-{
- double adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz, pm, eb;
- double bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady, det;
-
- adx = pa[0]-pd[0]; bdx = pb[0]-pd[0]; cdx = pc[0]-pd[0];
- ady = pa[1]-pd[1]; bdy = pb[1]-pd[1]; cdy = pc[1]-pd[1];
- adz = pa[2]-pd[2]; bdz = pb[2]-pd[2]; cdz = pc[2]-pd[2];
-
- bdxcdy = bdx*cdy; cdxbdy = cdx*bdy;
- cdxady = cdx*ady; adxcdy = adx*cdy;
- adxbdy = adx*bdy; bdxady = bdx*ady;
-
- det = adz*(bdxcdy-cdxbdy)+bdz*(cdxady-adxcdy)+cdz*(adxbdy-bdxady);
- pm=(FABS(bdxcdy)+FABS(cdxbdy))*FABS(adz)+(FABS(cdxady)+FABS(adxcdy))*FABS(bdz)+(FABS(adxbdy)+FABS(bdxady))*FABS(cdz);
- eb = _o3ebA*pm;
- if ((det>eb) || (-det>eb)) return det;
- return _adaptive3dorientation(pa, pb, pc, pd, pm);
-}
diff --git a/src/mesh_fix/src/Kernel/point.cpp b/src/mesh_fix/src/Kernel/point.cpp
deleted file mode 100644
index 7d82b7f85..000000000
--- a/src/mesh_fix/src/Kernel/point.cpp
+++ /dev/null
@@ -1,653 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "point.h"
-#include
-#include
-#include
-
-namespace T_MESH
-{
-
-const Point INFINITE_POINT(DBL_MAX, DBL_MAX, DBL_MAX);
-
-#ifdef USE_HYBRID_KERNEL
-
-PM_Rational orient2D(const PM_Rational& px, const PM_Rational& py, const PM_Rational& qx, const PM_Rational& qy, const PM_Rational& rx, const PM_Rational& ry)
-{
- if (!PM_Rational::isUsingFiltering() && !PM_Rational::isUsingRationals())
- {
- return ((px - rx)*(qy - ry) - (py - ry)*(qx - rx));
- }
- else if (px.isOfDoubleType() && py.isOfDoubleType() && qx.isOfDoubleType() && qy.isOfDoubleType() && rx.isOfDoubleType() && ry.isOfDoubleType())
- {
- double pqr[6];
- pqr[0] = px.getDVal(); pqr[1] = py.getDVal();
- pqr[2] = qx.getDVal(); pqr[3] = qy.getDVal();
- pqr[4] = rx.getDVal(); pqr[5] = ry.getDVal();
- return orient2d(pqr, pqr + 2, pqr + 4);
- }
- else if (PM_Rational::isUsingRationals())
- {
- return ((px - rx)*(qy - ry) - (py - ry)*(qx - rx));
- }
- else
- {
- PM_Rational::use_rationals = true;
- PM_Rational O = ((px - rx)*(qy - ry) - (py - ry)*(qx - rx));
- PM_Rational::use_rationals = false;
- return O;
- }
-}
-
-PM_Rational orient3D(const Point *t, const Point *a, const Point *b, const Point *c)
-{
- if (!PM_Rational::isUsingFiltering() && !PM_Rational::isUsingRationals())
- {
- return TMESH_DETERMINANT3X3(t->x - c->x, t->y - c->y, t->z - c->z, a->x - c->x, a->y - c->y, a->z - c->z, b->x - c->x, b->y - c->y, b->z - c->z);
- } else if (a->x.isOfDoubleType() && a->y.isOfDoubleType() && a->z.isOfDoubleType() &&
- t->x.isOfDoubleType() && t->y.isOfDoubleType() && t->z.isOfDoubleType() &&
- b->x.isOfDoubleType() && b->y.isOfDoubleType() && b->z.isOfDoubleType() &&
- c->x.isOfDoubleType() && c->y.isOfDoubleType() && c->z.isOfDoubleType())
- {
- double p1[3], p2[3], p3[3], p4[3];
- p1[0] = (t->x).getDVal(); p1[1] = (t->y).getDVal(); p1[2] = (t->z).getDVal();
- p2[0] = (a->x).getDVal(); p2[1] = (a->y).getDVal(); p2[2] = (a->z).getDVal();
- p3[0] = (b->x).getDVal(); p3[1] = (b->y).getDVal(); p3[2] = (b->z).getDVal();
- p4[0] = (c->x).getDVal(); p4[1] = (c->y).getDVal(); p4[2] = (c->z).getDVal();
- return orient3d(p1, p2, p3, p4);
- } else if (PM_Rational::isUsingRationals())
- {
- return TMESH_DETERMINANT3X3(t->x - c->x, t->y - c->y, t->z - c->z, a->x - c->x, a->y - c->y, a->z - c->z, b->x - c->x, b->y - c->y, b->z - c->z);
- } else
- {
- PM_Rational::use_rationals = true;
- PM_Rational O = TMESH_DETERMINANT3X3(t->x - c->x, t->y - c->y, t->z - c->z, a->x - c->x, a->y - c->y, a->z - c->z, b->x - c->x, b->y - c->y, b->z - c->z);
- PM_Rational::use_rationals = false;
- return O;
- }
-}
-
-#else
-
-PM_Rational orient2D(const PM_Rational& px, const PM_Rational& py, const PM_Rational& qx, const PM_Rational& qy, const PM_Rational& rx, const PM_Rational& ry)
-{
-// return ((px - rx)*(qy - ry) - (py - ry)*(qx - rx));
-
- double pqr[6];
- pqr[0] = TMESH_TO_DOUBLE(px); pqr[1] = TMESH_TO_DOUBLE(py);
- pqr[2] = TMESH_TO_DOUBLE(qx); pqr[3] = TMESH_TO_DOUBLE(qy);
- pqr[4] = TMESH_TO_DOUBLE(rx); pqr[5] = TMESH_TO_DOUBLE(ry);
- return orient2d(pqr, pqr + 2, pqr + 4);
-}
-
-PM_Rational orient3D(const Point *t, const Point *a, const Point *b, const Point *c)
-{
-// return TMESH_DETERMINANT3X3(t->x - c->x, t->y - c->y, t->z - c->z, a->x - c->x, a->y - c->y, a->z - c->z, b->x - c->x, b->y - c->y, b->z - c->z);
-
- double p1[3], p2[3], p3[3], p4[3];
- p1[0] = TMESH_TO_DOUBLE(t->x); p1[1] = TMESH_TO_DOUBLE(t->y); p1[2] = TMESH_TO_DOUBLE(t->z);
- p2[0] = TMESH_TO_DOUBLE(a->x); p2[1] = TMESH_TO_DOUBLE(a->y); p2[2] = TMESH_TO_DOUBLE(a->z);
- p3[0] = TMESH_TO_DOUBLE(b->x); p3[1] = TMESH_TO_DOUBLE(b->y); p3[2] = TMESH_TO_DOUBLE(b->z);
- p4[0] = TMESH_TO_DOUBLE(c->x); p4[1] = TMESH_TO_DOUBLE(c->y); p4[2] = TMESH_TO_DOUBLE(c->z);
- return orient3d(p1, p2, p3, p4);
-}
-
-#endif
-
-coord Point::exactOrientation(const Point *a, const Point *b, const Point *c) const
-{
- return orient3D(this, a, b, c);
-}
-
-
-////////////// Alignment check /////////////
-
-bool Point::exactMisalignment(const Point *A, const Point *B) const
-{
- if (orient2D(x, y, A->x, A->y, B->x, B->y) != 0) return true;
- if (orient2D(y, z, A->y, A->z, B->y, B->z) != 0) return true;
- if (orient2D(z, x, A->z, A->x, B->z, B->x) != 0) return true;
-
- return false;
-}
-
-bool Point::exactSameSideOnPlane(const Point *Q, const Point *A, const Point *B) const
-{
- coord o1, o2;
- int s1, s2;
-
- o1 = orient2D(x, y, A->x, A->y, B->x, B->y);
- o2 = orient2D(Q->x, Q->y, A->x, A->y, B->x, B->y);
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- o1 = orient2D(y, z, A->y, A->z, B->y, B->z);
- o2 = orient2D(Q->y, Q->z, A->y, A->z, B->y, B->z);
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- o1 = orient2D(z, x, A->z, A->x, B->z, B->x);
- o2 = orient2D(Q->z, Q->x, A->z, A->x, B->z, B->x);
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- return true;
-}
-
-// Returns true if the coplanar point 'p' is in the inner area of 't'.
-// Undetermined if p and t are not coplanar.
-bool Point::pointInInnerTriangle(const Point *p, const Point *v1, const Point *v2, const Point *v3)
-{
- //if (!p->exactSameSideOnPlane(v1, v2, v3)) return false;
- //if (!p->exactSameSideOnPlane(v2, v3, v1)) return false;
- //if (!p->exactSameSideOnPlane(v3, v1, v2)) return false;
- //return true;
-
- // Less readable, but slightly more efficient (12 predicates instead of 18)
-
- coord o1, o2, oo2, oo4, oo6;
- int s1, s2;
-
- o1 = orient2D(p->x, p->y, v2->x, v2->y, v3->x, v3->y);
- o2 = oo2 = orient2D(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y);
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- o1 = orient2D(p->y, p->z, v2->y, v2->z, v3->y, v3->z);
- o2 = oo4 = orient2D(v1->y, v1->z, v2->y, v2->z, v3->y, v3->z);
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- o1 = orient2D(p->z, p->x, v2->z, v2->x, v3->z, v3->x);
- o2 = oo6 = orient2D(v1->z, v1->x, v2->z, v2->x, v3->z, v3->x);
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- o1 = orient2D(p->x, p->y, v3->x, v3->y, v1->x, v1->y);
- o2 = oo2,
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- o1 = orient2D(p->y, p->z, v3->y, v3->z, v1->y, v1->z);
- o2 = oo4;
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- o1 = orient2D(p->z, p->x, v3->z, v3->x, v1->z, v1->x);
- o2 = oo6;
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- o1 = orient2D(p->x, p->y, v1->x, v1->y, v2->x, v2->y);
- o2 = oo2;
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- o1 = orient2D(p->y, p->z, v1->y, v1->z, v2->y, v2->z);
- o2 = oo4;
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- o1 = orient2D(p->z, p->x, v1->z, v1->x, v2->z, v2->x);
- o2 = oo6;
- s1 = (o1>0) ? (1) : ((o1<0) ? (-1) : (0)); s2 = (o2>0) ? (1) : ((o2<0) ? (-1) : (0));
- if (s1 != s2) return false;
-
- return true;
-}
-
-//////// Lexicographic Point comparison //////////
-
-// This can be used with std::sort()
-bool Point::operator<(const Point& s) const
-{
- if (xs.x) return false;
- if (ys.y) return false;
- if (zx - ((Point *)b)->x)) < 0) return -1;
- if (c > 0) return 1;
- if ((c=(((Point *)a)->y - ((Point *)b)->y)) < 0) return -1;
- if (c > 0) return 1;
- if ((c=(((Point *)a)->z - ((Point *)b)->z)) < 0) return -1;
- if (c > 0) return 1;
-
- return 0;
-}
-
-//////////////// Normalization /////////////////////////
-
-void Point::normalize()
-{
- coord l = length();
-
- if (l == 0) TMesh::error("normalize : Trying to normalize a null vector !\n");
-
- x/=l;
- y/=l;
- z/=l;
-}
-
-
-//////////////////// Point rotation ////////////////////
-/////////// 'ang' radians CCW around 'axis' ////////////
-
-void Point::rotate(const Point& a, const double& ang)
-{
- double l, q[4], m[3][3];
- if ((l = a.length())==0.0) return;
- l = sin(ang/2.0)/l;
-
- q[0] = TMESH_TO_DOUBLE(a.x)*l;
- q[1] = TMESH_TO_DOUBLE(a.y)*l;
- q[2] = TMESH_TO_DOUBLE(a.z)*l;
- q[3] = cos(ang/2.0);
-
- m[0][0] = 1.0 - (q[1]*q[1] + q[2]*q[2])*2.0;
- m[0][1] = (q[0] * q[1] + q[2] * q[3])*2.0;
- m[0][2] = (q[2] * q[0] - q[1] * q[3])*2.0;
-
- m[1][0] = (q[0] * q[1] - q[2] * q[3])*2.0;
- m[1][1] = 1.0 - (q[2] * q[2] + q[0] * q[0])*2.0;
- m[1][2] = (q[1] * q[2] + q[0] * q[3])*2.0;
-
- m[2][0] = (q[2] * q[0] + q[1] * q[3])*2.0;
- m[2][1] = (q[1] * q[2] - q[0] * q[3])*2.0;
- m[2][2] = 1.0 - (q[1] * q[1] + q[0] * q[0])*2.0;
-
- q[0] = TMESH_TO_DOUBLE(x); q[1] = TMESH_TO_DOUBLE(y); q[2] = TMESH_TO_DOUBLE(z);
- x = m[0][0]*q[0] + m[1][0]*q[1] + m[2][0]*q[2];
- y = m[0][1]*q[0] + m[1][1]*q[1] + m[2][1]*q[2];
- z = m[0][2]*q[0] + m[1][2]*q[1] + m[2][2]*q[2];
-}
-
-
-///// Project the point on the plane whose normal is 'nor' /////
-
-void Point::project(const Point *nor)
-{
- Point pr = (*this)-((*nor)*((*this)*(*nor)));
- x = pr.x; y = pr.y; z = pr.z;
-}
-
-
-/////////// Distance from the line passing through A and B ////////
-
-double Point::distanceFromLine(const Point *A, const Point *B) const
-{
- Point BA = (*B)-(*A);
- double lba = BA.length();
-
- if (lba == 0.0) TMesh::error("distanceFromLine : Degenerate line passed !\n");
-
- return ((((*this)-(*A))&BA).length())/(lba);
-}
-
-
-/////////////////// Distance from a line ///////////////////////
-//// 'cc' is initialized as the point of the line whose ////
-//// distance from 'this' is minimum. ////
-
-double Point::distanceFromLine(const Point *A, const Point *B, Point *cc) const
-{
- Point AB = (*A)-(*B);
- Point AP = (*A)-(*this);
- Point BP = (*B)-(*this);
-
- if (AP.isNull())
- {
- cc->x = A->x; cc->y = A->y; cc->z = A->z;
- return 0.0;
- }
- else if (BP.isNull())
- {
- cc->x = B->x; cc->y = B->y; cc->z = B->z;
- return 0.0;
- }
-
- coord t = (AB*AB);
- if (t == 0.0) TMesh::error("distanceFromLine : Degenerate line passed !\n");
- else t = (AP*AB)/(-t);
- cc->x = t*AB.x + A->x;
- cc->y = t*AB.y + A->y;
- cc->z = t*AB.z + A->z;
- return distanceFromLine(A,B);
-}
-
-
-////////////// Projection on the line passing through A and B ///////////
-
-Point Point::projection(const Point *A, const Point *B) const
-{
- Point BA = (*B)-(*A);
- coord l = BA*BA;
- if (l == 0.0) TMesh::error("projection : Degenerate line passed !\n");
-
- return ((*A)+(BA*((BA*((*this)-(*A)))/(l))));
-}
-
-
-////////////// Distance from a segment /////////////////
-
-double Point::distanceFromEdge(const Point *A, const Point *B) const
-{
- Point AP = (*A)-(*this); double apl = AP.length();
- Point BP = (*B) - (*this); double bpl = BP.length();
-
- if (apl == 0 || bpl == 0.0) return 0.0;
-
- Point AB = (*A) - (*B); double abl = AP.length();
- Point BA = (*B)-(*A);
-
- if (abl*apl == 0.0 || abl*bpl == 0.0) return apl;
-
- if (AB.getAngle(AP) > PI2) return apl;
- else if (BA.getAngle(BP) > PI2) return bpl;
-
- return distanceFromLine(A,B);
-}
-
-/////////////////// Distance from a segment ///////////////////////
-//// 'cc' is initialized as the point of the segment whose ////
-//// distance from 'this' is minimum. ////
-
-double Point::distanceFromEdge(const Point *A, const Point *B, Point *cc) const
-{
- Point AP = (*A)-(*this); double apl = AP.length();
- Point BP = (*B) - (*this); double bpl = BP.length();
-
- if (apl == 0) {cc->setValue(A); return 0.0;}
- if (bpl == 0) {cc->setValue(B); return 0.0;}
-
- Point AB = (*A)-(*B); coord abl = AP.length();
- Point BA = (*B)-(*A);
-
- if (abl*apl == 0.0 || abl*bpl == 0.0) {cc->setValue(A); return apl;}
-
- if (AB.getAngle(AP) > PI2) {cc->setValue(A); return apl;}
- else if (BA.getAngle(BP) > PI2) {cc->setValue(B); return bpl;}
-
- coord t = (AB*AB);
- if (t == 0.0) {cc->setValue(A); return apl;}
- else t = (AP*AB)/(-t);
- cc->x = t*AB.x + A->x;
- cc->y = t*AB.y + A->y;
- cc->z = t*AB.z + A->z;
- return distanceFromLine(A,B);
-}
-
-///////////////// Angle between two vectors ///////////////
-
-double Point::getAngle(const Point& p) const
-{
- return atan2(((*this)&p).length(), TMESH_TO_DOUBLE(((*this)*p)));
-}
-
-
-/////////// Distance of two straight lines ///////////////
-
-double Point::distanceLineLine(const Point *A, const Point *A1, const Point *B1) const
-{
- Point uu1 = ((*this)-(*A))&((*A1)-(*B1));
- coord nom = ((*A)-(*A1))*(uu1);
- return FABS(TMESH_TO_DOUBLE(nom)) / (uu1.length());
-}
-
-
-/////////// Solution of a linear system 3 x 3 //////////
-///// System Ax = d, where A = (a,b,c) rows, d = this /////
-
-Point Point::linearSystem(const Point& a, const Point& b, const Point& c)
-{
- Point ret;
- coord det_A = TMESH_DETERMINANT3X3(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z);
- if (det_A == 0.0) return INFINITE_POINT;
- ret.x = TMESH_DETERMINANT3X3(x, a.y, a.z, y, b.y, b.z, z, c.y, c.z);
- ret.y = TMESH_DETERMINANT3X3(a.x, x, a.z, b.x, y, b.z, c.x, z, c.z);
- ret.z = TMESH_DETERMINANT3X3(a.x, a.y, x, b.x, b.y, y, c.x, c.y, z);
-
- return (ret/det_A);
-}
-
-
-
-//// Computes the closest points of the two lines 'this'-v1 and p1-p2 ////
-//// Returns FALSE if the lines are parallel. ////
-
-int Point::closestPoints(const Point *v1, const Point *p1, const Point *p2, Point *ptOnThis, Point *ptOnLine2) const
-{
- Point pos1 = *this; Point dir1 = (*v1)-pos1;
- Point pos2 = *p1; Point dir2 = (*p2)-pos2;
- coord d1l = dir1.length(), d2l = dir2.length();
-
- if (d1l == 0.0 && d2l == 0.0)
- {ptOnThis->setValue(this); ptOnLine2->setValue(p1); return 1;}
- if (d1l*d2l == 0.0)
- {
- if (d1l <= d2l)
- {ptOnThis->setValue(this); distanceFromLine(p1, p2, ptOnLine2); return 1;}
- if (d2l <= d1l)
- {ptOnLine2->setValue(p1); p1->distanceFromLine(this, v1, ptOnThis); return 1;}
- }
-
- coord ang = dir1.getAngle(dir2);
- if (ang == 0.0 || ang == M_PI) return 0;
-
- coord s, t, A, B, C, D, E, F, denom;
-
- denom = ((dir1*dir2)/(d1l*d2l));
- denom = denom*denom - 1;
-
- dir1.normalize();
- dir2.normalize();
-
- A = E = dir1*dir2;
- B = dir1*dir1;
- C = (dir1*pos1) - (dir1*pos2);
- D = dir2*dir2;
- F = (dir2*pos1) - (dir2*pos2);
-
- s = ( C * D - A * F ) / denom;
- t = ( C * E - B * F ) / denom;
- *ptOnThis = pos1 + (dir1*s);
- *ptOnLine2 = pos2 + (dir2*t);
-
-// Uncomment the following to compute the distance between segments
-// if (s < 0 || s > ((*v1)-(*this)).length() || t < 0 || t > ((*p2)-(*p1)).length())
-// return 0; // The points does not belong to the edges
-
- return 1;
-}
-
-
-
-// Returns the point of intersection between the two lines defined by (p,q) and (r,s) respectively
-// Return INFINITE_POINT is lines are parallel or if p==q or r==s
-Point Point::lineLineIntersection(const Point& p, const Point& q, const Point& r, const Point& s)
-{
- Point da = q - p;
- Point db = s - r;
- Point dc = r - p;
- Point dab = (da&db);
-
- if (dc*dab != 0.0) return INFINITE_POINT;
-
- coord k = (((dc&db)*dab) / (dab*dab));
- return p + (da*k);
-}
-
-// Returns the point of intersection between the line for (p,q) and the plane for (r,s,t)
-// Returns INFINITE_POINT in case of parallelism
-Point Point::linePlaneIntersection(const Point& p, const Point& q, const Point& r, const Point& s, const Point& t)
-{
- coord den = TMESH_DETERMINANT3X3(p.x - q.x, p.y - q.y, p.z - q.z, s.x - r.x, s.y - r.y, s.z - r.z, t.x - r.x, t.y - r.y, t.z - r.z);
- if (den == 0) return INFINITE_POINT;
- coord num = TMESH_DETERMINANT3X3(p.x - r.x, p.y - r.y, p.z - r.z, s.x - r.x, s.y - r.y, s.z - r.z, t.x - r.x, t.y - r.y, t.z - r.z);
- coord gamma = num / den;
- return p + ((q - p)*gamma);
-}
-
-coord Point::squaredTriangleArea3D(const Point& p, const Point& q, const Point& r)
-{
- Point pr = (p - r), qr = (q - r);
- Point n = pr&qr;
- return (n*n) / 4;
-}
-
-
-//////////////////////////////////////////////////////////////////
-//
-// Basic predicates of type 'pointIn'
-//
-//////////////////////////////////////////////////////////////////
-
-// Returns true if 'p' is a point of the segment v1-v2 (endpoints excluded)
-bool Point::pointInInnerSegment(const Point *p, const Point *v1, const Point *v2)
-{
- if (!p->exactMisalignment(v1, v2)) // Segment and point aligned
- {
- if (v1->x < v2->x && v1->x < p->x && p->x < v2->x) return true;
- if (v1->y < v2->y && v1->y < p->y && p->y < v2->y) return true;
- if (v1->z < v2->z && v1->z < p->z && p->z < v2->z) return true;
- if (v1->x > v2->x && v1->x > p->x && p->x > v2->x) return true;
- if (v1->y > v2->y && v1->y > p->y && p->y > v2->y) return true;
- if (v1->z > v2->z && v1->z > p->z && p->z > v2->z) return true;
- }
- return false;
-}
-
-// Returns true if 'p' is a point of the segment v1-v2 (endpoints included)
-bool Point::pointInSegment(const Point *p, const Point *v1, const Point *v2)
-{
- return ((*p) == (*(v1)) || (*p) == (*(v2)) || Point::pointInInnerSegment(p, v1, v2));
-}
-
-
-// Returns true if the coplanar point 'p' is either in the inner area of
-// 't' or on its border. Undetermined if p and t are not coplanar.
-bool Point::pointInTriangle(const Point *p, const Point *v1, const Point *v2, const Point *v3)
-{
- if (Point::pointInSegment(p, v1, v2)) return true;
- else if (Point::pointInSegment(p, v2, v3)) return true;
- else if (Point::pointInSegment(p, v3, v1)) return true;
- else return Point::pointInInnerTriangle(p, v1, v2, v3);
-}
-
-
-//////////////////////////////////////////////////////////////////
-//
-// Basic predicates of type 'segmentIntersects'
-//
-//////////////////////////////////////////////////////////////////
-
-// true if (p1-p2) properly intersects (sp1-sp2) at any point (endpoints included).
-// Collinear overlapping segments are not considered to be properly intersecting.
-bool Point::segmentsIntersect(const Point *p1, const Point *p2, const Point *sp1, const Point *sp2)
-{
- return (p1->exactOrientation(p2, sp1, sp2) == 0 && !p1->exactSameSideOnPlane(p2, sp1, sp2) && !sp1->exactSameSideOnPlane(sp2, p1, p2));
-}
-
-// Returns true if the interior of (p1-p2) properly intersects the interior of (sp1-sp2).
-// Collinear overlapping segments are not considered to be properly intersecting.
-bool Point::innerSegmentsCross(const Point& p1, const Point& p2, const Point& sp1, const Point& sp2)
-{
- if (p1 == sp1 || p1 == sp2 || p2 == sp1 || p2 == sp2) return false;
- return (p1.exactOrientation(&p2, &sp1, &sp2) == 0 && !p1.exactSameSideOnPlane(&p2, &sp1, &sp2) && !sp1.exactSameSideOnPlane(&sp2, &p1, &p2));
-}
-
-bool Point::segmentIntersectsTriangle(const Point *s1, const Point *s2, const Point *v1, const Point *v2, const Point *v3)
-{
- coord o1, o2, o3;
-
- coord mx = MIN(s1->x, s2->x);
- if (v1->x < mx && v2->x < mx && v3->x < mx) return false;
- mx = MAX(s1->x, s2->x);
- if (v1->x > mx && v2->x > mx && v3->x > mx) return false;
- mx = MIN(s1->y, s2->y);
- if (v1->y < mx && v2->y < mx && v3->y < mx) return false;
- mx = MAX(s1->y, s2->y);
- if (v1->y > mx && v2->y > mx && v3->y > mx) return false;
- mx = MIN(s1->z, s2->z);
- if (v1->z < mx && v2->z < mx && v3->z < mx) return false;
- mx = MAX(s1->z, s2->z);
- if (v1->z > mx && v2->z > mx && v3->z > mx) return false;
-
- o1 = s1->exactOrientation(v1, v2, v3);
- o2 = s2->exactOrientation(v1, v2, v3);
- if (o1 == 0 && o2 == 0)
- {
- if (!s1->exactSameSideOnPlane(s2, v1, v2) && !v1->exactSameSideOnPlane(v2, s1, s2)) return true;
- if (!s1->exactSameSideOnPlane(s2, v2, v3) && !v2->exactSameSideOnPlane(v3, s1, s2)) return true;
- if (!s1->exactSameSideOnPlane(s2, v3, v1) && !v3->exactSameSideOnPlane(v1, s1, s2)) return true;
- if (Point::pointInInnerTriangle(s1, v1, v2, v3) && Point::pointInInnerTriangle(s2, v1, v2, v3)) return true;
- return false;
- }
-
- if ((o1>0 && o2>0) || (o1<0 && o2<0)) return false; // s1 and s2 are both above/below v1,v2,v3
- o1 = s1->exactOrientation(s2, v1, v2);
- o2 = s1->exactOrientation(s2, v2, v3);
- if ((o1>0 && o2<0) || (o1<0 && o2>0)) return false;
- o3 = s1->exactOrientation(s2, v3, v1);
- if ((o1>0 && o3<0) || (o1<0 && o3>0)) return false;
- if ((o2>0 && o3<0) || (o2<0 && o3>0)) return false;
- return true;
-}
-
-bool Point::segmentIntersectsTriangle(const Point *s1, const Point *s2, const Point *v1, const Point *v2, const Point *v3, const coord& oo1, const coord& oo2)
-{
- // In this case the fast reject by bounding box appears to be a disadvantage ...
- if (oo1 == 0 && oo2 == 0)
- {
- if (!s1->exactSameSideOnPlane(s2, v1, v2) && !v1->exactSameSideOnPlane(v2, s1, s2)) return true;
- if (!s1->exactSameSideOnPlane(s2, v2, v3) && !v2->exactSameSideOnPlane(v3, s1, s2)) return true;
- if (!s1->exactSameSideOnPlane(s2, v3, v1) && !v3->exactSameSideOnPlane(v1, s1, s2)) return true;
- if (Point::pointInInnerTriangle(s1, v1, v2, v3) && Point::pointInInnerTriangle(s2, v1, v2, v3)) return true;
- return false;
- }
-
- if ((oo1>0 && oo2>0) || (oo1<0 && oo2<0)) return false; // s1 and s2 are both above/below v1,v2,v3
- coord o1, o2, o3;
- o1 = s1->exactOrientation(s2, v1, v2);
- o2 = s1->exactOrientation(s2, v2, v3);
- if ((o1>0 && o2<0) || (o1<0 && o2>0)) return false;
- o3 = s1->exactOrientation(s2, v3, v1);
- if ((o1>0 && o3<0) || (o1<0 && o3>0)) return false;
- if ((o2>0 && o3<0) || (o2<0 && o3>0)) return false;
- return true;
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/Kernel/tmesh.cpp b/src/mesh_fix/src/Kernel/tmesh.cpp
deleted file mode 100644
index c301cebeb..000000000
--- a/src/mesh_fix/src/Kernel/tmesh.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2012: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "tmesh_kernel.h"
-#include
-#include
-#include
-
-namespace T_MESH
-{
-
-extern "C" void initPredicates();
-
-void (* TMesh::display_message)(const char*, int) = NULL;
-
-const char *TMesh::app_name = NULL;
-const char *TMesh::app_version = NULL;
-const char *TMesh::app_year = NULL;
-const char *TMesh::app_authors = NULL;
-const char *TMesh::app_url = NULL;
-const char *TMesh::app_maillist = NULL;
-const char *TMesh::filename = NULL;
-bool TMesh::quiet = false;
-
-void TMesh::init(void (*dm)(const char *, int))
-{
- display_message = dm;
- app_name = NULL;
- app_version = NULL;
- app_year = NULL;
- app_authors = NULL;
- app_url = NULL;
- app_maillist = NULL;
- filename = NULL;
- quiet = false;
- initPredicates();
-}
-
-
-///////////// Prints a fatal error message and exits /////////////
-
-void TMesh::error(const char *msg, ...)
-{
- static char fmt[2048], fms[4096];
- va_list ap;
- va_start(ap, msg);
- strcpy(fmt,"\nERROR- ");
- strcat(fmt,msg);
- vsprintf(fms,fmt,ap);
-
- if (display_message != NULL)
- display_message(fms, DISPMSG_ACTION_ERRORDIALOG);
- else
- {
- fprintf(stderr,fms);
- exit(-1);
- }
-}
-
-///////////// Prints a warning message /////////////
-
-void TMesh::warning(const char *msg, ...)
-{
- if (quiet) return;
- static char fmt[2048], fms[4096];
- va_list ap;
- va_start(ap, msg);
- strcpy(fmt,"WARNING- ");
- strcat(fmt,msg);
- vsprintf(fms,fmt,ap);
-
- if (display_message != NULL)
- display_message(fms, DISPMSG_ACTION_PUTMESSAGE);
- else
- fputs(fms, stderr);
-
- va_end(ap);
-}
-
-///////////// Prints an information message /////////////
-
-void TMesh::info(const char *msg, ...)
-{
- if (quiet) return;
- static char fmt[2048], fms[4096];
- va_list ap;
- va_start(ap, msg);
- strcpy(fmt,"INFO- ");
- strcat(fmt,msg);
- vsprintf(fms,fmt,ap);
-
- if (display_message != NULL)
- display_message(fms, DISPMSG_ACTION_PUTMESSAGE);
- else
- printf(fms);
-
- va_end(ap);
-}
-
-///////// Reports progress status for a process //////////
-
-void TMesh::begin_progress()
-{
- if (quiet) return;
- if (display_message != NULL)
- display_message("\n", DISPMSG_ACTION_PUTNEWLINE);
- else
- printf("\n");
-}
-
-void TMesh::report_progress(const char *msg, ...)
-{
- if (quiet) return;
- static char fmt[2048] = "\r";
- static char fms[4096];
- static char rotating_bar[5] = "-\\|/";
- static unsigned char wc=0;
-
- if (msg == NULL)
- {
- sprintf(fms,"%c",rotating_bar[wc++]); if (wc==4) wc=0;
- strcpy(fmt+1,fms);
-
- if (display_message != NULL)
- display_message(fmt, DISPMSG_ACTION_PUTPROGRESS);
- else
- {
- printf("%s",fmt);
- fflush(stdout);
- }
- }
- else
- {
- va_list ap;
- va_start(ap, msg);
- strcpy(fmt+1,msg);
- vsprintf(fms,fmt,ap);
-
- if (display_message != NULL)
- display_message(fms, DISPMSG_ACTION_PUTPROGRESS);
- else
- {
- printf("%s", fms);
- fflush(stdout);
- }
- va_end(ap);
- }
-}
-
-void TMesh::end_progress()
-{
- if (quiet) return;
- if (display_message != NULL)
- display_message("\n", DISPMSG_ACTION_PUTNEWLINE);
- else
- printf("\n");
-}
-
-void TMesh::useRationals(bool u)
-{
-#ifdef USE_HYBRID_KERNEL
- coord::useRationals(u);
-#endif
-}
-
-bool TMesh::isUsingRationals()
-{
-#ifdef USE_HYBRID_KERNEL
- return coord::isUsingRationals();
-#else
- return false;
-#endif
-}
-
-void TMesh::useFiltering(bool u)
-{
-#ifdef USE_HYBRID_KERNEL
- coord::useFiltering(u);
-#endif
-}
-
-bool TMesh::isUsingFiltering()
-{
-#ifdef USE_HYBRID_KERNEL
- return coord::isUsingFiltering();
-#else
- return false;
-#endif
-}
-
-void TMesh::addMessageToLogFile(const char *msg)
-{
- FILE *fp = fopen("tmesh.log", "a");
- fprintf(fp, msg);
- fclose(fp);
-}
-
-// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
-char *currentDateTime()
-{
- time_t now = time(0);
- struct tm tstruct;
- static char buf[80];
- tstruct = *localtime(&now);
- strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct);
-
- return buf;
-}
-
-void TMesh::logToFileAndExit(const char *s)
-{
- static char msg[2048];
- sprintf(msg, "%s\nFILE: %s\nRETURN VALUE: %s\n\n", currentDateTime(), (filename) ? (filename) : ("unknown"), s);
- addMessageToLogFile(msg);
- TMesh::error(msg);
-}
-
-void TMesh::exitOnTimeout(clock_t ts)
-{
- static clock_t beginning_time, timeout_secs;
- if (ts != 0) { beginning_time = clock(); timeout_secs = ts; }
- else if (((clock() - beginning_time) / 1000) > timeout_secs) logToFileAndExit("Timeout reached");
-}
-
-void TMesh::printElapsedTime(bool reset)
-{
- static clock_t beginning_time;
- if (reset) beginning_time = clock();
- else printf("\n\n********** PARTIAL ELAPSED: %d msecs\n\n", int((clock() - beginning_time)));
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/MeshFix/meshfix.cpp b/src/mesh_fix/src/MeshFix/meshfix.cpp
deleted file mode 100644
index d864c7964..000000000
--- a/src/mesh_fix/src/MeshFix/meshfix.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-#include "tmesh.h"
-#include
-#include
-#include
-
-using namespace T_MESH;
-
-double closestPair(List *bl1, List *bl2, Vertex **closest_on_bl1, Vertex **closest_on_bl2)
-{
- Node *n, *m;
- Vertex *v, *w;
- double adist, mindist = DBL_MAX;
-
- FOREACHVVVERTEX(bl1, v, n)
- FOREACHVVVERTEX(bl2, w, m)
- if ((adist = w->squaredDistance(v))T)), t, n) t->info = NULL;
- FOREACHVTTRIANGLE((&(tin->T)), t, n) if (t->info == NULL)
- {
- i++;
- triList.appendHead(t);
- t->info = new intWrapper(i);
-
- while (triList.numels())
- {
- t = (Triangle *)triList.popHead();
- if ((s = t->t1()) != NULL && s->info == NULL) { triList.appendHead(s); s->info = new intWrapper(i); }
- if ((s = t->t2()) != NULL && s->info == NULL) { triList.appendHead(s); s->info = new intWrapper(i); }
- if ((s = t->t3()) != NULL && s->info == NULL) { triList.appendHead(s); s->info = new intWrapper(i); }
- }
- }
-
- if (i<2)
- {
- FOREACHVTTRIANGLE((&(tin->T)), t, n) t->info = NULL;
- // JMesh::info("Mesh is a single component. Nothing done.");
- return false;
- }
-
- FOREACHVTTRIANGLE((&(tin->T)), t, n)
- {
- t->v1()->info = t->v2()->info = t->v3()->info = t->info;
- }
-
- FOREACHVVVERTEX((&(tin->V)), v, n) if (!IS_VISITED2(v) && v->isOnBoundary())
- {
- w = v;
- one_loop = new List;
- do
- {
- one_loop->appendHead(w); MARK_VISIT2(w);
- w = w->nextOnBoundary();
- } while (w != v);
- boundary_loops.appendHead(one_loop);
- }
- FOREACHVVVERTEX((&(tin->V)), v, n) UNMARK_VISIT2(v);
-
- bloops_array = (List **)boundary_loops.toArray();
- numloops = boundary_loops.numels();
-
- int numtris = tin->T.numels();
- double adist, mindist = DBL_MAX;
-
- gv = NULL;
- for (i = 0; ihead()->data)->info != ((Vertex *)bloops_array[j]->head()->data)->info)
- {
- adist = closestPair(bloops_array[i], bloops_array[j], &v, &w);
- if (adistjoinBoundaryLoops(gv, gw, 1, 0);
-
- FOREACHVTTRIANGLE((&(tin->T)), t, n) t->info = NULL;
- FOREACHVVVERTEX((&(tin->V)), v, n) v->info = NULL;
-
- free(bloops_array);
- while ((one_loop = (List *)boundary_loops.popHead()) != NULL) delete one_loop;
-
- return (gv != NULL);
-}
-
-void usage()
-{
- printf("\nMeshFix V2.0 - by Marco Attene\n------\n");
- printf("Usage: MeshFix inmeshfile [outmeshfile] [-a] [-j] [-x]\n");
- printf(" Processes 'inmeshfile' and saves the result to 'outmeshfile'\n");
- printf(" If 'outmeshfile' is not specified 'inmeshfile_fixed.off' will be produced\n");
- printf(" Option '-a' = joins multiple open components before starting\n");
- printf(" Option '-j' = output files in STL format insted of OFF\n");
- printf(" Option '-x' exits if output file already exists.\n");
- printf(" Accepted input formats are OFF, PLY and STL.\n Other formats are supported only partially.\n");
- printf("\nIf MeshFix is used for research purposes, please cite the following paper:\n");
- printf("\n M. Attene.\n A lightweight approach to repairing digitized polygon meshes.\n The Visual Computer, 2010. (c) Springer.\n");
- printf("\nHIT ENTER TO EXIT.\n");
- getchar();
- exit(0);
-}
-
-char *createFilename(const char *iname, const char *subext, char *oname, const char *newextension)
-{
- static char tname[2048];
- strcpy(tname, iname);
- for (int n = strlen(tname) - 1; n>0; n--) if (tname[n] == '.') { tname[n] = '\0'; break; }
- sprintf(oname, "%s%s%s", tname, subext, newextension);
- return oname;
-}
-
-
-int main(int argc, char *argv[])
-{
- TMesh::init(); // This is mandatory
- TMesh::app_name = "MeshFix";
- TMesh::app_version = "2.0";
- TMesh::app_year = "2016";
- TMesh::app_authors = "Marco Attene";
- TMesh::app_maillist = "attene@ge.imati.cnr.it";
-
- clock_t beginning = clock();
-
- // Uncomment the following to prevent message reporting
- // TMesh::quiet = true;
-
- Basic_TMesh tin;
- bool stl_output = false;
- bool skip_if_fixed = false;
- bool join_multiple_components = false;
- char infilename[2048], outfilename[2048], extension[] = ".off";
-
- if (argc < 2) usage();
-
- float par;
- int i = 2;
- if (argc > 2 && argv[2][0] == '-') i--;
-
- for (; i2 && argv[2][0] != '-') sprintf(outfilename, "%s", argv[2]);
- else createFilename(infilename, "_fixed", outfilename, extension);
-
- if (skip_if_fixed && fopen(outfilename, "r")) TMesh::error("Output file already exists (-x option specified).");
-
- // The loader automatically reconstructs a manifold triangle connectivity
- if (tin.load(infilename) != 0) TMesh::error("Can't open file.\n");
-
- if (join_multiple_components)
- {
- TMesh::info("\nJoining input components ...\n");
- TMesh::begin_progress();
- while (joinClosestComponents(&tin)) TMesh::report_progress("Num. components: %d ", tin.shells());
- TMesh::end_progress();
- tin.deselectTriangles();
- }
-
- // Keep only the largest component (i.e. with most triangles)
- int sc = tin.removeSmallestComponents();
- if (sc) TMesh::warning("Removed %d small components\n",sc);
-
- // Fill holes
- if (tin.boundaries())
- {
- TMesh::warning("Patching holes\n");
- tin.fillSmallBoundaries(0, true);
- }
-
- // Run geometry correction
- if (!tin.boundaries()) TMesh::warning("Fixing degeneracies and intersections...\n");
- if (tin.boundaries() || !tin.meshclean()) TMesh::warning("MeshFix could not fix everything.\n", sc);
-
-
- TMesh::info("Saving output mesh ...\n");
- tin.save(outfilename);
-
- printf("Elapsed time: %d ms\n", clock() - beginning);
-
- return 0;
-}
diff --git a/src/mesh_fix/src/TMesh/edge.cpp b/src/mesh_fix/src/TMesh/edge.cpp
deleted file mode 100644
index cee1ff3eb..000000000
--- a/src/mesh_fix/src/TMesh/edge.cpp
+++ /dev/null
@@ -1,427 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "edge.h"
-#include "triangle.h"
-
-namespace T_MESH
-{
-
-//////// Length-based edge comparison for qsort //////////
-
-int edgeCompare(const Data *a, const Data *b)
-{
- coord la = ((Edge *)a)->squaredLength();
- coord lb = ((Edge *)b)->squaredLength();
-
- if (lalb) return 1;
-
- return 0;
-}
-
-
-//////// Lexycographic edge comparison for qsort //////////
-
-int lexEdgeCompare(const Data *a, const Data *b)
-{
- Vertex *va1 = ((Edge *)a)->v1;
- Vertex *va2 = ((Edge *)a)->v2;
- Vertex *vb1 = ((Edge *)b)->v1;
- Vertex *vb2 = ((Edge *)b)->v2;
-
- if (xyzCompare(va1, va2) > 0) p_swap((void **)&va1, (void **)&va2);
- if (xyzCompare(vb1, vb2) > 0) p_swap((void **)&vb1, (void **)&vb2);
-
- int ca = xyzCompare(va1, vb1);
-
- if (ca == 0) return xyzCompare(va2, vb2);
-
- return ca;
-}
-
-
-//////// Vertex-based edge comparison for qsort //////////
-
-int vtxEdgeCompare(const Data *a, const Data *b)
-{
- Vertex *va1 = ((Edge *)a)->v1;
- Vertex *va2 = ((Edge *)a)->v2;
- Vertex *vb1 = ((Edge *)b)->v1;
- Vertex *vb2 = ((Edge *)b)->v2;
- Vertex *tmp;
-
- if (va2vb1) return 1;
- if (va2vb2) return 1;
- return 0;
-}
-
-
-//////////////////////// Constructor ///////////////////////
-//!< AMF_ADD 1.1-2 >
-Edge::Edge(){
- mask = 0;
- info = NULL;
-}
-Edge::Edge(Vertex *va, Vertex *vb)
-{
- v1 = va;
- v2 = vb;
- t1 = t2 = NULL;
- info = NULL;
- mask = 0;
-}
-
-
-////////////////// Destructor /////////////////////////////
-
-Edge::~Edge()
-{
-}
-
-
-////// Returns the unit vector for the edge direction //////
-
-Point Edge::toUnitVector() const
-{
- Point v = toVector();
- coord l = v.length();
-
- if (l == 0) TMesh::error("Edge::toUnitVector : Degenerate Edge !\n");
-
- return v/l;
-}
-
-
-/// Returns the edge normal. ////
-/// It is the average of the incident triangle normals ////
-
-Point Edge::getNormal() const
-{
- Point nor, n1, n2;
-
- if (t1 == NULL || t2 == NULL) return Point(0,0,0);
-
- n1 = t1->getNormal();
- n2 = t2->getNormal();
- nor = n1+n2;
- if (nor.length() != 0.0) nor.normalize();
- return nor;
-}
-
-////////////////////////// Edge swap ////////////////////////
-
-bool Edge::swap(const bool fast)
-{
- if (!fast && (t1 == NULL || t2 == NULL ||
- t2->oppositeVertex(this)->getEdge(t1->oppositeVertex(this)) != NULL)) return 0;
-
- Edge *e1 = t1->nextEdge(this);
- Edge *e3 = t2->nextEdge(this);
- v1->e0 = e3;
- v2->e0 = e1;
- v1 = t2->oppositeVertex(this);
- v2 = t1->oppositeVertex(this);
- t1->replaceEdge(e1, e3);
- t2->replaceEdge(e3, e1);
- t1->invert();
- t2->invert();
- e1->replaceTriangle(t1, t2);
- e3->replaceTriangle(t2, t1);
-
- return 1;
-}
-
-
-////////////////////////// Edge collapse ////////////////////////
-
-Vertex *Edge::collapseOnV1()
-{
- Edge *e;
- Node *n;
- List *ve;
- Vertex *tv;
-
- Edge *e1 = (t1 != NULL)?(t1->nextEdge(this)):(NULL);
- Edge *e2 = (t1 != NULL)?(t1->prevEdge(this)):(NULL);
- Edge *e3 = (t2 != NULL)?(t2->nextEdge(this)):(NULL);
- Edge *e4 = (t2 != NULL)?(t2->prevEdge(this)):(NULL);
- Vertex *v3 = (e1 != NULL)?(e1->oppositeVertex(v2)):(NULL);
- Vertex *v4 = (e4 != NULL)?(e4->oppositeVertex(v2)):(NULL);
- Triangle *ta1 = (e1 != NULL)?(e1->oppositeTriangle(t1)):(NULL);
- Triangle *ta2 = (e2 != NULL)?(e2->oppositeTriangle(t1)):(NULL);
- Triangle *ta3 = (e3 != NULL)?(e3->oppositeTriangle(t2)):(NULL);
- Triangle *ta4 = (e4 != NULL)?(e4->oppositeTriangle(t2)):(NULL);
-
- if (v1->isOnBoundary() && v2->isOnBoundary())
- if (!(((ta1 || ta2) && !ta3 && !ta4) || ((ta3 || ta4) && !ta1 && !ta2))) return NULL;
-
- if (ta1 != NULL && ta2 != NULL && ta1->oppositeVertex(e1) == ta2->oppositeVertex(e2))
- return NULL;
- if (ta3 != NULL && ta4 != NULL && ta3->oppositeVertex(e3) == ta4->oppositeVertex(e4))
- return NULL;
-
- if (ta1 == NULL && ta2 == NULL) v1->e0 = e3;
- else v1->e0 = e2;
-
- if (v3 != NULL) v3->e0 = e2;
- if (v4 != NULL) v4->e0 = e3;
-
- ve = v2->VE();
- FOREACHVEEDGE(ve, e, n)
- {
- tv = e->oppositeVertex(v2);
- if (tv != v3 && tv != v4 && tv->getEdge(v1) != NULL) {delete(ve); return NULL;}
- }
- FOREACHVEEDGE(ve, e, n) if (e != this) e->replaceVertex(v2, v1);
- delete(ve);
-
- if (e2 != NULL) e2->replaceTriangle(t1, ta1);
- if (e3 != NULL) e3->replaceTriangle(t2, ta4);
-
- if (ta1 != NULL) ta1->replaceEdge(e1, e2);
- if (ta4 != NULL) ta4->replaceEdge(e4, e3);
-
- v2->e0 = NULL; // v2 must be removed
- if (e4 != NULL) e4->v1 = e4->v2 = NULL; // e4 must be removed
- if (e1 != NULL) e1->v1 = e1->v2 = NULL; // e1 must be removed
- if (t1 != NULL) t1->e1 = t1->e2 = t1->e3 = NULL; // t1 must be removed
- if (t2 != NULL) t2->e1 = t2->e2 = t2->e3 = NULL; // t2 must be removed
-
- if (e2 != NULL && e2->t1 == NULL && e2->t2 == NULL)
- {
- v3->e0 = NULL;
- e2->v1 = e2->v2 = NULL;
- }
- if (e3 != NULL && e3->t1 == NULL && e3->t2 == NULL)
- {
- v4->e0 = NULL;
- e3->v1 = e3->v2 = NULL;
- }
-
- v4 = v1; // This is the remaining vertex to be returned
-
- v2 = v1 = NULL; // this edge must be removed
-
- return v4;
-}
-
-Vertex *Edge::collapseOnV2()
-{
- invert();
- return collapseOnV1();
-}
-
-bool Edge::collapse(const Point& p)
-{
- Vertex *r = collapseOnV1();
- if (r==NULL) return false;
- else r->setValue(&p); // Average the collapse
-
- return true;
-}
-
-bool Edge::collapse()
-{
- return collapse(((*v1)+(*v2))/2);
-}
-
-
-///// Merge with another boundary edge /////
-
-bool Edge::merge(Edge *e)
-{
- if (t1 && t2) return 0;
- if (e->t1 && e->t2) return 0;
- Triangle *ot = (e->t1==NULL)?(e->t2):(e->t1);
- if (ot == getBoundaryTriangle()) return 0;
- if ((t1 && e->t1) || (t2 && e->t2)) e->invert();
- Vertex *ov1 = e->v1, *ov2 = e->v2;
- List *ve1=NULL, *ve2=NULL;
- Node *n;
- Edge *f, *f2;
-
- if (ov1 != v1)
- {
- ve1 = ov1->VE();
- FOREACHVEEDGE(ve1, f, n)
- {
- f2 = f->oppositeVertex(ov1)->getEdge(v1);
- if (f2 != NULL && (!f2->isOnBoundary() || !f->isOnBoundary()))
- {delete(ve1); return 0;}
- }
- }
- if (ov2 != v2)
- {
- ve2 = ov2->VE();
- FOREACHVEEDGE(ve2, f, n)
- {
- f2 = f->oppositeVertex(ov2)->getEdge(v2);
- if (f2 != NULL && (!f2->isOnBoundary() || !f->isOnBoundary()))
- {delete(ve1); delete(ve2); return 0;}
- }
- }
-
- if (ov1 != v1)
- {
- FOREACHVEEDGE(ve1, f, n) f->replaceVertex(ov1, v1);
- delete(ve1);
- ov1->e0 = NULL;
- }
- if (ov2 != v2)
- {
- FOREACHVEEDGE(ve2, f, n) f->replaceVertex(ov2, v2);
- delete(ve2);
- ov2->e0 = NULL;
- }
- ot->replaceEdge(e, this);
- ((t1==NULL)?(t1):(t2)) = ot;
- v1->e0 = v2->e0 = this;
- e->v1 = e->v2 = NULL;
-
- return 1;
-}
-
-
-///// Angle between the normal of incident triangles /////
-
-double Edge::curvature() const
-{
- if (!t1 || !t2) return -1.0;
- return t1->getDAngle(t2);
-}
-
-
-//// Dihedral angle
-
-double Edge::dihedralAngle() const
-{
- if (!t1 || !t2) return -1.0;
- Point nor1 = t1->getNormal();
- Point nor2 = t2->getNormal();
- if (nor1.isNull() || nor2.isNull()) return -1.0;
- double c = nor1.getAngle(&nor2);
-
- Vertex *ov = t2->oppositeVertex(this);
- if (((*ov)*nor1) - ((*v1)*nor1) < 0) return -(c - M_PI);
-
- return c+M_PI;
-}
-
-//// Min Angle among those of the two incident triangles ////
-
-double Edge::delaunayMinAngle() const
-{
- if (t1==NULL || t2==NULL) return 2*M_PI;
- if (squaredLength()==0) return 0;
- if (t1->nextEdge(this)->squaredLength() == 0) return 0;
- if (t1->prevEdge(this)->squaredLength() == 0) return 0;
- double a1 = t1->getAngle(v1);
- double a2 = t1->getAngle(v2);
- double a3 = t1->getAngle(t1->oppositeVertex(this));
- if (t2->nextEdge(this)->length()==0) return 0;
- if (t2->prevEdge(this)->length()==0) return 0;
- double a4 = t2->getAngle(v1);
- double a5 = t2->getAngle(v2);
- double a6 = t2->getAngle(t2->oppositeVertex(this));
-
- if (a1+a4 >= M_PI || a2+a5 >= M_PI) return 3*M_PI;
- return MIN(a1,(MIN(a2,(MIN(a3,(MIN(a4,(MIN(a5,a6)))))))));
-}
-
-
-// If edge is stitchable, merge it with its copy
-
-bool Edge::stitch()
-{
- // This function seems to be insufficient to stitch in every case !
- if (!isOnBoundary()) return 0;
-
- Triangle *t, *t0 = (t1 != NULL) ? (t1) : (t2);
- Vertex *v0;
- Edge *e1;
-
- for (v0 = v1; v0 != NULL; v0 = ((v0 == v1) ? (v2) : (NULL)))
- {
- e1 = this;
- t = t0;
- while (t != NULL)
- {
- e1 = t->nextEdge(e1); if (!e1->hasVertex(v0)) e1 = t->nextEdge(e1);
- t = e1->oppositeTriangle(t);
- }
- if (e1->oppositeVertex(v0) == oppositeVertex(v0))
- {
- t = (e1->t1 != NULL) ? (e1->t1) : (e1->t2);
- t->replaceEdge(e1, this);
- v1->e0 = v2->e0 = this;
- e1->v1 = e1->v2 = NULL;
- replaceTriangle(NULL, t);
- return 1;
- }
- }
-
- return 0;
-}
-
-bool Edge::overlaps() const
-{
- if (t1 == NULL || t2 == NULL) return false;
-
- Vertex *ov = t2->oppositeVertex(this);
- if (ov->exactOrientation(t1->v1(), t1->v2(), t1->v3()) == 0 && ov->exactSameSideOnPlane(t1->oppositeVertex(this), v1, v2)) return true;
- else return false;
-}
-
-bool Edge::intersects(const Triangle *t) const
-{
- if (t->hasEdge(this)) return false;
-
- Vertex *cv = (t->hasVertex(v1)) ? (v1) : ((t->hasVertex(v2)) ? (v2) : (NULL));
- if (cv) // If they share a vertex, intersection occurs if t's opposite edge intersect this edge
- {
- Edge *oe = t->oppositeEdge(cv);
- if (Point::pointInTriangle(oppositeVertex(cv), cv, oe->v1, oe->v2)) return true;
- else return (Point::segmentsIntersect(oe->v1, oe->v2, v1, v2));
- }
- else return Point::segmentIntersectsTriangle(v1, v2, t->v1(), t->v2(), t->v3());
-}
-
-coord Edge::getConvexity() const
-{
- if (t1 == NULL || t2 == NULL) return DBL_MAX;
- else return (t1->oppositeVertex(this)->exactOrientation(t2->v3(), t2->v2(), t2->v1()));
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/TMesh/io.cpp b/src/mesh_fix/src/TMesh/io.cpp
deleted file mode 100644
index 1dda5ff41..000000000
--- a/src/mesh_fix/src/TMesh/io.cpp
+++ /dev/null
@@ -1,1623 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "tmesh.h"
-#include
-#include
-#include
-#include
-#include
-
-namespace T_MESH
-{
-
-#define VRML1_HEADER "#VRML V1.0 ascii"
-#define VRML1_HSIZE 16
-#define VRML2_HEADER "#VRML V2.0 utf8"
-#define VRML2_HSIZE 15
-#define OFF_HEADER "OFF"
-#define OFF_HSIZE 3
-#define EFF_HEADER "EFF"
-#define EFF_HSIZE 3
-#define PLY_HEADER "ply"
-#define PLY_HSIZE 3
-#define IV_HEADER "#Inventor V2.1 ascii"
-#define IV_HSIZE 20
-
-#define PLY_FORMAT_ASCII 0
-#define PLY_FORMAT_BIN_L 1
-#define PLY_FORMAT_BIN_B 2
-
-#define TVI1(a) (TMESH_TO_INT(((Triangle *)a->data)->v1()->x))
-#define TVI2(a) (TMESH_TO_INT(((Triangle *)a->data)->v2()->x))
-#define TVI3(a) (TMESH_TO_INT(((Triangle *)a->data)->v3()->x))
-
-inline void PRINT_HEADING_COMMENT(FILE *f)
-{
- if (TMesh::app_name != NULL)
- {
- fprintf(f, "# File created by %s",TMesh::app_name);
- if (TMesh::app_version != NULL)
- {
- fprintf(f, " v%s",TMesh::app_version);
- if (TMesh::app_year != NULL) fprintf(f, " (%s)",TMesh::app_year);
- }
- fprintf(f, "\n");
- if (TMesh::app_url != NULL) fprintf(f, "# %s\n",TMesh::app_url);
- }
- fprintf(f, "\n");
-}
-
-inline void PRINT_PLY_COMMENT(FILE *f)
-{
- if (TMesh::app_name != NULL)
- {
- fprintf(f, "comment File created by %s",TMesh::app_name);
- if (TMesh::app_version != NULL)
- {
- fprintf(f, " v%s",TMesh::app_version);
- if (TMesh::app_year != NULL) fprintf(f, " (%s)",TMesh::app_year);
- }
- fprintf(f, "\n");
- if (TMesh::app_url != NULL) fprintf(f, "comment %s\n",TMesh::app_url);
- }
-}
-
-/// Returns TRUE if the two strings are equal in a case-insensitive sense /////
-
-inline bool sameString(const char *a, const char *b)
-{
- int i = 0;
- while (a[i] != '\0' && b[i] != '\0')
- {
- if (tolower(a[i]) != tolower(b[i])) return false;
- i++;
- }
-
- return (a[i] == '\0' && b[i] == '\0');
-}
-
-
-
-// Swap endian-ness for four-byte elements
-
-inline void endian_swap_long(unsigned char *p)
-{
- unsigned char b0,b1,b2,b3;
-
- b0 = *p; b1 = *(p+1); b2 = *(p+2); b3 = *(p+3);
- *p = b3; *(p+1) = b2; *(p+2) = b1; *(p+3) = b0;
-}
-
-
-// Read one line (max 1024 chars) and exit if EOF
-
-char *readLineFromFile(FILE *in, bool exit_on_eof = 1)
-{
-#define MAX_READLINE_CHARS 1024
- static char line[MAX_READLINE_CHARS];
- int i=0;
- char c;
-
- while ((c = fgetc(in)) != '\n' && i<(MAX_READLINE_CHARS-1))
- if (c==EOF)
- {
- if (exit_on_eof) TMesh::error("\nUnexpected end of file!\n");
- else return NULL;
- }
- else if (c != '\r') line[i++] = c;
- line[i] = '\0';
-
- if (i==MAX_READLINE_CHARS-1)
- TMesh::warning("readLineFromFile: Line is too long. Truncated !\n");
-
- return line;
-}
-
-
-// Looks for a keyword 'kw' in an ASCII file referenced through 'fp'.
-// The file pointer is set to the byte right after the first keyword matched.
-// Return 1 on success (keyword match), 0 otherwise.
-
-
-bool seek_keyword(FILE *fp, const char *kw)
-{
- static char s[256];
- s[0]='\0';
- do fscanf(fp,"%255s",s); while (strcmp(s,kw) && !feof(fp));
- if (feof(fp)) return 0;
- return 1;
-}
-
-
-inline void skipCommentAndBlankLines(FILE *fp)
-{
- long pos0;
- char *line, s[2];
- do {pos0 = ftell(fp); line = readLineFromFile(fp);} while (line[0] == '#' || line[0] == '\0' || !sscanf(line,"%1s",s));
- fseek(fp, pos0, SEEK_SET);
-}
-
-
-////////////////////// Dispatch the load ///////////////////////////
-
-int Basic_TMesh::load(const char *fname, const bool doupdate)
-{
- FILE *fp;
- char header[256];
- size_t as;
- int err = IO_UNKNOWN;
-
- if ((fp = fopen(fname,"r")) == NULL) return IO_CANTOPEN;
- as = fread(header, 1, 256, fp);
- fclose(fp);
-
- if (as >= VRML1_HSIZE && !strncmp(header, VRML1_HEADER, VRML1_HSIZE)) err = loadVRML1(fname);
- else if (as >= VRML2_HSIZE && !strncmp(header, VRML2_HEADER, VRML2_HSIZE)) err = loadVRML2(fname);
- else if (as >= OFF_HSIZE && !strncmp(header, OFF_HEADER, OFF_HSIZE)) err = loadOFF(fname);
- else if (as >= EFF_HSIZE && !strncmp(header, EFF_HEADER, EFF_HSIZE)) err = loadEFF(fname);
- else if (as >= PLY_HSIZE && !strncmp(header, PLY_HEADER, PLY_HSIZE)) err = loadPLY(fname);
- else if (as >= IV_HSIZE && !strncmp(header, IV_HEADER, IV_HSIZE)) err = loadIV(fname);
- else if (sameString((char *)(fname+strlen(fname)-4), (char *)".obj")) err = loadOBJ(fname);
- else if (sameString((char *)(fname+strlen(fname)-4), (char *)".tri")) err = loadVerTri(fname);
- else if (sameString((char *)(fname+strlen(fname)-4), (char *)".stl")) err = loadSTL(fname);
-
- if (!err && doupdate) eulerUpdate();
- if (!err) TMesh::setFilename(fname);
-
- return err;
-}
-
-int Basic_TMesh::append(const char *filename, const bool doupdate)
-{
- if (!T.numels()) return load(filename, doupdate);
- Basic_TMesh ntin;
- int err = ntin.load(filename, 0);
-
- if (err) return err;
-
- V.joinTailList(&(ntin.V));
- E.joinTailList(&(ntin.E));
- T.joinTailList(&(ntin.T));
- if (doupdate) eulerUpdate();
- else d_boundaries = d_handles = d_shells = 1;
-
- return 0;
-}
-
-int Basic_TMesh::save(const char *fname, bool back_approx)
-{
- char nfname[4096];
- strcpy(nfname, fname);
-
- int rv;
- size_t i=strlen(fname)-1;
- while (i>0 && fname[i] != '.') i--;
-
- if (i==0) {strcat(nfname,".wrl"); i=strlen(fname);}
-
- if (sameString(nfname+i, ".wrl")) rv = saveVRML1(nfname);
- else if (sameString(nfname+i, ".iv")) rv = saveIV(nfname);
- else if (sameString(nfname + i, ".off")) rv = saveOFF(nfname);
- else if (sameString(nfname + i, ".eff")) rv = saveEFF(nfname);
- else if (sameString(nfname + i, ".ply")) rv = savePLY(nfname);
- else if (sameString(nfname+i, ".obj")) rv = saveOBJ(nfname);
- else if (sameString(nfname+i, ".stl")) rv = saveSTL(nfname);
- else if (sameString(nfname+i, ".tri")) {nfname[i]='\0'; rv = saveVerTri(nfname);}
- else
- {
- TMesh::warning("Unknown extension '%s'.\n",nfname+i);
- TMesh::warning("I did not save anything.\n");
- TMesh::warning("Recognized extensions are:");
- TMesh::warning(".wrl (ASCII VRML 1.0)\n");
- TMesh::warning(".iv (Open Inventor 2.1)\n");
- TMesh::warning(".off (Object File Format)\n");
- TMesh::warning(".eff (Exact File Format)\n");
- TMesh::warning(".obj (Wavefront/Java3D)\n");
- TMesh::warning(".stl (Stereolithography)\n");
- TMesh::warning(".ply (Ascii PLY 1.0 Format)\n");
- TMesh::warning(".tri (IMATI ver-tri File Format)\n");
- return 0;
- }
-
- if (!rv && back_approx) coordBackApproximation();
-
- return rv;
-}
-
-
-// This part is common to all the loaders
-
-Triangle * Basic_TMesh::CreateTriangleFromVertices(ExtVertex *vari1, ExtVertex *vari2, ExtVertex *vari3)
-{
- Edge *e1, *e2, *e3;
- Triangle *t = NULL;
-
- e1 = CreateEdge(vari1,vari2); if (e1->t1 != NULL && e1->t2 != NULL) MARK_BIT(e1,5);
- e2 = CreateEdge(vari2,vari3); if (e2->t1 != NULL && e2->t2 != NULL) MARK_BIT(e2,5);
- e3 = CreateEdge(vari3,vari1); if (e3->t1 != NULL && e3->t2 != NULL) MARK_BIT(e3,5);
- if (IS_BIT(e1,5)) {e1 = CreateEdge(vari1,vari2,0); MARK_BIT(e1,5);}
- if (IS_BIT(e2,5)) {e2 = CreateEdge(vari2,vari3,0); MARK_BIT(e2,5);}
- if (IS_BIT(e3,5)) {e3 = CreateEdge(vari3,vari1,0); MARK_BIT(e3,5);}
-
- if ((t=CreateUnorientedTriangle(e1,e2,e3)) == NULL)
- {
- if (e3->t1 == NULL && e3->t2 == NULL)
- {
- E.freeNode(e3);
- vari3->VE.removeNode(e3); vari1->VE.removeNode(e3);
- if (vari3->v->e0 == e3) vari3->v->e0 = NULL;
- if (vari1->v->e0 == e3) vari1->v->e0 = NULL;
- }
- if (e2->t1 == NULL && e2->t2 == NULL)
- {
- E.freeNode(e2);
- vari2->VE.removeNode(e2); vari3->VE.removeNode(e2);
- if (vari2->v->e0 == e2) vari2->v->e0 = NULL;
- if (vari3->v->e0 == e2) vari3->v->e0 = NULL;
- }
- if (e1->t1 == NULL && e1->t2 == NULL)
- {
- E.freeNode(e1);
- vari1->VE.removeNode(e1); vari2->VE.removeNode(e1);
- if (vari1->v->e0 == e1) vari1->v->e0 = NULL;
- if (vari2->v->e0 == e1) vari2->v->e0 = NULL;
- }
- }
-
- return t;
-}
-
-
-// This part is common to all the loaders
-
-Triangle * Basic_TMesh::CreateIndexedTriangle(ExtVertex **var, int i1, int i2, int i3)
-{
- return CreateTriangleFromVertices(var[i1], var[i2], var[i3]);
-}
-
-
-// This part is common to all the loaders
-
-void Basic_TMesh::closeLoadingSession(FILE *fp, int loaded_faces, ExtVertex **var, bool triangulate)
-{
- int i, nv = V.numels();
-
- fclose(fp);
-
- if (var != NULL)
- {
- for (i=0; ix)); sscanf(floatver, "%f", &x); v->x = x;
- sprintf(floatver, "%f", TMESH_TO_FLOAT(v->y)); sscanf(floatver, "%f", &x); v->y = x;
- sprintf(floatver, "%f", TMESH_TO_FLOAT(v->z)); sscanf(floatver, "%f", &x); v->z = x;
- }
-}
-
-////////////////////// Loads VRML 1.0 format ///////////////////////////
-
-int Basic_TMesh::loadVRML1(const char *fname)
-{
- FILE *fp;
- Node *n;
- float x,y,z;
- int i,i1,i2,i3,i4,nv=0,triangulate=0;
- Vertex *v;
-
- coord cx;
-
- if ((fp = fopen(fname,"r")) == NULL) return IO_CANTOPEN;
-
- if (!seek_keyword(fp, "point")) {closeLoadingSession(fp, 0, NULL, 0); return IO_FORMAT;}
- if (!seek_keyword(fp, "[")) {closeLoadingSession(fp, 0, NULL, 0); return IO_FORMAT;}
-
- while (fscanf(fp, "%f %f %f,", &x, &y, &z) == 3) { V.appendTail(newVertex(x, y, z)); cx = coord(x); /*printf("%f %f\n", x, cx.toFloat());*/ }
- nv = V.numels();
- ExtVertex **var = (ExtVertex **)malloc(sizeof(ExtVertex *)*nv);
- i = 0; FOREACHVERTEX(v, n) var[i++] = new ExtVertex(v);
-
- if (!seek_keyword(fp, "coordIndex")) {closeLoadingSession(fp, 0, var, 0); return IO_FORMAT;}
- if (!seek_keyword(fp, "[")) {closeLoadingSession(fp, 0, var, 0); return IO_FORMAT;}
-
- i=0; TMesh::begin_progress();
- while (fscanf(fp,"%d, %d, %d,",&i1,&i2,&i3) == 3)
- {
- if (((i++)%1000) == 0) TMesh::report_progress("Loading ..%d%%",(i*100)/(nv*2));
- if (i1<0 || i2<0 || i3<0 || i1>(nv-1) || i2>(nv-1) || i3>(nv-1))
- TMesh::error("\nloadVRML1: Invalid indices %d %d %d!\n",i1,i2,i3);
- do
- {
- if (i1 == i2 || i2 == i3 || i3 == i1) TMesh::warning("\nloadVRML1: Coincident indexes at face %d! Skipping.\n",i);
- else if (!CreateIndexedTriangle(var, i1, i2, i3)) TMesh::warning("\nloadVRML1: This shouldn't happen!!! Skipping triangle.\n");
- if (fscanf(fp,"%d,",&i4) != 1) TMesh::error("loadVRML1: Unexpected end of file at face %d!\n",i);
- i2=i3; i3=i4;
- if (i4 != -1) triangulate=1;
- } while (i4 != -1);
- }
- TMesh::end_progress();
-
- closeLoadingSession(fp, i, var, (triangulate != 0));
- TMesh::setFilename(fname);
-
- return 0;
-}
-
-
-int Basic_TMesh::loadIV(const char *fname)
-{
- return loadVRML1(fname);
-}
-
-
-////////////////////// Loads OFF format ///////////////////////////
-
-int Basic_TMesh::loadOFF(const char *fname)
-{
- FILE *fp;
- Node *n;
- char s[256], *line;
- float x,y,z;
- int i,j,i1,i2,i3,i4,nv,nt,ne,triangulate=0;
- Vertex *v;
-
- if ((fp = fopen(fname,"rb")) == NULL) return IO_CANTOPEN;
-
- fscanf(fp,"%255s",s);
- if (strcmp(s,"OFF") || feof(fp)) return IO_FORMAT;
- do {line = readLineFromFile(fp);} while (line[0] == '#' || line[0] == '\0' || !sscanf(line,"%256s",s));
- if (sscanf(line,"%d %d %d",&nv,&nt,&ne) < 3) return IO_FORMAT;
- if (nv < 3) TMesh::error("\nloadOFF: Sorry. Can't load objects with less than 3 vertices.\n");
- if (nt < 1) TMesh::error("\nloadOFF: Sorry. Can't load objects with no faces.\n");
-
- skipCommentAndBlankLines(fp);
-
- for (i = 0; i(nv-1) || i2>(nv-1) || i3>(nv-1)) TMesh::error("\nloadOFF: Invalid index at face %d!\n",i);
- for (j=3; j<=i4; j++)
- {
- if (i1 == i2 || i2 == i3 || i3 == i1) TMesh::warning("\nloadOFF: Coincident indexes at triangle %d! Skipping.\n",i);
- else if (!CreateIndexedTriangle(var, i1, i2, i3)) TMesh::warning("\nloadOFF: This shouldn't happen!!! Skipping triangle.\n");
- i2 = i3;
- if (j> s;
- if (is.eof() || is.fail() || strcmp(s, "EFF")) return IO_FORMAT;
- is >> nv; if (is.eof() || is.fail()) return IO_FORMAT;
- is >> nt; if (is.eof() || is.fail()) return IO_FORMAT;
- if (nv < 3) TMesh::error("\nloadOFF: Sorry. Can't load objects with less than 3 vertices.\n");
- if (nt < 1) TMesh::error("\nloadOFF: Sorry. Can't load objects with no faces.\n");
-
- TMesh::useRationals(true);
- for (i = 0; i < nv; i++)
- {
- is >> x >> y >> z;
- if (is.eof() || is.fail()) TMesh::error("\nloadEFF: Couldn't read coordinates for vertex # %d\n", i);
- V.appendTail(newVertex(x, y, z));
- }
-
- ExtVertex **var = (ExtVertex **)malloc(sizeof(ExtVertex *)*nv);
- i = 0; FOREACHVERTEX(v, n) var[i++] = new ExtVertex(v);
-
- TMesh::begin_progress();
- for (i = 0; i> i1 >> i2 >> i3;
- if (is.eof() || is.fail()) TMesh::error("\nloadEFF: Couldn't read indexes for face # %d\n", i);
- else
- {
- if ((i % 1000) == 0) TMesh::report_progress("Loading ..%d%%", (i * 100) / (nv * 2));
- if (i1<0 || i2<0 || i3<0 || i1>(nv - 1) || i2>(nv - 1) || i3>(nv - 1)) TMesh::error("\nloadEFF: Invalid index at face %d!\n", i);
- if (i1 == i2 || i2 == i3 || i3 == i1) TMesh::warning("\nloadEFF: Coincident indexes at triangle %d! Skipping.\n", i);
- else if (!CreateIndexedTriangle(var, i1, i2, i3)) TMesh::warning("\nloadEFF: This shouldn't happen!!! Skipping triangle.\n");
- }
- }
-
- TMesh::end_progress();
-
- is.close();
-
- for (i = 0; i(nv-1) || i2>(nv-1) || i3>(nv-1)) TMesh::error("\nloadVRML2: Invalid index at face %d!\n",i);
- do
- {
- if (i1 == i2 || i2 == i3 || i3 == i1) TMesh::warning("\nloadVRML2: Coincident indexes at triangle %d! Skipping.\n",i);
- else if (!CreateIndexedTriangle(var, i1, i2, i3)) TMesh::warning("\nloadVRML2: This shouldn't happen!!! Skipping triangle.\n");
- if (fscanf(fp,"%d,",&i4) != 1) TMesh::error("loadVRML2: Unexpected end of file at triangle %d!\n",i);
- i2=i3; i3=i4;
- if (i4 != -1) triangulate=1;
- } while (i4 != -1);
- }
- TMesh::end_progress();
-
- closeLoadingSession(fp, i, var, (triangulate != 0));
- TMesh::setFilename(fname);
-
- return 0;
-}
-
-
-////////////////////// Loads Ver-Tri format ////////////////////
-
-int Basic_TMesh::loadVerTri(const char *fname)
-{
- FILE *fpv, *fpt;
- int numvers, numtris, i, i1, i2, i3, a1, a2, a3;
- float x,y,z;
- char vername[256], triname[256];
- Node *n;
- Vertex *v;
-
- if (!sameString((char *)(fname+strlen(fname)-4), (char *)".tri")) return IO_UNKNOWN;
-
- strcpy(triname,fname);
- strcpy(vername,fname); vername[strlen(vername)-4]='\0';
- strcat(vername,".ver");
-
- if ((fpv = fopen(vername,"r")) == NULL)
- {
- fprintf(stderr,"Can't open '%s' for input !\n",vername);
- return 1;
- }
- if ((fpt = fopen(triname,"r")) == NULL)
- {
- fclose(fpv);
- fprintf(stderr,"Can't open '%s' for input !\n",triname);
- return 1;
- }
-
- if (!fscanf(fpv,"%d\n",&numvers) || numvers < 3) {fclose(fpv); fclose(fpt); return IO_FORMAT;}
- if (!fscanf(fpt,"%d\n",&numtris) || numtris < 1) {fclose(fpv); fclose(fpt); return IO_FORMAT;}
-
- for (i=0; i (numvers) || i2 > (numvers) || i3 > (numvers)) TMesh::error("\nloadVerTri: Index out of bounds at triangle %d!\n",i);
- else if (i1 == i2 || i2 == i3 || i3 == i1) TMesh::warning("\nloadVerTri: Coincident indexes at triangle %d! Skipping.\n",i);
- else if (!CreateIndexedTriangle(var, i1-1, i2-1, i3-1)) TMesh::warning("\nloadVerTri: This shouldn't happen!!! Skipping triangle.\n");
- }
- else TMesh::error("loadVerTri: Couldn't read %dth triangle !\n",i+1);
-
- TMesh::end_progress();
-
- closeLoadingSession(fpt, T.numels(), var, 0);
- TMesh::setFilename(fname);
-
- return 0;
-}
-
-
-////////////////////// Saves IV 2.1 format ////////////////////
-
-int Basic_TMesh::saveIV(const char *fname)
-{
- FILE *fp;
- int i;
- char triname[256];
- Node *n;
- coord *ocds;
- Vertex *v;
-
- strcpy(triname,fname);
-
- if ((fp = fopen(triname,"w")) == NULL)
- {
- TMesh::warning("Can't open '%s' for output !\n",triname);
- return 1;
- }
-
- fprintf(fp,"#Inventor V2.1 ascii\n\n");
- PRINT_HEADING_COMMENT(fp);
- fprintf(fp,"Separator {\n");
- fprintf(fp," Coordinate3 {\n point [\n");
-
- FOREACHVERTEX(v, n) fprintf(fp, " %f %f %f,\n", TMESH_TO_FLOAT(v->x), TMESH_TO_FLOAT(v->y), TMESH_TO_FLOAT(v->z));
-
- fprintf(fp," ]\n }\n");
- fprintf(fp," IndexedFaceSet {\n coordIndex [\n");
-
- ocds = new coord[V.numels()];
- i=0; FOREACHVERTEX(v, n) ocds[i++] = v->x;
- i=0; FOREACHVERTEX(v, n) v->x = i++;
-
- FOREACHNODE(T, n) fprintf(fp," %d, %d, %d, -1,\n",TVI1(n),TVI2(n),TVI3(n));
-
- fprintf(fp," ]\n }\n");
- fprintf(fp,"}\n");
-
- fclose(fp);
- i=0; FOREACHVERTEX(v, n) v->x = ocds[i++];
- delete[] ocds;
-
- return 0;
-}
-
-
-////////////////////// Saves VRML 1.0 format ////////////////////
-
-int Basic_TMesh::saveVRML1(const char *fname, const int mode)
-{
- FILE *fp;
- int i;
- unsigned int pkc;
- char triname[256];
- Node *n;
- Vertex *v;
- Triangle *t;
- coord *ocds;
-
- strcpy(triname,fname);
-
- if ((fp = fopen(triname,"w")) == NULL)
- {
- TMesh::warning("Can't open '%s' for output !\n",triname);
- return 1;
- }
-
- fprintf(fp,"#VRML V1.0 ascii\n\n");
- PRINT_HEADING_COMMENT(fp);
- fprintf(fp,"Separator {\n");
- fprintf(fp," Coordinate3 {\n point [\n");
-
- FOREACHVERTEX(v, n) fprintf(fp, " %f %f %f,\n", TMESH_TO_FLOAT(v->x), TMESH_TO_FLOAT(v->y), TMESH_TO_FLOAT(v->z));
-
- fprintf(fp," ]\n }\n");
-
- ocds = new coord[V.numels()];
- i=0; FOREACHVERTEX(v, n) {ocds[i] = v->x; v->x = i++;}
-
- switch (mode)
- {
- case IO_CSAVE_OVERALL:
- fprintf(fp,"Material {\n diffuseColor 0.6 0.6 0.6\n}\n");
- break;
- case IO_CSAVE_PERFACE:
- fprintf(fp,"Material {\n diffuseColor [\n");
- FOREACHTRIANGLE(t, n)
- {
- pkc = ((intWrapper*)(t->info))->operator int();
- fprintf(fp," %f %f %f,\n",((pkc>>24)&0x000000ff)/255.0,((pkc>>16)&0x000000ff)/255.0,((pkc>>8)&0x000000ff)/255.0);
- }
- fprintf(fp," ]\n}\nMaterialBinding {\n value PER_FACE_INDEXED\n}\n");
- break;
- case IO_CSAVE_PERVERTEX:
- fprintf(fp,"Material {\n diffuseColor [\n");
- FOREACHVERTEX(v, n)
- {
- pkc = ((intWrapper*)(v->info))->operator int();
- fprintf(fp," %f %f %f,\n",((pkc>>24)&0x000000ff)/255.0,((pkc>>16)&0x000000ff)/255.0,((pkc>>8)&0x000000ff)/255.0);
- }
- fprintf(fp," ]\n}\nMaterialBinding {\n value PER_VERTEX_INDEXED\n}\n");
- break;
- case IO_CSAVE_PERFACE_INDEXED:
- fprintf(fp,"Material {\n diffuseColor [\n");
- fprintf(fp,"1.0 1.0 1.0,\n1.0 0.0 0.0,\n0.0 1.0 0.0,\n0.0 0.0 1.0,\n 0.8 0.8 0.0\n");
- fprintf(fp," ]\n}\nMaterialBinding {\n value PER_FACE_INDEXED\n}\n");
- break;
- case IO_CSAVE_PERVERTEX_INDEXED:
- fprintf(fp,"Material {\n diffuseColor [\n");
- fprintf(fp,"1.0 1.0 1.0,\n1.0 0.0 0.0,\n0.0 1.0 0.0,\n0.0 0.0 1.0,\n 0.8 0.8 0.0\n");
- fprintf(fp," ]\n}\nMaterialBinding {\n value PER_VERTEX_INDEXED\n}\n");
- break;
- default: TMesh::error("Basic_TMesh::saveVRML1. Unknown mode %d\n",mode);
- }
-
- fprintf(fp," IndexedFaceSet {\n coordIndex [\n");
-
- FOREACHTRIANGLE(t, n)
- fprintf(fp, " %d, %d, %d, -1,\n", TMESH_TO_INT(t->v1()->x), TMESH_TO_INT(t->v2()->x), TMESH_TO_INT(t->v3()->x));
-
- fprintf(fp," ]\n");
-
- if (mode != IO_CSAVE_OVERALL)
- {
- fprintf(fp," materialIndex [\n");
- switch (mode)
- {
- case IO_CSAVE_PERFACE_INDEXED:
- FOREACHTRIANGLE(t, n) fprintf(fp," %d,\n",t->mask);
- break;
- case IO_CSAVE_PERVERTEX_INDEXED:
- FOREACHTRIANGLE(t, n) fprintf(fp," %d, %d, %d, -1,\n",t->v1()->mask,t->v2()->mask,t->v3()->mask);
- break;
- case IO_CSAVE_PERFACE:
- i=0; FOREACHTRIANGLE(t, n) fprintf(fp," %d,\n",i++);
- break;
- case IO_CSAVE_PERVERTEX:
- FOREACHTRIANGLE(t, n) fprintf(fp, " %d, %d, %d, -1,\n", TMESH_TO_INT(t->v1()->x), TMESH_TO_INT(t->v2()->x), TMESH_TO_INT(t->v3()->x));
- break;
- }
- fprintf(fp," ]\n");
- }
-
- fprintf(fp," }\n}\n");
-
- fclose(fp);
- i=0; FOREACHVERTEX(v, n) v->x = ocds[i++];
- delete[] ocds;
-
- return 0;
-}
-
-
-////////////////////// Saves OFF format ///////////////////////////
-
-int Basic_TMesh::saveOFF(const char *fname)
-{
- FILE *fp;
- int i;
- char triname[256];
- Node *n;
- coord *ocds;
- Vertex *v;
-
- strcpy(triname,fname);
-
- if ((fp = fopen(triname,"w")) == NULL)
- {
- TMesh::warning("Can't open '%s' for output !\n",triname);
- return 1;
- }
-
- fprintf(fp,"OFF\n");
- PRINT_HEADING_COMMENT(fp);
- fprintf(fp,"%d %d 0\n",V.numels(),T.numels());
-
- FOREACHVERTEX(v, n) fprintf(fp, "%f %f %f\n", TMESH_TO_FLOAT(v->x), TMESH_TO_FLOAT(v->y), TMESH_TO_FLOAT(v->z));
-
- ocds = new coord[V.numels()];
- i=0; FOREACHVERTEX(v, n) ocds[i++] = v->x;
- i=0; FOREACHVERTEX(v, n) v->x = i++;
-
- FOREACHNODE(T, n) fprintf(fp,"3 %d %d %d\n",TVI1(n),TVI2(n),TVI3(n));
-
- fclose(fp);
- i=0; FOREACHVERTEX(v, n) v->x = ocds[i++];
- delete[] ocds;
-
- return 0;
-}
-
-
-////////////////////// Saves Ver-Tri format ////////////////////
-
-//#define SAVE_INFO
-int Basic_TMesh::saveVerTri(const char *fname)
-{
-#ifdef SAVE_INFO
- TMesh::warning("saveVerTri: Assuming that the vertex info field is allocated!\n");
- FILE *fpj;
- char jkkname[256];
-#endif
- FILE *fpv, *fpt;
- int i, i1, i2, i3, a1, a2, a3;
- char vername[256], triname[256];
- Node *n;
- Vertex *v;
- Triangle *t, *t1, *t2, *t3;
- coord *ocds;
-
- strcpy(triname,fname);
- strcpy(vername,fname);
- strcat(triname,".tri");
- strcat(vername,".ver");
-
-#ifdef SAVE_INFO
- strcpy(jkkname,fname);
- strcat(jkkname,".jkk");
-#endif
-
- if ((fpv = fopen(vername,"w")) == NULL)
- {
- fprintf(stderr,"Can't open '%s' for output !\n",vername);
- return 1;
- }
- if ((fpt = fopen(triname,"w")) == NULL)
- {
- fclose(fpv);
- fprintf(stderr,"Can't open '%s' for output !\n",triname);
- return 1;
- }
-#ifdef SAVE_INFO
- if ((fpj = fopen(jkkname,"w")) == NULL)
- {
- fclose(fpv); fclose(fpt);
- fprintf(stderr,"Can't open '%s' for output !\n",jkkname);
- return 1;
- }
-#endif
-
- fprintf(fpv,"%d\n",V.numels());
- FOREACHVERTEX(v, n)
- {
- fprintf(fpv, "%f %f %f\n", TMESH_TO_FLOAT(v->x), TMESH_TO_FLOAT(v->y), TMESH_TO_FLOAT(v->z));
- }
- fclose(fpv);
-
-#ifdef SAVE_INFO
- for (n=V.tail; n != NULL; n=n->prev)
- {
- v = ((Vertex *)n->data);
- fprintf(fpj,"%f\n",(*((double *)(v->info))));
- }
- fclose(fpj);
-#endif
-
- ocds = new coord[V.numels()];
- i=0; FOREACHVERTEX(v, n) ocds[i++] = v->x;
- i=0; FOREACHVERTEX(v, n) v->x = ++i;
- i=0; FOREACHTRIANGLE(t, n) {i++; t->info = new intWrapper(i);}
-
- fprintf(fpt,"%d\n",T.numels());
- FOREACHTRIANGLE(t, n)
- {
- i1 = TMESH_TO_INT(t->v1()->x); i2 = TMESH_TO_INT(t->v2()->x); i3 = TMESH_TO_INT(t->v3()->x);
- t1 = t->t1(); t2 = t->t2(); t3 = t->t3();
- a1 = (t1)?((long int)(t1->info)):(0); a2 = (t2)?((long int)(t2->info)):(0); a3 = (t3)?((long int)(t3->info)):(0);
- fprintf(fpt,"%d %d %d %d %d %d\n",i1, i2, i3, a1, a2, a3);
- }
- fclose(fpt);
-
- i=0; FOREACHVERTEX(v, n) v->x = ocds[i++];
- delete[] ocds;
-
- return 0;
-}
-
-
-// Implements the cutting and stitching procedure to convert to manifold mesh //
-// Assumes that singular edges to be cut and stitched are marked as BIT5. //
-
-bool Basic_TMesh::pinch(Edge *e1, bool with_common_vertex)
-{
- List *ee = (List *)e1->info;
- if (ee == NULL) return false;
- Node *n = NULL;
- Edge *e2=NULL;
- List *ve;
-
- if (with_common_vertex)
- {
- e1->v1->e0 = e1; ve = e1->v1->VE();
- FOREACHVEEDGE(ve, e2, n) if (e2 != e1 && e2->isOnBoundary() && (*(e2->oppositeVertex(e1->v1))) == (*(e1->v2)) && e1->merge(e2)) break;
- delete ve;
- if (n == NULL)
- {
- e1->v2->e0 = e1; ve = e1->v2->VE();
- FOREACHVEEDGE(ve, e2, n) if (e2 != e1 && e2->isOnBoundary() && (*(e2->oppositeVertex(e1->v2))) == (*(e1->v1)) && e1->merge(e2)) break;
- delete ve;
- }
- }
- else //if (ee->numels()==2)
- {
- if (e1->t1 != NULL)
- {
- FOREACHVEEDGE(ee, e2, n) if (e2 != e1 && (((*(e2->v1)) == (*(e1->v1)) && e2->t2 != NULL) || ((*(e2->v1)) == (*(e1->v2)) && e2->t1 != NULL)) && e1->merge(e2)) break;
- }
- else
- {
- FOREACHVEEDGE(ee, e2, n) if (e2 != e1 && (((*(e2->v1)) == (*(e1->v1)) && e2->t1 != NULL) || ((*(e2->v1)) == (*(e1->v2)) && e2->t2 != NULL)) && e1->merge(e2)) break;
- }
- }
- if (n == NULL) return false;
-
- ee->removeNode(e1); ee->removeNode(e2); e1->info = e2->info = NULL;
- if (ee->numels() == 0) delete ee;
-
- Edge *e, *e_1 = NULL, *e_2 = NULL;
- ve = e1->v1->VE();
- for (n = ve->head(); n != NULL; n = n->next()) if ((e = (Edge *)n->data)->info != NULL) { e_1 = e; break; }
- for (n = ve->tail(); n != NULL; n = n->prev()) if ((e = (Edge *)n->data)->info != NULL)
- {
- if ((*(e->oppositeVertex(e1->v1))) != (*(e_1->oppositeVertex(e1->v1)))) e_1 = NULL;
- break;
- }
- delete ve;
-
- ve = e1->v2->VE();
- for (n = ve->head(); n != NULL; n = n->next()) if ((e = (Edge *)n->data)->info != NULL) { e_2 = e; break; }
- for (n = ve->tail(); n != NULL; n = n->prev()) if ((e = (Edge *)n->data)->info != NULL)
- {
- if ((*(e->oppositeVertex(e1->v2))) != (*(e_2->oppositeVertex(e1->v2)))) e_2 = NULL;
- break;
- }
- delete ve;
-
- if (e_1 != NULL) pinch(e_1, true);
- if (e_2 != NULL) pinch(e_2, true);
-
- return true;
-}
-
-Edge *Basic_TMesh::duplicateEdge(Edge *e1)
-{
- if (e1->t1 == NULL || e1->t2 == NULL) return NULL;
- Edge *e2 = newEdge(e1); //e2->invert();
- E.appendHead(e2);
- e1->t2->replaceEdge(e1, e2);
- e2->t2 = e1->t2; e1->t2 = NULL;
- return e2;
-}
-
-int Basic_TMesh::cutAndStitch()
-{
- Edge *e1, *e2;
- Node *n;
- List singular_edges;
-
- FOREACHEDGE(e1, n) if (IS_BIT(e1, 5) && ((e2 = duplicateEdge(e1)) != NULL)) MARK_BIT(e2, 5);
-
- FOREACHEDGE(e1, n) if (IS_BIT(e1, 5))
- {
- singular_edges.appendHead(e1);
- UNMARK_BIT(e1, 5);
- }
-
- forceNormalConsistence();
- duplicateNonManifoldVertices();
-
- singular_edges.sort(&lexEdgeCompare);
- FOREACHEDGE(e1, n) e1->info = NULL;
- e2 = NULL;
- FOREACHVEEDGE((&singular_edges), e1, n)
- {
- if (e2 == NULL || lexEdgeCompare(e1, e2) != 0) { e1->info = new List(); e2 = e1; }
- ((List *)e2->info)->appendTail(e1);
- e1->info = e2->info;
- }
- // Now each edge is either 'regular' or has the info field pointing to a list of coincident boundary edges
-
- // First, pinch bounded chains of singular edges starting from one endpoint
- FOREACHVEEDGE((&singular_edges), e1, n) if (e1->isLinked()) pinch(e1, true);
-
- // Then, pinch the remaining unbounded chains starting from any of the edges
- FOREACHVEEDGE((&singular_edges), e1, n) if (e1->isLinked()) pinch(e1, false);
-
- removeUnlinkedElements();
-
- d_boundaries = d_handles = d_shells = 1;
-
- return singular_edges.numels();
-}
-
-
-//int Basic_TMesh::cutAndStitch()
-//{
-// Edge *e1, *e2;
-// Node *n;
-// List cut;
-// int i;
-//
-// FOREACHEDGE(e1, n) if (IS_BIT(e1, 5))
-// {
-// if (e1->t1 != NULL && e1->t2 != NULL)
-// {
-// e2 = newEdge(e1);
-// E.appendHead(e2);
-// e1->t2->replaceEdge(e1, e2);
-// e2->t2 = e1->t2; e1->t2 = NULL;
-// }
-// cut.appendHead(e1);
-// UNMARK_BIT(e1, 5);
-// }
-//
-// do
-// {
-// i = 0;
-// FOREACHVEEDGE((&cut), e1, n) if (e1->v1 != NULL) i += e1->stitch();
-// } while (i);
-//
-// removeEdges();
-//
-// d_boundaries = d_handles = d_shells = 1;
-//
-// return cut.numels();
-//}
-
-
-////////////////////// PLY LOADER //////////////////////////////////////////////
-
-int ply_parseElements(FILE *in, const char *elname)
-{
- char c, keyword[64];
- int num;
- // skip comments
- if (!fscanf(in,"%64s ",keyword)) TMesh::error("Unexpected token or end of file!\n");
- while (!strcmp(keyword,"comment") || !strcmp(keyword,"obj_info"))
- {
- while ((c = fgetc(in)) != '\n') if (c==EOF) TMesh::error("\nUnexpected end of file!\n");
- if (!fscanf(in,"%64s ",keyword)) TMesh::error("Unexpected token or end of file!\n");
- }
- if (strcmp(keyword,"element")) TMesh::error("element definition expected!\n");
- if (!fscanf(in,"%64s ",keyword)) TMesh::error("Unexpected token or end of file!\n");
- if (strcmp(keyword,elname)) TMesh::error("Sorry. Element type '%s' is not supported!\n",keyword);
- if (!fscanf(in,"%d\n",&num)) TMesh::error("Unexpected token or end of file!\n");
- if (num <= 0) TMesh::error("Unexpected empty element list!\n");
-
- return num;
-}
-
-void ply_checkVertexProperties(FILE *in)
-{
- char keyword[64], dtype[64], dval[64];
- if (fscanf(in,"%64s %64s %64s\n",keyword,dtype,dval) < 3) TMesh::error("Unexpected token or end of file!\n");
- if (strcmp(keyword,"property")) TMesh::error("property definition expected!\n");
- if (strcmp(dtype,"float") && strcmp(dtype,"float32")) TMesh::error("float property expected!\n");
- if (strcmp(dval,"x")) TMesh::error("'x' float property expected!\n");
- if (fscanf(in,"%64s %64s %64s\n",keyword,dtype,dval) < 3) TMesh::error("Unexpected token or end of file!\n");
- if (strcmp(keyword,"property")) TMesh::error("property definition expected!\n");
- if (strcmp(dtype,"float") && strcmp(dtype,"float32")) TMesh::error("float property expected!\n");
- if (strcmp(dval,"y")) TMesh::error("'y' float property expected!\n");
- if (fscanf(in,"%64s %64s %64s\n",keyword,dtype,dval) < 3) TMesh::error("Unexpected token or end of file!\n");
- if (strcmp(keyword,"property")) TMesh::error("property definition expected!\n");
- if (strcmp(dtype,"float") && strcmp(dtype,"float32")) TMesh::error("float property expected!\n");
- if (strcmp(dval,"z")) TMesh::error("'z' float property expected!\n");
-}
-
-int ply_getOverhead(FILE *in, int format, const char *element)
-{
- char keyword[64], ptype[64], pname[64];
- int oh = 0;
- long pos = ftell(in);
- char *rline = readLineFromFile(in);
- if (!sscanf(rline,"%64s ",keyword)) TMesh::error("Unexpected token or end of file!\n");
- while (!strcmp(keyword, "property"))
- {
- if (sscanf(rline,"%64s %64s %64s",keyword,ptype,pname) < 3) TMesh::error("Unexpected token or end of file!\n");
- if (!strcmp(element,"vertex") && !strcmp(pname,"x")) break;
- else if (!strcmp(element,"face") && !strcmp(ptype,"list")) break;
- pos = ftell(in);
- if (!strcmp(ptype, "char") || !strcmp(ptype, "uchar")) oh += (format)?(1):1;
- else if (!strcmp(ptype, "short") || !strcmp(ptype, "ushort")) oh += (format)?(2):1;
- else if (!strcmp(ptype, "int") || !strcmp(ptype, "uint") ||
- !strcmp(ptype, "float") || !strcmp(ptype,"float32")) oh += (format)?(4):1;
- else if (!strcmp(ptype, "double")) oh += (format)?(8):1;
- else if (!strcmp(ptype, "list")) TMesh::error("list properties other than face indices are not supported!\n");
- else TMesh::error("Unrecognized property type!\n");
- if (!sscanf(readLineFromFile(in),"%64s ",keyword)) TMesh::error("Unexpected token or end of file!\n");
- }
- fseek(in, pos, SEEK_SET);
-
- return oh;
-}
-
-void ply_checkFaceProperties(FILE *in)
-{
- char keyword[64], ltype[64], uctype[64], dtype[64], dval[64];
- if (fscanf(in,"%64s %64s %64s %64s %64s\n",keyword,ltype,uctype,dtype,dval) < 5) TMesh::error("Unexpected token or end of file!\n");
- if (strcmp(keyword,"property")) TMesh::error("property definition expected!\n");
- if (strcmp(ltype,"list")) TMesh::error("list property expected!\n");
- if (strcmp(uctype,"uchar") && strcmp(uctype,"uint8")) TMesh::error("uchar property expected!\n");
- if (strcmp(dtype,"int") && strcmp(dtype,"int32")) TMesh::error("int property expected!\n");
- if (strcmp(dval,"vertex_indices")) TMesh::error("vertex_indices property expected!\n");
-}
-
-void ply_readOverhead(FILE *in, int format, int oh)
-{
- int i;
- static char token[1024];
- if (format == PLY_FORMAT_ASCII) for (i=0; i(nv-1) || i2>(nv-1) || i3>(nv-1)) TMesh::error("\nloadPLY: Invalid index at face %d!\n",i);
- for (j=3; j<=i4; j++)
- {
- if (i1 == i2 || i2 == i3 || i3 == i1) TMesh::warning("\nloadPLY: Coincident indexes at triangle %d! Skipping.\n",i);
- else if (!CreateIndexedTriangle(var, i1, i2, i3)) TMesh::warning("\nloadPLY: This shouldn't happen!!! Skipping triangle.\n");
- i2 = i3;
- if (jx), TMESH_TO_FLOAT(v->y), TMESH_TO_FLOAT(v->z));
- else FOREACHVERTEX(v, n)
- {
- fc[0] = TMESH_TO_FLOAT(v->x); fc[1] = TMESH_TO_FLOAT(v->y); fc[2] = TMESH_TO_FLOAT(v->z);
- fwrite(fc, sizeof(float), 3, fp);
- }
-
- ocds = new coord[V.numels()];
- i=0; FOREACHVERTEX(v, n) ocds[i++] = v->x;
- i=0; FOREACHVERTEX(v, n) v->x = i++;
-
- if (ascii) FOREACHNODE(T, n) fprintf(fp,"3 %d %d %d\n",TVI1(n),TVI2(n),TVI3(n));
- else FOREACHNODE(T, n)
- {
- ii[0]=TVI1(n); ii[1]=TVI2(n); ii[2]=TVI3(n);
- fwrite(&ii0, sizeof(unsigned char), 1, fp);
- fwrite(ii, sizeof(int), 3, fp);
- }
-
- fclose(fp);
- i=0; FOREACHVERTEX(v, n) v->x = ocds[i++];
- delete[] ocds;
-
- return 0;
-}
-
-
-////////////////////// Loads OBJ format ///////////////////////////
-
-int Basic_TMesh::loadOBJ(const char *fname)
-{
- FILE *fp;
- Node *n;
- char c, cmd[3] = "";
- float x,y,z;
- bool face_section = 0;
- int i=0,i1,i2,i3,nv=0,triangulate=0;
- Vertex *v;
- ExtVertex **var=NULL;
-
- if ((fp = fopen(fname,"r")) == NULL) return IO_CANTOPEN;
-
- TMesh::begin_progress();
- while (fscanf(fp, "%2s", cmd) && cmd[0] != '\0')
- {
- if (!strcmp(cmd,"v"))
- {
- if (face_section) TMesh::error("\nloadOBJ: Sorry. Couldn't manage disconnected vertex sections.\n");
- if (fscanf(fp, "%f %f %f", &x, &y, &z) == 3) V.appendTail(newVertex(x,y,z));
- else TMesh::error("\nloadOBJ: Couldn't read coordinates for vertex # %d\n",i);
- }
- else if (!strcmp(cmd,"f"))
- {
- if (!face_section)
- {
- nv = V.numels();
- var = (ExtVertex **)malloc(sizeof(ExtVertex *)*nv);
- i=0; FOREACHVERTEX(v, n) var[i++] = new ExtVertex(v);
- face_section = 1;
- i=0;
- }
-
- if (fscanf(fp,"%d %d %d",&i1,&i2,&i3) == 3)
- {
- if ((i%1000) == 0) TMesh::report_progress("Loading ..%d%%",(i*100)/(nv*2));
- if (i1<0 || i2<0 || i3<0) TMesh::error("\nloadOBJ: Sorry. Negative vertex references not supported.\n");
- if (i1<1 || i2<1 || i3<1 || i1>nv || i2>nv || i3>nv) TMesh::error("\nloadOBJ: Invalid index at face %d!\n",i);
- do
- {
- if (i1 == i2 || i2 == i3 || i3 == i1) TMesh::warning("\nloadOBJ: Coincident indexes at triangle %d! Skipping.\n",i);
- else if (!CreateIndexedTriangle(var, i1-1, i2-1, i3-1)) TMesh::warning("\nloadOBJ: This shouldn't happen!!! Skipping triangle.\n");
- i2 = i3;
- while ((c=fgetc(fp)) != EOF && isspace(c) && c != '\n' && c != '\r');
- if (c==EOF) TMesh::error("\nloadOBJ: Unexpected end of file!\n");
- if (c != '\n' && c != '\r')
- {
- ungetc(c, fp);
- if (fscanf(fp,"%d",&i3) != 1) TMesh::error("\nloadOBJ: Couldn't read indexes for face # %d\n",i);
- else triangulate=1;
- }
- } while (c != '\n' && c != '\r');
- }
- else TMesh::error("\nloadOBJ: Couldn't read indexes for face # %d\n",i);
- i++;
- }
- else if (readLineFromFile(fp, 0) == NULL) break;
- cmd[0]='\0';
- }
-
- TMesh::end_progress();
-
- closeLoadingSession(fp, i, var, (triangulate!=0));
- TMesh::setFilename(fname);
-
- return 0;
-}
-
-////////////////////// Saves OBJ format ///////////////////////////
-
-int Basic_TMesh::saveOBJ(const char *fname)
-{
- FILE *fp;
- int i;
- char triname[256];
- Node *n;
- coord *ocds;
- Vertex *v;
-
- strcpy(triname,fname);
-
- if ((fp = fopen(triname,"w")) == NULL)
- {
- TMesh::warning("Can't open '%s' for output !\n",triname);
- return 1;
- }
-
- PRINT_HEADING_COMMENT(fp);
-
- FOREACHVERTEX(v, n) fprintf(fp, "v %f %f %f\n", TMESH_TO_FLOAT(v->x), TMESH_TO_FLOAT(v->y), TMESH_TO_FLOAT(v->z));
-
- ocds = new coord[V.numels()];
- i=0; FOREACHVERTEX(v, n) ocds[i++] = v->x;
- i=0; FOREACHVERTEX(v, n) v->x = i++;
-
- FOREACHNODE(T, n) fprintf(fp,"f %d %d %d\n",TVI1(n)+1,TVI2(n)+1,TVI3(n)+1);
-
- fclose(fp);
- i=0; FOREACHVERTEX(v, n) v->x = ocds[i++];
- delete[] ocds;
-
- return 0;
-}
-
-
-
-////////////////////// Loads STL format ///////////////////////////
-
-int Basic_TMesh::loadSTL(const char *fname)
-{
- FILE *fp;
- int nt=0, i=0;
- char kw[65]="", kw2[65]="", *line, facet[50];
- float x,y,z;
- bool binary=0;
- Vertex *v, *v1=NULL, *v2=NULL, *v3=NULL;
- Edge *e1, *e2, *e3;
- Triangle *t;
- Point nor;
-
- if ((fp = fopen(fname,"r")) == NULL) return IO_CANTOPEN;
-
- fscanf(fp,"%5s",kw);
- if (strcmp(kw,"solid")) binary=1;
-
- if (!binary) // Might look ASCII just because it begins with 'solid'...
- {
- rewind(fp);
- if ((line = readLineFromFile(fp, 0)) == NULL) binary = 1;
- else if ((line = readLineFromFile(fp, 0)) == NULL) binary = 1;
- else {
- sscanf(line, "%64s", kw);
- if (strcmp(kw, "facet")) binary = 1;
- }
- }
- if (binary) fp = freopen(fname, "rb", fp);
-
- TMesh::begin_progress();
-
- if (binary)
- {
- fseek(fp, 80, SEEK_SET);
- fread(&nt, 4, 1, fp);
-
- for (i=0; igetNormal();
- fprintf(fp, " facet normal %f %f %f\n", TMESH_TO_FLOAT(nor.x), TMESH_TO_FLOAT(nor.y), TMESH_TO_FLOAT(nor.z));
- fprintf(fp, " outer loop\n");
- fprintf(fp, " vertex %f %f %f\n", TMESH_TO_FLOAT(t->v1()->x), TMESH_TO_FLOAT(t->v1()->y), TMESH_TO_FLOAT(t->v1()->z));
- fprintf(fp, " vertex %f %f %f\n", TMESH_TO_FLOAT(t->v2()->x), TMESH_TO_FLOAT(t->v2()->y), TMESH_TO_FLOAT(t->v2()->z));
- fprintf(fp, " vertex %f %f %f\n", TMESH_TO_FLOAT(t->v3()->x), TMESH_TO_FLOAT(t->v3()->y), TMESH_TO_FLOAT(t->v3()->z));
- fprintf(fp, " endloop\n");
- fprintf(fp, " endfacet\n");
- }
- fprintf(fp, "endsolid T_MESH\n");
-
- fclose(fp);
-
- return 0;
-}
-
-////////////////////// Saves Extact File format (EFF) ///////////////////////////
-
-int Basic_TMesh::saveEFF(const char *fname)
-{
- std::ofstream os;
- os.open(fname);
- if (!os.is_open())
- {
- TMesh::warning("Can't open '%s' for output !\n", fname);
- return 1;
- }
-
- os << "EFF\n";
- os << V.numels() << " " << T.numels() << "\n";
-
- Node *n;
- Vertex *v;
- FOREACHVERTEX(v, n) os << v->x << " " << v->y << " " << v->z << "\n";
-
- coord *ocds = new coord[V.numels()];
- int i;
- i = 0; FOREACHVERTEX(v, n) ocds[i++] = v->x;
- i = 0; FOREACHVERTEX(v, n) v->x = i++;
-
- FOREACHNODE(T, n) os << TVI1(n) << " " << TVI2(n) << " " << TVI3(n) << "\n";
-
- os.close();
- i = 0; FOREACHVERTEX(v, n) v->x = ocds[i++];
- delete[] ocds;
-
- return 0;
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/TMesh/tin.cpp b/src/mesh_fix/src/TMesh/tin.cpp
deleted file mode 100644
index 7cd3d8913..000000000
--- a/src/mesh_fix/src/TMesh/tin.cpp
+++ /dev/null
@@ -1,2122 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "tin.h"
-#include
-#include
-
-namespace T_MESH
-{
-
- Vertex * Basic_TMesh::newVertex(){ return new Vertex(); } //!< AMF_ADD 1.1>
- Vertex * Basic_TMesh::newVertex(const coord &x, const coord &y, const coord &z){ return new Vertex(x, y, z); } //!< AMF_ADD 1.1>
- Vertex * Basic_TMesh::newVertex(Point *p){ return new Vertex(p); } //!< AMF_ADD 1.1>
- Vertex * Basic_TMesh::newVertex(Point &p){ return new Vertex(p); } //!< AMF_ADD 1.1>
- Vertex * Basic_TMesh::newVertex(Vertex *v){ return new Vertex(v); } //!< AMF_ADD 1.1-2>
- Edge * Basic_TMesh::newEdge(Vertex *s, Vertex *d){ return new Edge(s, d); } //!< AMF_ADD 1.1>
- Edge * Basic_TMesh::newEdge(Edge *e){ return new Edge(e->v1,e->v2); } //!< AMF_ADD 1.1-2>
- Triangle * Basic_TMesh::newTriangle(){ return new Triangle(); } //!< AMF_ADD 1.1>
- Triangle * Basic_TMesh::newTriangle(Edge *a, Edge *b, Edge *c){ return new Triangle(a, b, c); } //!< AMF_ADD 1.1>
-
-//////////////////////////////////////////////////////////////////
-// //
-// C L A S S C O N S T R U C T O R S //
-// //
-//////////////////////////////////////////////////////////////////
-
-
-///////////////////// Constructor (Empty) ////////////////////
-
-Basic_TMesh::Basic_TMesh()
-{
- info=NULL;
- n_boundaries = n_handles = n_shells = 0;
- d_boundaries = d_handles = d_shells = 0;
-}
-
-
-//////////////////// Constructor (Pre-defined) ///////////////
-
-Basic_TMesh::Basic_TMesh(const char *tin_definition) { init(tin_definition); }
-
-void Basic_TMesh::init(const char *tin_definition)
-{
- info=NULL;
- if (!strcmp(tin_definition, "triangle"))
- {
- Vertex *v1 = newVertex(0,0,0);
- Vertex *v2 = newVertex(2,0,0);
- Vertex *v3 = newVertex(1,1,0);
- Edge *e1 = newEdge(v1,v2); v1->e0 = e1;
- Edge *e2 = newEdge(v2,v3); v2->e0 = e2;
- Edge *e3 = newEdge(v3,v1); v3->e0 = e3;
- Triangle *t1 = newTriangle(e1,e2,e3);
- e1->t1 = t1; e1->t2 = NULL;
- e2->t1 = t1; e2->t2 = NULL;
- e3->t1 = t1; e3->t2 = NULL;
- V.appendHead(v1); V.appendHead(v2); V.appendHead(v3);
- T.appendHead(t1);
- E.appendHead(e1); E.appendHead(e2); E.appendHead(e3);
-
- n_boundaries = 1;
- n_handles = 0;
- n_shells = 1;
- d_boundaries = d_handles = d_shells = 0;
- }
- else if (!strcmp(tin_definition, "tetrahedron"))
- {
- Vertex *v1 = newVertex(-1,-1.4142136,0);
- Vertex *v2 = newVertex(-1,1.4142136,0);
- Vertex *v3 = newVertex(1,0,-1.4142136);
- Vertex *v4 = newVertex(1,0,1.4142136);
- Edge *e1 = newEdge(v1,v2); v1->e0 = e1;
- Edge *e2 = newEdge(v2,v3); v2->e0 = e2;
- Edge *e3 = newEdge(v3,v1); v3->e0 = e3;
- Edge *e4 = newEdge(v1,v4); v4->e0 = e4;
- Edge *e5 = newEdge(v2,v4);
- Edge *e6 = newEdge(v3,v4);
- Triangle *t1 = newTriangle(e1,e2,e3);
- Triangle *t2 = newTriangle(e1,e4,e5);
- Triangle *t3 = newTriangle(e2,e5,e6);
- Triangle *t4 = newTriangle(e3,e6,e4);
- e1->t1 = t1; e1->t2 = t2;
- e2->t1 = t1; e2->t2 = t3;
- e3->t1 = t1; e3->t2 = t4;
- e4->t1 = t2; e4->t2 = t4;
- e5->t1 = t3; e5->t2 = t2;
- e6->t1 = t4; e6->t2 = t3;
- V.appendHead(v1); V.appendHead(v2); V.appendHead(v3); V.appendHead(v4);
- T.appendHead(t1); T.appendHead(t2); T.appendHead(t3); T.appendHead(t4);
- E.appendHead(e1); E.appendHead(e2); E.appendHead(e3);
- E.appendHead(e4); E.appendHead(e5); E.appendHead(e6);
-
- n_boundaries = 0;
- n_handles = 0;
- n_shells = 1;
- d_boundaries = d_handles = d_shells = 0;
- }
- else if (!strcmp(tin_definition, "cube"))
- {
- const double crds[8][3] = {{0, 0, 0},{1, 0, 0},{1, 1, 0},{0, 1, 0},{0, 0, 1},{1, 0, 1},{1, 1, 1},{0, 1, 1}};
- const int tris[12][3] = {{3, 2, 1},{3, 1, 0},{4, 5, 6},{4, 6, 7},{7, 6, 2},{7, 2, 3},{0, 1, 5},{0, 5, 4},{1, 2, 6},{1, 6, 5},{3, 0, 4},{3, 4, 7}};
- ExtVertex *ev[8];
- for (int i=0; i<8; i++)
- {
- Vertex *v = newVertex(crds[i][0], crds[i][1], crds[i][2]);
- ev[i] = new ExtVertex(v);
- V.appendTail(v);
- }
- for (int i=0; i<12; i++)
- CreateIndexedTriangle(ev, tris[i][0], tris[i][1], tris[i][2]);
- for (int i=0; i<8; i++) delete ev[i];
-
- n_boundaries = 1;
- n_handles = 0;
- n_shells = 1;
- d_boundaries = d_handles = d_shells = 0;
- }
- else if (!strcmp(tin_definition, "cylinder"))
- {
- const double crds[8][2] = {{1,0},{0.7,0.7},{0,1},{-0.7,0.7},{-1,0},{-0.7,-0.7},{0,-1},{0.7,-0.7}};
- ExtVertex *ev[8];
- for (int i=0; i<16; i++)
- {
- Vertex *v = newVertex(crds[i%8][0], crds[i%8][1], (i<8)?(-1):(1));
- ev[i] = new ExtVertex(v);
- V.appendTail(v);
- }
-
- for (int i=0; i<8; i++)
- {
- CreateIndexedTriangle(ev, i, (i+1)%8, i+8);
- CreateIndexedTriangle(ev, i+8, (i+1)%8, 8+(i+1)%8);
- }
- for (int i=0; i<6; i++)
- {
- CreateIndexedTriangle(ev, 0, i+2, i+1);
- CreateIndexedTriangle(ev, 8, i+9, i+10);
- }
- for (int i=0; i<8; i++) delete ev[i];
-
- n_boundaries = 1;
- n_handles = 0;
- n_shells = 1;
- d_boundaries = d_handles = d_shells = 0;
- }
- else TMesh::error("Unknown triangulation type '%s'\n",tin_definition);
-}
-
-
-///////////////////// Cloning TIN ///////////////////////////
-
-Basic_TMesh::Basic_TMesh(const Basic_TMesh *tin, const bool clone_info) { init(tin, clone_info); }
-
-void Basic_TMesh::init(const Basic_TMesh *tin, const bool clone_info)
-{
- info=NULL;
- Node *n;
- Vertex *v, *nv;
- Edge *e, *ne;
- Triangle *t, *nt;
-
- int i;
- Data **t_info = new Data *[tin->T.numels()];
- i=0; FOREACHVTTRIANGLE((&(tin->T)), t, n) t_info[i++]=t->info;
- Data **e_info = new Data *[tin->E.numels()];
- i=0; FOREACHVEEDGE((&(tin->E)), e, n) e_info[i++]=e->info;
- Data **v_info = new Data *[tin->V.numels()];
- i=0; FOREACHVVVERTEX((&(tin->V)), v, n) v_info[i++]=v->info;
-
- FOREACHVVVERTEX((&(tin->V)), v, n)
- {
- nv = newVertex(v); V.appendTail(nv); v->info = nv;
- }
-
- FOREACHVEEDGE((&(tin->E)), e, n)
- {ne=newEdge((Vertex *)e->v1->info, (Vertex *)e->v2->info); E.appendTail(ne); e->info = ne;}
-
- FOREACHVTTRIANGLE((&(tin->T)), t, n)
- {nt=newTriangle((Edge *)t->e1->info,(Edge *)t->e2->info,(Edge *)t->e3->info); T.appendTail(nt); t->info = nt;}
-
- FOREACHVVVERTEX((&(tin->V)), v, n) {((Vertex *)v->info)->e0 = (Edge *)v->e0->info; v->info = NULL;}
-
- FOREACHVEEDGE((&(tin->E)), e, n)
- {((Edge *)e->info)->t1 = (e->t1)?((Triangle *)e->t1->info):(NULL); ((Edge *)e->info)->t2 = (e->t2)?((Triangle *)e->t2->info):(NULL); e->info = NULL;}
-
- i=0; FOREACHVTTRIANGLE((&(tin->T)), t, n) t->info=t_info[i++];
- i=0; FOREACHVEEDGE((&(tin->E)), e, n) e->info=e_info[i++];
- i=0; FOREACHVVVERTEX((&(tin->V)), v, n) v->info=v_info[i++];
-
- if (clone_info)
- {
- i=0; FOREACHTRIANGLE(t, n) t->info=t_info[i++];
- i=0; FOREACHEDGE(e, n) e->info=e_info[i++];
- i=0; FOREACHVERTEX(v, n) v->info=v_info[i++];
- }
- delete [] t_info; delete [] e_info; delete [] v_info;
-
- d_boundaries = d_handles = d_shells = 1;
-}
-
-
-//// Creates a new Basic_TMesh out of a connected component of an existing Basic_TMesh.
-//// If 'keep_reference' is set to 'true', each element of the existing mesh keeps a
-//// pointer to the corresponding new element in the 'info' field.
-
-Basic_TMesh::Basic_TMesh(const Triangle *t0, const bool keep_reference) { init(t0, keep_reference); }
-
-void Basic_TMesh::init(const Triangle *t0, const bool keep_reference)
-{
- info=NULL;
- List todo(t0), st, sv, se;
- Node *n;
- Triangle *t, *nt;
- Vertex *v, *nv;
- Edge *e, *ne;
-
- t=(Triangle *)t0;
- MARK_VISIT2(t);
-
- while (todo.numels())
- {
- t = (Triangle *)todo.popHead();
- st.appendHead(t);
- nt=t->t1(); if (nt != NULL && !IS_VISITED2(nt)) {MARK_VISIT2(nt); todo.appendHead(nt);}
- nt=t->t2(); if (nt != NULL && !IS_VISITED2(nt)) {MARK_VISIT2(nt); todo.appendHead(nt);}
- nt=t->t3(); if (nt != NULL && !IS_VISITED2(nt)) {MARK_VISIT2(nt); todo.appendHead(nt);}
- }
-
- FOREACHVTTRIANGLE((&st), t, n)
- {
- UNMARK_VISIT2(t);
- e = t->e1; if (!IS_VISITED2(e)) {MARK_VISIT2(e); se.appendHead(e);}
- e = t->e2; if (!IS_VISITED2(e)) {MARK_VISIT2(e); se.appendHead(e);}
- e = t->e3; if (!IS_VISITED2(e)) {MARK_VISIT2(e); se.appendHead(e);}
- v = t->v1(); if (!IS_VISITED2(v)) {MARK_VISIT2(v); sv.appendHead(v);}
- v = t->v2(); if (!IS_VISITED2(v)) {MARK_VISIT2(v); sv.appendHead(v);}
- v = t->v3(); if (!IS_VISITED2(v)) {MARK_VISIT2(v); sv.appendHead(v);}
- }
-
- FOREACHVVVERTEX((&sv), v, n)
- {UNMARK_VISIT2(v); nv=newVertex(v); V.appendTail(nv); v->info = nv;}
-
- FOREACHVEEDGE((&se), e, n)
- {UNMARK_VISIT2(e); ne=newEdge((Vertex *)e->v1->info, (Vertex *)e->v2->info); E.appendTail(ne); e->info = ne;}
-
- FOREACHVTTRIANGLE((&st), t, n)
- {nt=newTriangle((Edge *)t->e1->info,(Edge *)t->e2->info,(Edge *)t->e3->info); T.appendTail(nt); t->info = nt;}
-
- FOREACHVVVERTEX((&sv), v, n) ((Vertex *)v->info)->e0 = (Edge *)v->e0->info;
-
- FOREACHVEEDGE((&se), e, n)
- {((Edge *)e->info)->t1 = (e->t1)?((Triangle *)e->t1->info):(NULL); ((Edge *)e->info)->t2 = (e->t2)?((Triangle *)e->t2->info):(NULL);}
-
- if (!keep_reference)
- {
- FOREACHVVVERTEX((&sv), v, n) v->info = NULL;
- FOREACHVEEDGE((&se), e, n) e->info = NULL;
- FOREACHVTTRIANGLE((&st), t, n) t->info = NULL;
- }
-
- eulerUpdate();
-}
-
-
-Basic_TMesh *Basic_TMesh::split()
-{
- if (T.numels() == 0) return NULL;
- deselectTriangles();
- Triangle *t = (Triangle *)T.head()->data;
- selectConnectedComponent(t);
- Basic_TMesh *stin = createSubMeshFromSelection(t);
- removeSelectedTriangles();
- return stin;
-}
-
-///////////////////// Destructor ///////////////////////////
-
-Basic_TMesh::~Basic_TMesh()
-{
- T.freeNodes();
- V.freeNodes();
- E.freeNodes();
-}
-
-
-//////////////////////////////////////////////////////////////////
-// //
-// P R I M I T I V E C O N S T R U C T I O N //
-// //
-//////////////////////////////////////////////////////////////////
-
-
-//////////////////// Creates an edge ////////////////////////////
-
-Edge *Basic_TMesh::CreateEdge(Vertex *v1, Vertex *v2)
-{
- Edge *e;
-
- if ((e = v1->getEdge(v2)) != NULL) return e;
-
- e = newEdge(v1,v2);
- v1->e0 = e;
- v2->e0 = e;
- E.appendHead(e);
-
- return e;
-}
-
-
-//////////////////// Creates an edge ////////////////////////////
-
-Edge *Basic_TMesh::CreateEdge(ExtVertex *v1, ExtVertex *v2, const bool check)
-{
- Edge *e;
- Node *n;
-
- if (check)
- FOREACHVEEDGE((&(v1->VE)), e, n)
- if (e->oppositeVertex(v1->v) == v2->v) return e;
-
- e = newEdge(v1->v,v2->v);
- if (v1->v->e0 == NULL) v1->v->e0 = e;
- if (v2->v->e0 == NULL) v2->v->e0 = e;
- v1->VE.appendHead(e);
- v2->VE.appendHead(e);
- E.appendHead(e);
-
- return e;
-}
-
-
-///////////////////// Creates a triangle //////////////////////////
-
-Triangle *Basic_TMesh::CreateTriangle(Edge *e1, Edge *e2, Edge *e3)
-{
- Triangle *tt, **at1, **at2, **at3;
-
- if (e1->commonVertex(e2) == e1->v2 && e1->t1 == NULL) at1 = &(e1->t1);
- else if (e1->commonVertex(e2) == e1->v1 && e1->t2 == NULL) at1 = &(e1->t2);
- else return NULL;
- if (e2->commonVertex(e3) == e2->v2 && e2->t1 == NULL) at2 = &(e2->t1);
- else if (e2->commonVertex(e3) == e2->v1 && e2->t2 == NULL) at2 = &(e2->t2);
- else return NULL;
- if (e3->commonVertex(e1) == e3->v2 && e3->t1 == NULL) at3 = &(e3->t1);
- else if (e3->commonVertex(e1) == e3->v1 && e3->t2 == NULL) at3 = &(e3->t2);
- else return NULL;
-
- tt = newTriangle(e1,e2,e3);
- *at1 = *at2 = *at3 = tt;
- T.appendHead(tt);
-
- MARK_VISIT(tt); // < AMF_ADD - since IMATI-STL 2.4-1 >
-
- d_boundaries = d_handles = d_shells = 1;
-
- return tt;
-}
-
-
-///////////////////// Creates an unoriented triangle //////////////////////////
-
-Triangle *Basic_TMesh::CreateUnorientedTriangle(Edge *e1, Edge *e2, Edge *e3)
-{
- Triangle *tt, **at1, **at2, **at3;
-
- if (e1->t1 == NULL) at1 = &(e1->t1);
- else if (e1->t2 == NULL) at1 = &(e1->t2);
- else return NULL;
- if (e2->t1 == NULL) at2 = &(e2->t1);
- else if (e2->t2 == NULL) at2 = &(e2->t2);
- else return NULL;
- if (e3->t1 == NULL) at3 = &(e3->t1);
- else if (e3->t2 == NULL) at3 = &(e3->t2);
- else return NULL;
-
- tt = newTriangle(e1,e2,e3);
- *at1 = *at2 = *at3 = tt;
- T.appendHead(tt);
-
- return tt;
-}
-
-
-////////////// Euler operatior: Create edge and triangle //////////////////////
-
-Triangle *Basic_TMesh::EulerEdgeTriangle(Edge *e2, Edge *e3)
-{
- Vertex *cv = e2->commonVertex(e3);
- Triangle *adj = (e2->t1 == NULL)?(e2->t2):(e2->t1);
- if (cv == NULL || !e2->isOnBoundary() || !e3->isOnBoundary()) return NULL;
-
- Edge *e1 = CreateEdge(e2->oppositeVertex(cv), e3->oppositeVertex(cv));
- if (adj->nextEdge(e2)->hasVertex(cv)) return CreateTriangle(e1,e3,e2);
- return CreateTriangle(e1,e2,e3);
-}
-
-
-/////////// Creation of two triangles bridging two boundary edges /////////////
-
-Edge *Basic_TMesh::bridgeBoundaries(Edge *gve, Edge *gwe)
-{
- if (gve == gwe || !gve->isOnBoundary() || !gwe->isOnBoundary()) return NULL;
-
- Triangle *t;
- Vertex *v = gve->commonVertex(gwe);
- if (v != NULL)
- {
- t = EulerEdgeTriangle(gve, gwe);
- return gve;
- }
-
- Vertex *gv = (gve->t1) ? (gve->v1) : (gve->v2);
- Vertex *gw = (gwe->t1) ? (gwe->v2) : (gwe->v1);
- Vertex *gvn = gve->oppositeVertex(gv);
- Vertex *gwn = gwe->oppositeVertex(gw);
-
- Edge *je = CreateEdge(gv, gw);
- Edge *je2 = CreateEdge(gwn, gvn);
- Edge *je1 = CreateEdge(gv, gwn);
-
- t = CreateTriangle(je, gwe, je1);
- t = CreateTriangle(je1, je2, gve);
-
- return je1;
-}
-
-//////////////////////////////////////////////////////////////////
-// //
-// P R I M I T I V E D E S T R U C T I O N //
-// //
-//////////////////////////////////////////////////////////////////
-
-
-/////// Unlinks the triangle (elements are not removed from the lists) //////////
-
-void Basic_TMesh::unlinkTriangle(Triangle *t)
-{
- Vertex *v1 = t->v1(), *v2 = t->v2(), *v3 = t->v3();
- Edge *e1 = t->e1, *e2 = t->e2, *e3 = t->e3;
-
- int v1nm = (v1->isOnBoundary() && !e1->isOnBoundary() && !e2->isOnBoundary());
- int v2nm = (v2->isOnBoundary() && !e2->isOnBoundary() && !e3->isOnBoundary());
- int v3nm = (v3->isOnBoundary() && !e3->isOnBoundary() && !e1->isOnBoundary());
-
- v1->e0 = ((e2->isOnBoundary())?(e1):(e2));
- v2->e0 = ((e3->isOnBoundary())?(e2):(e3));
- v3->e0 = ((e1->isOnBoundary())?(e3):(e1));
-
- e1->replaceTriangle(t, NULL);
- e2->replaceTriangle(t, NULL);
- e3->replaceTriangle(t, NULL);
-
- if (e1->isIsolated() && e2->isIsolated()) v1->e0 = NULL;
- if (e2->isIsolated() && e3->isIsolated()) v2->e0 = NULL;
- if (e3->isIsolated() && e1->isIsolated()) v3->e0 = NULL;
- if (e1->isIsolated()) e1->v1 = e1->v2 = NULL;
- if (e2->isIsolated()) e2->v1 = e2->v2 = NULL;
- if (e3->isIsolated()) e3->v1 = e3->v2 = NULL;
- t->e1 = t->e2 = t->e3 = NULL;
-
- Vertex *nv;
- Edge *e;
- List *ve;
- Node *n;
-
- if (v1nm)
- {
- nv = newVertex(v1->x, v1->y, v1->z);
- nv->e0 = v1->e0;
- ve = v1->VE();
- FOREACHVEEDGE(ve, e, n) e->replaceVertex(v1, nv);
- delete(ve);
- v1->e0 = e1;
- V.appendHead(nv);
- }
- if (v2nm)
- {
- nv = newVertex(v2->x, v2->y, v2->z);
- nv->e0 = v2->e0;
- ve = v2->VE();
- FOREACHVEEDGE(ve, e, n) e->replaceVertex(v2, nv);
- delete(ve);
- v2->e0 = e2;
- V.appendHead(nv);
- }
- if (v3nm)
- {
- nv = newVertex(v3->x, v3->y, v3->z);
- nv->e0 = v3->e0;
- ve = v3->VE();
- FOREACHVEEDGE(ve, e, n) e->replaceVertex(v3, nv);
- delete(ve);
- v3->e0 = e3;
- V.appendHead(nv);
- }
-}
-
-
-//// Unlinks the triangle (elements are not removed from the lists) ////
-//// Differently from the above method, non-manifold vertices are not duplicated ////
-
-void Basic_TMesh::unlinkTriangleNoManifold(Triangle *t)
-{
- Edge *e1 = t->e1, *e2 = t->e2, *e3 = t->e3;
-
- e1->replaceTriangle(t, NULL);
- e2->replaceTriangle(t, NULL);
- e3->replaceTriangle(t, NULL);
-
- if (e1->isIsolated()) e1->v1 = e1->v2 = NULL;
- if (e2->isIsolated()) e2->v1 = e2->v2 = NULL;
- if (e3->isIsolated()) e3->v1 = e3->v2 = NULL;
- t->e1 = t->e2 = t->e3 = NULL;
-}
-
-
-///// Removes all the triangles with NULL edges /////
-
-int Basic_TMesh::removeTriangles()
-{
- Node *n;
- Triangle *t;
- int r = 0;
-
- n = T.head();
- while (n != NULL)
- {
- t = (Triangle *)n->data;
- n = n->next();
- if (t->e1 == NULL || t->e2 == NULL || t->e3 == NULL)
- {
- r++;
- T.removeCell((n!=NULL)?(n->prev()):T.tail());
- delete t;
- }
- }
-
- d_boundaries = d_handles = d_shells = 1;
-
- return r;
-}
-
-
-///// Removes all the edges with NULL vertices /////
-
-int Basic_TMesh::removeEdges()
-{
- Node *n;
- Edge *e;
- int r = 0;
-
- n = E.head();
- while (n != NULL)
- {
- e = (Edge *)n->data;
- n = n->next();
- if (e->v1 == NULL || e->v2 == NULL)
- {
- r++;
- E.removeCell((n!=NULL)?(n->prev()):E.tail());
- delete e;
- }
- }
-
- d_boundaries = d_handles = d_shells = 1;
-
- return r;
-}
-
-
-/////////// Removes all the vertices with e0 field = NULL ////////////
-
-int Basic_TMesh::removeVertices()
-{
- Node *n;
- Vertex *v;
- int r = 0;
-
- n = V.head();
- while (n != NULL)
- {
- v = (Vertex *)n->data;
- n = n->next();
- if (v->e0 == NULL)
- {
- r++;
- V.removeCell((n!=NULL)?(n->prev()):V.tail());
- delete v;
- }
- }
-
- d_boundaries = d_handles = d_shells = 1;
-
- return r;
-}
-
-
-//// Removes all the vertices that can be deleted without changing the geometric realization. O(N).
-int Basic_TMesh::removeRedundantVertices()
-{
- Node *n;
- Vertex *v;
- int fv = 0;
- FOREACHVERTEX(v, n) if (v->removeIfRedundant()) fv++;
- removeUnlinkedElements();
- return fv;
-}
-
-//////////////////////////////////////////////////////////////////
-// //
-// S E L E C T I O N M A N A G E M E N T //
-// //
-//////////////////////////////////////////////////////////////////
-
-
-//////////////// Deselect all the triangles /////////////
-
-void Basic_TMesh::deselectTriangles()
-{
- Triangle *t;
- Node *n;
- FOREACHTRIANGLE(t, n) UNMARK_VISIT(t);
-}
-
-
-//////// Removes all the selected (IS_VISITED) triangles /////////////
-
-void Basic_TMesh::removeSelectedTriangles()
-{
- Node *n;
- Triangle *t;
-
- FOREACHTRIANGLE(t, n) if (IS_VISITED(t)) unlinkTriangle(t);
- removeUnlinkedElements();
-}
-
-
-// Mark all the triangles having at least one boundary vertex as 'selected'
-
-int Basic_TMesh::selectBoundaryTriangles()
-{
- Node *n;
- Edge *e;
- Vertex *v, *v1, *v2, *v3;
- Triangle *t;
- int ns=0;
-
- FOREACHEDGE(e, n) if (e->isOnBoundary()) {MARK_VISIT(e->v1); MARK_VISIT(e->v2);}
-
- FOREACHTRIANGLE(t, n) if (!IS_VISITED(t))
- {
- v1 = t->v1(); v2 = t->v2(); v3 = t->v3();
- if (IS_VISITED(v1) || IS_VISITED(v2) || IS_VISITED(v3)) {MARK_VISIT(t); ns++;}
- }
- FOREACHVERTEX(v, n) UNMARK_VISIT(v);
-
- return ns;
-}
-
-
-// Grows the current selection (1 triangle width)
-
-int Basic_TMesh::growSelection()
-{
- Node *n;
- Vertex *v, *v1, *v2, *v3;
- Triangle *t;
- int ns=0;
-
- FOREACHTRIANGLE(t, n) if (IS_VISITED(t))
- {
- v1 = t->v1(); v2 = t->v2(); v3 = t->v3();
- MARK_VISIT(v1); MARK_VISIT(v2); MARK_VISIT(v3);
- }
- FOREACHTRIANGLE(t, n) if (!IS_VISITED(t))
- {
- v1 = t->v1(); v2 = t->v2(); v3 = t->v3();
- if (IS_VISITED(v1) || IS_VISITED(v2) || IS_VISITED(v3)) {MARK_VISIT(t); ns++;}
- }
-
- FOREACHVERTEX(v, n) UNMARK_VISIT(v);
-
- return ns;
-}
-
-
-// Shrinks the current selection (1 triangle width)
-
-void Basic_TMesh::shrinkSelection()
-{
- Node *n;
- Vertex *v, *v1, *v2, *v3;
- Triangle *t;
-
- FOREACHTRIANGLE(t, n) if (!IS_VISITED(t))
- {
- v1 = t->v1(); v2 = t->v2(); v3 = t->v3();
- MARK_VISIT(v1); MARK_VISIT(v2); MARK_VISIT(v3);
- }
- FOREACHTRIANGLE(t, n) if (IS_VISITED(t))
- {
- v1 = t->v1(); v2 = t->v2(); v3 = t->v3();
- if (IS_VISITED(v1) || IS_VISITED(v2) || IS_VISITED(v3)) UNMARK_VISIT(t);
- }
-
- FOREACHVERTEX(v, n) UNMARK_VISIT(v);
-}
-
-
-// Toggles the selection status of the triangles
-
-void Basic_TMesh::invertSelection(Triangle *t0)
-{
- Node *n;
- Triangle *t;
-
- if (t0 != NULL)
- {
- List totoggle(t0);
- Triangle *s;
- bool unmark = IS_VISITED(t0);
- if (unmark) UNMARK_VISIT(t0); else MARK_VISIT(t0);
- while ((t = (Triangle *)totoggle.popHead()) != NULL)
- {
- if ((s = t->t1()) != NULL && ((IS_VISITED(s) && unmark) || (!IS_VISITED(s) && !unmark)))
- {if (unmark) UNMARK_VISIT(s); else MARK_VISIT(s); totoggle.appendTail(s);}
- if ((s = t->t2()) != NULL && ((IS_VISITED(s) && unmark) || (!IS_VISITED(s) && !unmark)))
- {if (unmark) UNMARK_VISIT(s); else MARK_VISIT(s); totoggle.appendTail(s);}
- if ((s = t->t3()) != NULL && ((IS_VISITED(s) && unmark) || (!IS_VISITED(s) && !unmark)))
- {if (unmark) UNMARK_VISIT(s); else MARK_VISIT(s); totoggle.appendTail(s);}
- }
- }
- else
- {
- FOREACHTRIANGLE(t, n) if (IS_VISITED(t)) UNMARK_VISIT(t); else MARK_VISIT(t);
- }
-}
-
-
-void Basic_TMesh::reselectSelection(Triangle *t0)
-{
- if (!IS_VISITED(t0)) return;
-
- Node *n;
- Triangle *t, *s;
- List triList(t0);
- MARK_VISIT2(t0);
-
- while(triList.numels())
- {
- t = (Triangle *)triList.popHead();
- if ((s = t->t1()) != NULL && !IS_VISITED2(s) && IS_VISITED(s)) {triList.appendHead(s); MARK_VISIT2(s);}
- if ((s = t->t2()) != NULL && !IS_VISITED2(s) && IS_VISITED(s)) {triList.appendHead(s); MARK_VISIT2(s);}
- if ((s = t->t3()) != NULL && !IS_VISITED2(s) && IS_VISITED(s)) {triList.appendHead(s); MARK_VISIT2(s);}
- }
-
- FOREACHTRIANGLE(t, n) if (!IS_VISITED2(t)) UNMARK_VISIT(t); else UNMARK_VISIT2(t);
-}
-
-// Creates a new mesh out of a selection.
-
-Basic_TMesh *Basic_TMesh::createSubMeshFromSelection(Triangle *t0, bool keep_ref)
-{
- Triangle *t,*s, *nt;
- Node *n;
-
- if (t0 != NULL && !IS_VISITED(t0)) return NULL;
-
- Basic_TMesh *tin = newObject();
- Vertex *v,*nv;
- Edge *e, *ne;
- List triList, sT, sE, sV;
-
- if (t0 != NULL)
- {
- triList.appendHead(t0); MARK_BIT(t0,5);
- while (triList.numels())
- {
- t = (Triangle *)triList.popHead();
- sT.appendHead(t);
- if ((s = t->t1()) != NULL && !IS_BIT(s, 5) && IS_VISITED(s)) { triList.appendHead(s); MARK_BIT(s, 5); }
- if ((s = t->t2()) != NULL && !IS_BIT(s, 5) && IS_VISITED(s)) { triList.appendHead(s); MARK_BIT(s, 5); }
- if ((s = t->t3()) != NULL && !IS_BIT(s, 5) && IS_VISITED(s)) { triList.appendHead(s); MARK_BIT(s, 5); }
- }
- FOREACHVTTRIANGLE((&sT), t, n)
- {
- UNMARK_BIT(t->e1, 5); UNMARK_BIT(t->e2, 5); UNMARK_BIT(t->e3, 5);
- UNMARK_BIT(t->v1(), 5); UNMARK_BIT(t->v2(), 5); UNMARK_BIT(t->v3(), 5);
- }
- FOREACHVTTRIANGLE((&sT), t, n)
- {
- if (!IS_BIT(t->e1, 5)) { sE.appendHead(t->e1); MARK_BIT(t->e1, 5); }
- if (!IS_BIT(t->e2, 5)) { sE.appendHead(t->e2); MARK_BIT(t->e2, 5); }
- if (!IS_BIT(t->e3, 5)) { sE.appendHead(t->e3); MARK_BIT(t->e3, 5); }
- if ((v = t->v1()) && !IS_BIT(v, 5)) { sV.appendHead(v); MARK_BIT(v, 5); }
- if ((v = t->v2()) && !IS_BIT(v, 5)) { sV.appendHead(v); MARK_BIT(v, 5); }
- if ((v = t->v3()) && !IS_BIT(v, 5)) { sV.appendHead(v); MARK_BIT(v, 5); }
- }
- }
- else
- {
- FOREACHEDGE(e, n) UNMARK_BIT(e, 5);
- FOREACHVERTEX(v, n) UNMARK_BIT(v, 5);
- FOREACHTRIANGLE(t, n) if (IS_VISITED(t))
- {sT.appendHead(t); MARK_BIT(t->e1, 5); MARK_BIT(t->e2, 5); MARK_BIT(t->e3, 5);}
- FOREACHEDGE(e, n) if (IS_BIT(e,5))
- {sE.appendHead(e); MARK_BIT(e->v1, 5); MARK_BIT(e->v2, 5);}
- FOREACHVERTEX(v, n) if (IS_BIT(v,5)) sV.appendHead(v);
- }
-
- FOREACHVEEDGE((&sE), e, n) e->v1->e0 = e->v2->e0 = e;
-
- int i;
- Data **v_info = NULL, **e_info = NULL, **t_info = NULL;
- if (!keep_ref)
- {
- v_info = new Data *[sV.numels()];
- i=0; FOREACHVVVERTEX((&sV), v, n) v_info[i++] = v->info;
- e_info = new Data *[sE.numels()];
- i=0; FOREACHVEEDGE((&sE), e, n) e_info[i++] = e->info;
- t_info = new Data *[sT.numels()];
- i=0; FOREACHVTTRIANGLE((&sT), t, n) t_info[i++] = t->info;
- }
-
- FOREACHVVVERTEX((&sV), v, n)
- {nv=newVertex(v); tin->V.appendTail(nv); v->info = nv;}
-
- FOREACHVEEDGE((&sE), e, n)
- {ne=newEdge((Vertex *)e->v1->info, (Vertex *)e->v2->info); tin->E.appendTail(ne); e->info = ne;}
-
- FOREACHVTTRIANGLE((&sT), t, n)
- {nt=newTriangle((Edge *)t->e1->info,(Edge *)t->e2->info,(Edge *)t->e3->info); tin->T.appendTail(nt); t->info = nt; nt->info = t;}
-
- FOREACHVVVERTEX((&sV), v, n) ((Vertex *)v->info)->e0 = (Edge *)v->e0->info;
-
- FOREACHVEEDGE((&sE), e, n)
- {
- ((Edge *)e->info)->t1 = (e->t1 && IS_VISITED(e->t1))?((Triangle *)e->t1->info):(NULL);
- ((Edge *)e->info)->t2 = (e->t2 && IS_VISITED(e->t2))?((Triangle *)e->t2->info):(NULL);
- }
-
- i=0; if (!keep_ref) FOREACHVVVERTEX((&sV), v, n) v->info = v_info[i++];
- i=0; if (!keep_ref) FOREACHVEEDGE((&sE), e, n) e->info = e_info[i++];
- i=0; if (!keep_ref) FOREACHVTTRIANGLE((&sT), t, n) t->info = t_info[i++];
-
- FOREACHVTTRIANGLE((&sT), t, n) UNMARK_BIT(t, 5);
- FOREACHVEEDGE((&sE), e, n) UNMARK_BIT(e, 5);
- FOREACHVVVERTEX((&sV), v, n) UNMARK_BIT(v, 5);
-
- if (!sT.numels()) {delete(tin); return NULL;}
-
- tin->duplicateNonManifoldVertices();
- tin->eulerUpdate();
-
- return tin;
-}
-
-Basic_TMesh *Basic_TMesh::createSubMeshFromTriangle(Triangle *t0)
-{
- Basic_TMesh *ntin = newObject("triangle");
-
- Vertex *v1 = (Vertex *)ntin->V.head()->data;
- Vertex *v2 = (Vertex *)ntin->V.head()->next()->data;
- Vertex *v3 = (Vertex *)ntin->V.head()->next()->next()->data;
- v1->setValue(t0->v1());
- v2->setValue(t0->v3());
- v3->setValue(t0->v2());
- ((Triangle *)ntin->T.head()->data)->info = t0->info;
-
- return ntin;
-}
-
-///// Marks all the triangles within distance L as selected //////
-
-int Basic_TMesh::selectSphericalRegion(Triangle *t, const double L, const Point *center)
-{
- List *reg = getRegion(t, L, center);
- Node *n;
- Triangle *s;
- int nt=0;
-
- FOREACHVTTRIANGLE(reg, s, n) {MARK_VISIT(s); nt++;}
- delete(reg);
-
- return nt;
-}
-
-
-///// Deselects all the triangles within distance L //////
-
-int Basic_TMesh::deselectSphericalRegion(Triangle *t, const double L, const Point *center)
-{
- List *reg = getRegion(t, L, center);
- Node *n;
- Triangle *s;
- int nt=0;
-
- FOREACHVTTRIANGLE(reg, s, n) {UNMARK_VISIT(s); nt++;}
- delete(reg);
-
- return nt;
-}
-
-
-///// Selects all the triangles within distance L which were already //////
-///// selected. Deselects the others. //////
-
-void Basic_TMesh::reselectSphericalRegion(Triangle *t, const double L, const Point *center)
-{
- List *reg = getRegion(t, L, center);
- Node *n;
- Triangle *s;
-
- FOREACHVTTRIANGLE(reg, s, n) MARK_VISIT2(s);
- FOREACHTRIANGLE(s, n) if (IS_VISITED(s) && !IS_VISITED2(s)) UNMARK_VISIT(s);
- FOREACHVTTRIANGLE(reg, s, n) UNMARK_VISIT2(s);
- delete(reg);
-}
-
-
-//// Remove all the selected triangles and re-triangulate /////
-
-bool Basic_TMesh::retriangulateSelectedRegion()
-{
- List ttbr;
- Node *n;
- Triangle *u;
- Point nor;
- FOREACHTRIANGLE(u, n) if (IS_VISITED(u))
- {ttbr.appendHead(u); nor = nor+(u->getNormal()*u->area());}
-
- if (ttbr.numels() < 2)
- {
- TMesh::warning("retriangulateRegion: Nothing to retriangulate.\n");
- return 0;
- }
-
- FOREACHVTTRIANGLE((&(ttbr)), u, n)
- if (u->getNormal()*nor <= 0.0)
- {
- TMesh::warning("retriangulateRegion: Too complex geometry. Can't retriangulate.\n");
- return 0;
- }
-
- if (!isSelectionSimple(&ttbr))
- {
- TMesh::warning("retriangulateRegion: Non-simple region. Can't retriangulate.\n");
- return 0;
- }
-
- List *ms = getRegionInternalVertices(&ttbr);
-
- FOREACHVTTRIANGLE((&(ttbr)), u, n) unlinkTriangle(u);
- Edge *e = ((Edge *)ms->head()->data);
- List *vl = ((List *)ms->head()->next()->data);
- TriangulateHole(e, vl);
- delete(vl);
- delete(ms);
- removeUnlinkedElements();
-
- return 1;
-}
-
-
-////////// Check wether 's' represents a simple selection ////////
-
-bool Basic_TMesh::isSelectionSimple(List *s)
-{
- if (!s->numels()) return 0; // Empty region is not simple
-
- Node *n;
- Triangle *ta, *t = (Triangle *)s->head()->data;
- List bdr, top(t);
- MARK_VISIT2(t);
- int nv=0;
-
- while (top.numels())
- {
- t = (Triangle *)top.popHead();
- nv++;
- ta=t->t1(); if (ta && IS_VISITED(ta) && !IS_VISITED2(ta)) {MARK_VISIT2(ta); top.appendHead(ta);}
- else if (ta == NULL) break; else if (!IS_VISITED(ta)) bdr.appendHead(t->e1);
- ta=t->t2(); if (ta && IS_VISITED(ta) && !IS_VISITED2(ta)) {MARK_VISIT2(ta); top.appendHead(ta);}
- else if (ta == NULL) break; else if (!IS_VISITED(ta)) bdr.appendHead(t->e2);
- ta=t->t3(); if (ta && IS_VISITED(ta) && !IS_VISITED2(ta)) {MARK_VISIT2(ta); top.appendHead(ta);}
- else if (ta == NULL) break; else if (!IS_VISITED(ta)) bdr.appendHead(t->e3);
- }
-
- FOREACHVTTRIANGLE(s, t, n) UNMARK_VISIT2(t);
- if (top.numels()) return 0; // Mesh-boundary in selection
- if (nv != s->numels()) return 0; // Disconnected selection
-
- Edge *e, *f, *ge=NULL, *e0;
- List *ve;
- FOREACHVEEDGE((&(bdr)), e, n) MARK_VISIT(e);
- int nae;
-
- nv = 0;
- e = e0 = (Edge *)bdr.head()->data;
- Vertex *v = e->v1;
-
- do
- {
- nv++;
- v = e->oppositeVertex(v);
- ve = v->VE();
- nae=0; FOREACHVEEDGE(ve, f, n) if (f!=e && IS_VISITED(f)) {ge=f; nae++;}
- delete(ve);
- if (nae > 1) break;
- e=ge;
- } while (e != e0);
-
- FOREACHVEEDGE((&(bdr)), e, n) UNMARK_VISIT(e);
- if (nv != bdr.numels()) return 0; // Non-simple selection
-
- return 1;
-}
-
-
-//// Unmarks all the elements of the triangulation ////
-//// but leaves selected triangles marked. ////
-
-void Basic_TMesh::unmarkEverythingButSelections()
-{
- Vertex *v;
- Edge *e;
- Triangle *t;
- Node *n;
- FOREACHVERTEX(v, n) v->mask = 0;
- FOREACHEDGE(e, n) e->mask = 0;
- FOREACHTRIANGLE(t, n) t->mask &= (unsigned char)1;
-}
-
-
-//// Selects all the triangles of the shell containing 't' ////
-
-int Basic_TMesh::selectConnectedComponent(Triangle *t0, bool sos)
-{
- List todo;
- Triangle *t, *t1, *t2, *t3;
- int ns = 0;
-
- todo.appendHead(t0);
- while (todo.numels())
- {
- t = (Triangle *)todo.popHead();
- if (!IS_VISITED(t))
- {
- t1 = t->t1(); t2 = t->t2(); t3 = t->t3();
-
- if (t1 != NULL && !IS_VISITED(t1) && (!(sos && IS_SHARPEDGE(t->e1)))) todo.appendHead(t1);
- if (t2 != NULL && !IS_VISITED(t2) && (!(sos && IS_SHARPEDGE(t->e2)))) todo.appendHead(t2);
- if (t3 != NULL && !IS_VISITED(t3) && (!(sos && IS_SHARPEDGE(t->e3)))) todo.appendHead(t3);
-
- MARK_VISIT(t); ns++;
- }
- }
-
- return ns;
-}
-
-
-//// Deselects all the triangles of the shell containing 't' ////
-
-int Basic_TMesh::deselectConnectedComponent(Triangle *t0, bool sos)
-{
- List todo;
- Triangle *t, *t1, *t2, *t3;
- int ns = 0;
-
- todo.appendHead(t0);
- while (todo.numels())
- {
- t = (Triangle *)todo.popHead();
- if (IS_VISITED(t))
- {
- t1 = t->t1(); t2 = t->t2(); t3 = t->t3();
-
- if (t1 != NULL && IS_VISITED(t1) && (!(sos && IS_SHARPEDGE(t->e1)))) todo.appendHead(t1);
- if (t2 != NULL && IS_VISITED(t2) && (!(sos && IS_SHARPEDGE(t->e2)))) todo.appendHead(t2);
- if (t3 != NULL && IS_VISITED(t3) && (!(sos && IS_SHARPEDGE(t->e3)))) todo.appendHead(t3);
-
- UNMARK_VISIT(t); ns++;
- }
- }
-
- return ns;
-}
-
-
-// Append to the current mesh a copy of all the elements of 'src'.
-// The newly created elements form a new selection.
-
-void Basic_TMesh::append(Basic_TMesh *src)
-{
- deselectTriangles();
- Basic_TMesh cb(src);
- cb.invertSelection();
- V.joinTailList(&(cb.V));
- E.joinTailList(&(cb.E));
- T.joinTailList(&(cb.T));
- d_boundaries = d_handles = d_shells = 1;
-}
-
-
-// Move all the elements of 't' to this mesh and delete 't' itself.
-void Basic_TMesh::moveMeshElements(Basic_TMesh *t, bool delInput)
-{
- V.joinTailList(&(t->V));
- E.joinTailList(&(t->E));
- T.joinTailList(&(t->T));
- d_boundaries = d_handles = d_shells = 1;
- if(delInput) delete t;
-}
-
-
-//////////////////////////////////////////////////////////////////
-// //
-// R E G I O N M A N I P U L A T I O N //
-// //
-//////////////////////////////////////////////////////////////////
-
-///// Make a list with all the triangles within distance L //////
-
-List *Basic_TMesh::getRegion(Triangle *t, const double L, const Point *center)
-{
- List triList, *toRemove = new List;
- if (t->v1()->distance(center) > L) return toRemove;
- if (t->v2()->distance(center) > L) return toRemove;
- if (t->v3()->distance(center) > L) return toRemove;
-
- Triangle *s;
- Node *n;
-
- triList.appendHead(t);
- MARK_BIT(t,3);
-
- while(triList.numels() > 0)
- {
- t = (Triangle *)triList.head()->data;
- triList.removeCell(triList.head());
- toRemove->appendHead(t);
-
- if ((s = t->t1()) != NULL && !IS_BIT(s,3) && s->oppositeVertex(t->e1)->distance(center) <= L)
- {triList.appendHead(s); MARK_BIT(s,3);}
- if ((s = t->t2()) != NULL && !IS_BIT(s,3) && s->oppositeVertex(t->e2)->distance(center) <= L)
- {triList.appendHead(s); MARK_BIT(s,3);}
- if ((s = t->t3()) != NULL && !IS_BIT(s,3) && s->oppositeVertex(t->e3)->distance(center) <= L)
- {triList.appendHead(s); MARK_BIT(s,3);}
- }
-
- FOREACHVTTRIANGLE(toRemove, s, n) UNMARK_BIT(s, 3);
-
- return toRemove;
-}
-
-
-///// Unlink all the triangles within distance L //////
-
-void Basic_TMesh::removeRegion(Triangle *t, const double L, const Point *center)
-{
- List triList, toRemove;
- Node *n;
- Triangle *s;
-
- triList.appendHead(t);
- MARK_VISIT(t);
-
- while(triList.numels() > 0)
- {
- t = (Triangle *)triList.head()->data;
- triList.removeCell(triList.head());
- toRemove.appendHead(t);
-
- if ((s = t->t1()) != NULL && !IS_VISITED(s) && s->oppositeVertex(t->e1)->distance(center) <= L)
- {triList.appendHead(s); MARK_VISIT(s);}
- if ((s = t->t2()) != NULL && !IS_VISITED(s) && s->oppositeVertex(t->e2)->distance(center) <= L)
- {triList.appendHead(s); MARK_VISIT(s);}
- if ((s = t->t3()) != NULL && !IS_VISITED(s) && s->oppositeVertex(t->e3)->distance(center) <= L)
- {triList.appendHead(s); MARK_VISIT(s);}
- }
-
- for (n = toRemove.tail(); n != NULL; n=n->prev())
- {
- s = ((Triangle *)n->data);
- unlinkTriangle(s);
- }
-
- removeUnlinkedElements();
-}
-
-
-//////// Next region's boundary vertex /////////////
-
-Vertex *Basic_TMesh::nextVertexOnRegionBoundary(Vertex *sv) const
-{
- Triangle *lt, *rt;
- Edge *e;
- List *ve = sv->VE();
- Node *n;
-
- FOREACHVEEDGE(ve, e, n)
- {
- lt = e->leftTriangle(sv);
- rt = e->rightTriangle(sv);
- if (lt != NULL && IS_VISITED(lt) && (rt == NULL || !IS_VISITED(rt)))
- {delete(ve); return e->oppositeVertex(sv);}
- }
- delete(ve);
-
- return NULL;
-}
-
-
-//// This method returns a list containing an edge of the region's boundary ////
-//// as its first element, and all the internal vertices as the remaining ////
-
-List *Basic_TMesh::getRegionInternalVertices(List *reg)
-{
- List *iVertices = new List;
- List *outList = new List;
- Edge *bEdge = NULL;
- Triangle *s, *t;
- Node *n;
- Vertex *v1, *v2, *v3;
-
- FOREACHVTTRIANGLE(reg, t, n) {MARK_VISIT(t); MARK_BIT(t, 3);}
-
- FOREACHVTTRIANGLE(reg, t, n)
- {
- if (IS_BIT(t,3))
- {
- UNMARK_BIT(t,3);
- if ((s = t->t1()) != NULL && !IS_VISITED(s)) {bEdge = t->e1; MARK_BIT(t->e1->v1, 3); MARK_BIT(t->e1->v2, 3);}
- if ((s = t->t2()) != NULL && !IS_VISITED(s)) {bEdge = t->e2; MARK_BIT(t->e2->v1, 3); MARK_BIT(t->e2->v2, 3);}
- if ((s = t->t3()) != NULL && !IS_VISITED(s)) {bEdge = t->e3; MARK_BIT(t->e3->v1, 3); MARK_BIT(t->e3->v2, 3);}
- }
- }
-
- FOREACHVTTRIANGLE(reg, s, n)
- {
- v1 = s->v1(); v2 = s->v2(); v3 = s->v3();
- if (!IS_BIT(v1, 3)) {iVertices->appendHead(v1); MARK_BIT(v1, 3);}
- if (!IS_BIT(v2, 3)) {iVertices->appendHead(v2); MARK_BIT(v2, 3);}
- if (!IS_BIT(v3, 3)) {iVertices->appendHead(v3); MARK_BIT(v3, 3);}
- }
- FOREACHVTTRIANGLE(reg, s, n)
- {
- v1 = s->v1(); v2 = s->v2(); v3 = s->v3();
- UNMARK_BIT(v1, 3); UNMARK_BIT(v2, 3); UNMARK_BIT(v3, 3);
- }
-
- outList->appendHead(iVertices);
- outList->appendHead(bEdge);
-
- return outList;
-}
-
-
-// Transforms only the shell indicated by 't0'
-
-void Basic_TMesh::transformShell(Triangle *t0, const Matrix4x4& m)
-{
- List todo(t0), st, sv;
- Triangle *t, *nt;
- Vertex *v;
- coord x, y, z, w;
-
- while (todo.numels())
- {
- t = (Triangle *)todo.popHead();
- st.appendHead(t);
- nt=t->t1(); if (nt != NULL && !IS_VISITED(nt)) {MARK_VISIT(nt); todo.appendHead(nt);}
- nt=t->t2(); if (nt != NULL && !IS_VISITED(nt)) {MARK_VISIT(nt); todo.appendHead(nt);}
- nt=t->t3(); if (nt != NULL && !IS_VISITED(nt)) {MARK_VISIT(nt); todo.appendHead(nt);}
- }
-
- while (st.numels())
- {
- t = (Triangle *)st.popHead();
- UNMARK_VISIT(t);
- v = t->v1(); if (!IS_VISITED(v)) {MARK_VISIT(v); sv.appendHead(v);}
- v = t->v2(); if (!IS_VISITED(v)) {MARK_VISIT(v); sv.appendHead(v);}
- v = t->v3(); if (!IS_VISITED(v)) {MARK_VISIT(v); sv.appendHead(v);}
- }
-
- while (sv.numels())
- {
- v = (Vertex *)sv.popHead();
- UNMARK_VISIT(v);
- x = ((*v)*Point(m.matrix[0][0],m.matrix[1][0],m.matrix[2][0]))+m.matrix[3][0];
- y = ((*v)*Point(m.matrix[0][1],m.matrix[1][1],m.matrix[2][1]))+m.matrix[3][1];
- z = ((*v)*Point(m.matrix[0][2],m.matrix[1][2],m.matrix[2][2]))+m.matrix[3][2];
- w = ((*v)*Point(m.matrix[0][3],m.matrix[1][3],m.matrix[2][3]))+m.matrix[3][3];
- v->x = x/w; v->y = y/w; v->z = z/w;
- }
-}
-
-
-//// Removes all the triangles of the shell containing 't0' ////
-
-void Basic_TMesh::removeShell(Triangle *t0)
-{
- List todo(t0);
- Triangle *t, *t1, *t2, *t3;
-
- while (todo.numels())
- {
- t = (Triangle *)todo.popHead();
- t1 = t->t1(); t2 = t->t2(); t3 = t->t3();
-
- if (t1 != NULL && !IS_VISITED2(t1)) {MARK_VISIT2(t1); todo.appendHead(t1);}
- if (t2 != NULL && !IS_VISITED2(t2)) {MARK_VISIT2(t2); todo.appendHead(t2);}
- if (t3 != NULL && !IS_VISITED2(t3)) {MARK_VISIT2(t3); todo.appendHead(t3);}
-
- unlinkTriangle(t);
- }
-
- removeUnlinkedElements();
-}
-
-
-//////////////////////////////////////////////////////////////////
-// //
-// G L O B A L O P E R A T I O N S //
-// //
-//////////////////////////////////////////////////////////////////
-
-
-/////// Tags as sharp all the edges exceeding the given curvature ///////////
-
-void Basic_TMesh::sharpEdgeTagging(const double ta)
-{
- Node *n;
- Edge *e;
- FOREACHEDGE(e, n)
- if (e->curvature() > ta) TAG_SHARPEDGE(e);
- else UNTAG_SHARPEDGE(e);
-}
-
-
-//// Unmarks all the elements of the triangulation ////
-
-void Basic_TMesh::unmarkEverything()
-{
- Vertex *v;
- Edge *e;
- Triangle *t;
- Node *n;
- FOREACHVERTEX(v, n) v->mask = 0;
- FOREACHEDGE(e, n) e->mask = 0;
- FOREACHTRIANGLE(t, n) t->mask = 0;
-}
-
-
-///// Compute the bounding box and return its max edge /////
-
-coord Basic_TMesh::getBoundingBox(Point& mp, Point& Mp) const
-{
- Vertex *v; Node *n;
- Mp.x = -DBL_MAX, mp.x = DBL_MAX;
- Mp.y = -DBL_MAX, mp.y = DBL_MAX;
- Mp.z = -DBL_MAX, mp.z = DBL_MAX;
- FOREACHVERTEX(v, n)
- {
- if (v->x < mp.x) mp.x = v->x;
- if (v->x > Mp.x) Mp.x = v->x;
- if (v->y < mp.y) mp.y = v->y;
- if (v->y > Mp.y) Mp.y = v->y;
- if (v->z < mp.z) mp.z = v->z;
- if (v->z > Mp.z) Mp.z = v->z;
- }
-
- return MAX(Mp.x-mp.x,MAX(Mp.y-mp.y,Mp.z-mp.z));
-}
-
-
-///// Compute the approximate bounding ball radius /////
-
-double Basic_TMesh::getBoundingBallRadius() const
-{
- Vertex *v; Node *n;
- Point tc, mp, Mp;
- double tb, bsr = TMESH_TO_DOUBLE(getBoundingBox(mp, Mp)) / 2;
- Point bsc = (Mp+mp)/2;
-
- FOREACHVERTEX(v, n)
- if ((tb = ((*v)-bsc).length()) > bsr)
- {
- tc = ((*v)-bsc); tc.normalize();
- tb = ((tb-bsr)/2);
- bsc = bsc+(tc*tb);
- bsr += tb;
- }
-
- return bsr;
-}
-
-
-////// Returns the surface area of the mesh //////
-
-double Basic_TMesh::area() const
-{
- Triangle *t;
- Node *n;
- double a=0.0;
- FOREACHTRIANGLE(t, n) a += t->area();
-
- return a;
-}
-
-
-////// Returns the volume of the mesh //////
-
-double Basic_TMesh::volume() const
-{
- Triangle *t;
- Node *n;
- double v=0.0;
- FOREACHTRIANGLE(t, n)
- v += TMESH_TO_DOUBLE((t->getCenter()*t->getNormal()))*t->area();
-
- return v/3;
-}
-
-
-///// Places the mesh into the unit cube by translating and resizing /////
-///// so that all the coordinates are between 0 and mc (default =1). /////
-
-void Basic_TMesh::normalize(coord mc)
-{
- Vertex *v;
- Node *n;
- Point mp, Mp;
- coord mel = getBoundingBox(mp, Mp) / mc;
- FOREACHVERTEX(v, n) v->setValue(((*v) - mp) / mel); // Shift and normalize
-}
-
-void Basic_TMesh::quantize(int nc)
-{
- Vertex *v;
- Node *n;
- normalize(nc);
- bool stat = TMesh::isUsingRationals();
- TMesh::useRationals(false);
- FOREACHVERTEX(v, n)
- {
- v->x = coord(TMESH_TO_INT(v->x));
- v->y = coord(TMESH_TO_INT(v->y));
- v->z = coord(TMESH_TO_INT(v->z));
- }
- TMesh::useRationals(stat);
-}
-
-
-/////// Transforms all the vertices using the 4x4 matrix 'm' ///////////
-
-void Basic_TMesh::transform(const Matrix4x4& m)
-{
- Node *n;
- Vertex *v;
- coord x,y,z,w;
-
- FOREACHVERTEX(v, n)
- {
- x = ((*v)*Point(m.matrix[0][0],m.matrix[1][0],m.matrix[2][0]))+m.matrix[3][0];
- y = ((*v)*Point(m.matrix[0][1],m.matrix[1][1],m.matrix[2][1]))+m.matrix[3][1];
- z = ((*v)*Point(m.matrix[0][2],m.matrix[1][2],m.matrix[2][2]))+m.matrix[3][2];
- w = ((*v)*Point(m.matrix[0][3],m.matrix[1][3],m.matrix[2][3]))+m.matrix[3][3];
- v->x = x/w; v->y = y/w; v->z = z/w;
- }
-}
-
-// Translate the whole mesh by t_vec
-void Basic_TMesh::translate(const Point& t_vec)
-{
- Vertex *v;
- Node *i;
- FOREACHVERTEX(v, i) v->setValue((*v)+t_vec);
-}
-
-// Return the center of mass of the mesh
-Point Basic_TMesh::getCenter() const
-{
- Point c;
- Triangle *t;
- Node *i;
- coord av, tvol=0.0;
- FOREACHTRIANGLE(t, i)
- {
- av = t->area();
- tvol += av;
- c += (t->getCenter()*av);
- }
-
- return c/tvol;
-}
-
-// Add noise in the normal direction. Normal displacement is
-// bounded by ns% of the bounding ball radius.
-
-void Basic_TMesh::addNormalNoise(double ns)
-{
- Vertex *v;
- Node *n;
- Point np;
- int i;
- double noise;
- coord *xyz = (coord *)malloc(sizeof(coord)*V.numels()*3);
- ns *= (getBoundingBallRadius()/100.0);
-
- i=0; FOREACHVERTEX(v, n)
- {
- noise = ns*(((((double)rand()))-(((double)RAND_MAX)/2.0))/((double)RAND_MAX));
- np = (*v)+((v->getNormal())*noise);
- xyz[i++]=np.x; xyz[i++]=np.y; xyz[i++]=np.z;
- }
- i=0; FOREACHVERTEX(v, n) {v->x=xyz[i++]; v->y=xyz[i++]; v->z=xyz[i++];}
-
- free(xyz);
-}
-
-
-// Iteratively swap edges to maximize the minimum angle.
-// Checks and avoids normal inversion.
-
-bool Basic_TMesh::iterativeEdgeSwaps()
-{
- Node *n;
- Edge *e, *f;
- double l;
- int swaps=1, totits=1;
- Point n1, n2, nor;
- List toswap;
-
- bool selection=0;
- Triangle *t;
- FOREACHTRIANGLE(t, n) if (IS_VISITED(t)) {selection=1; break;}
-
- FOREACHEDGE(e, n) if (!IS_SHARPEDGE(e) && !e->isOnBoundary())
- {
- MARK_VISIT(e); if ((!selection || (IS_VISITED(e->t1) && IS_VISITED(e->t2)))) toswap.appendTail(e);
- }
-
- TMesh::begin_progress();
- while (swaps && totits++ < 10)
- {
- swaps = 0; for (n=toswap.head(); n!=NULL; )
- {
- e = (Edge *)n->data;
- if (n==toswap.tail()) {toswap.removeCell(toswap.tail()); n=NULL;}
- else {n=n->next(); toswap.removeCell(n->prev());}
- UNMARK_VISIT(e);
-
- n1 = e->t1->getNormal();
- n2 = e->t2->getNormal();
- nor = n1+n2;
- l = e->delaunayMinAngle();
- if (e->swap())
- {
- if (e->delaunayMinAngle() <= l*1.000001 || nor*e->t1->getNormal() <= 0 || nor*e->t2->getNormal() <= 0) e->swap(1);
- else
- {
- swaps++;
- f = e->t1->nextEdge(e); if (!IS_VISITED(f) && !IS_SHARPEDGE(f) && !f->isOnBoundary()) {MARK_VISIT(f); toswap.appendHead(f);}
- f = e->t1->prevEdge(e); if (!IS_VISITED(f) && !IS_SHARPEDGE(f) && !f->isOnBoundary()) {MARK_VISIT(f); toswap.appendHead(f);}
- f = e->t2->nextEdge(e); if (!IS_VISITED(f) && !IS_SHARPEDGE(f) && !f->isOnBoundary()) {MARK_VISIT(f); toswap.appendHead(f);}
- f = e->t2->prevEdge(e); if (!IS_VISITED(f) && !IS_SHARPEDGE(f) && !f->isOnBoundary()) {MARK_VISIT(f); toswap.appendHead(f);}
- }
- }
-
- }
- TMesh::report_progress("Swaps: %d ", swaps);
- }
- TMesh::end_progress();
-
- FOREACHEDGE(e, n) UNMARK_VISIT(e);
-
- if (totits >= 10)
- {
- TMesh::warning("Optimization did not converge after 10 iterations! Stopping.\n");
- TMesh::warning("You may try to run the method again.\n");
- return 0;
- }
-
- return 1;
-}
-
-
-//////////////////////////////////////////////////////////////////
-// //
-// T O P O L O G Y M A N I P U L A T I O N //
-// //
-//////////////////////////////////////////////////////////////////
-
-
-////// Invertes all the triangle normals and edge orientations ///////
-
-void Basic_TMesh::flipNormals()
-{
- Node *n;
- Edge *e;
- Triangle *t;
-
- FOREACHTRIANGLE(t, n) t->invert();
- FOREACHEDGE(e, n) p_swap((void **)(&(e->v1)), (void **)(&(e->v2))); //!< AMF_CHANGE 1.1-2 >
-}
-
-
-//// Marks all the triangles of the shell containing 't' ////
-
-void Basic_TMesh::flipNormals(Triangle *t0)
-{
- List todo;
- Triangle *t, *t1, *t2, *t3;
-
- todo.appendHead(t0);
- while (todo.numels())
- {
- t = (Triangle *)todo.popHead();
- if (!IS_BIT(t,6))
- {
- t1 = t->t1(); t2 = t->t2(); t3 = t->t3();
-
- if (t1 != NULL && !IS_BIT(t1,6)) todo.appendHead(t1);
- if (t2 != NULL && !IS_BIT(t2,6)) todo.appendHead(t2);
- if (t3 != NULL && !IS_BIT(t3,6)) todo.appendHead(t3);
-
- t->invert();
- if (!IS_BIT(t->e1,6)) p_swap((void **)(&(t->e1->v1)), (void **)(&(t->e1->v2)));
- if (!IS_BIT(t->e2,6)) p_swap((void **)(&(t->e2->v1)), (void **)(&(t->e2->v2)));
- if (!IS_BIT(t->e3,6)) p_swap((void **)(&(t->e3->v1)), (void **)(&(t->e3->v2)));
- MARK_BIT(t->e1,6); MARK_BIT(t->e2,6); MARK_BIT(t->e3,6);
- MARK_BIT(t,6);
- }
- }
-
- todo.appendHead(t0);
- while (todo.numels())
- {
- t = (Triangle *)todo.popHead();
- if (IS_BIT(t,6))
- {
- t1 = t->t1(); t2 = t->t2(); t3 = t->t3();
-
- if (t1 != NULL && IS_BIT(t1,6)) todo.appendHead(t1);
- if (t2 != NULL && IS_BIT(t2,6)) todo.appendHead(t2);
- if (t3 != NULL && IS_BIT(t3,6)) todo.appendHead(t3);
-
- UNMARK_BIT(t->e1,6); UNMARK_BIT(t->e2,6); UNMARK_BIT(t->e3,6);
- UNMARK_BIT(t,6);
- }
- }
-}
-
-
-//// Returns the top triangle of the mesh (max. z) ////
-
-Triangle *Basic_TMesh::topTriangle(Triangle *t0)
-{
- Node *n;
- Vertex *v, *hv = NULL, *v1, *v2, *v3;
- Edge *e, *fe = NULL;
- coord az, Mz = -DBL_MAX;
- Triangle *t, *t1, *t2, *t3;
- List *ve, todo, tlist, elist, vlist;
-
- todo.appendHead(t0); MARK_BIT(t0,2);
-
- while (todo.numels())
- {
- t = (Triangle *)todo.popHead(); tlist.appendHead(t);
- t1 = t->t1(); t2 = t->t2(); t3 = t->t3();
- v1 = t->v1(); v2 = t->v2(); v3 = t->v3();
- if (!IS_VISITED(v1)) {MARK_VISIT(v1); vlist.appendHead(v1);}
- if (!IS_VISITED(v2)) {MARK_VISIT(v2); vlist.appendHead(v2);}
- if (!IS_VISITED(v3)) {MARK_VISIT(v3); vlist.appendHead(v3);}
-
- if (!IS_VISITED(t->e1)) {MARK_VISIT(t->e1); elist.appendHead(t->e1);}
- if (!IS_VISITED(t->e2)) {MARK_VISIT(t->e2); elist.appendHead(t->e2);}
- if (!IS_VISITED(t->e3)) {MARK_VISIT(t->e3); elist.appendHead(t->e3);}
-
- if (t1 != NULL && !IS_BIT(t1,2)) {MARK_BIT(t1,2); todo.appendHead(t1);}
- if (t2 != NULL && !IS_BIT(t2,2)) {MARK_BIT(t2,2); todo.appendHead(t2);}
- if (t3 != NULL && !IS_BIT(t3,2)) {MARK_BIT(t3,2); todo.appendHead(t3);}
- }
-
- ve = new List;
-
- FOREACHVVVERTEX((&(vlist)), v, n) {UNMARK_VISIT(v); if ((az = v->z) > Mz) {Mz=az; hv = v;}}
- Mz = DBL_MAX;
- FOREACHVEEDGE((&(elist)), e, n) {UNMARK_VISIT(e); if (e->hasVertex(hv) && e->length() != 0) ve->appendHead(e);}
- FOREACHVTTRIANGLE((&(tlist)), t, n) UNMARK_BIT(t, 2);
-
- FOREACHVEEDGE(ve, e, n)
- if ((az = (hv->z - e->oppositeVertex(hv)->z)/e->length()) < Mz) {Mz=az; fe = e;}
- delete(ve);
-
- if (fe == NULL) fe = hv->e0;
- if (fe->t1 == NULL || fe->t2 == NULL) return NULL;
-
- return (FABS(fe->t1->getNormal().z) > FABS(fe->t2->getNormal().z))?(fe->t1):(fe->t2);
-}
-
-
-/////// Computes boundaries and handles ///////////
-
-void Basic_TMesh::eulerUpdate()
-{
- Vertex *v, *w;
- Edge *e;
- Triangle *t, *s;
- List triList;
- Node *n;
- n_boundaries = n_shells = n_handles = 0;
-
- FOREACHTRIANGLE(t, n) UNMARK_BIT(t, 5);
- FOREACHVERTEX(v, n) UNMARK_BIT(v, 5);
-
- FOREACHTRIANGLE(t, n) if (!IS_BIT(t, 5))
- {
- n_shells++;
- triList.appendHead(t);
- MARK_BIT(t, 5);
-
- while (triList.numels())
- {
- t = (Triangle *)triList.popHead();
- if ((s = t->t1()) != NULL && !IS_BIT(s, 5)) { triList.appendHead(s); MARK_BIT(s, 5); }
- if ((s = t->t2()) != NULL && !IS_BIT(s, 5)) { triList.appendHead(s); MARK_BIT(s, 5); }
- if ((s = t->t3()) != NULL && !IS_BIT(s, 5)) { triList.appendHead(s); MARK_BIT(s, 5); }
- }
- }
- FOREACHTRIANGLE(t, n) UNMARK_BIT(t, 5);
-
- bool hasBoundary = false;
-
- FOREACHEDGE(e, n) if (e->isOnBoundary()){
- hasBoundary = true;
- MARK_BIT(e->v1, 5);
- MARK_BIT(e->v2, 5);
- }
-
- if (hasBoundary){
- FOREACHVERTEX(v, n) if (IS_BIT(v, 5))
- {
- n_boundaries++;
- for (w = v; IS_BIT(w, 5); w = w->nextOnBoundary()) UNMARK_BIT(w, 5);
- }
- }
-
- n_handles = (E.numels() - V.numels() - T.numels() + 2 * n_shells - n_boundaries) / 2;
- d_boundaries = d_handles = d_shells = 0;
-}
-
-
-// Makes the mesh equivalent to a topological disk.
-// Edges and vertices are duplicated when necessary.
-
-void Basic_TMesh::openToDisk()
-{
- Triangle *t = (Triangle *)T.head()->data;
- Triangle *s;
- List triList, *ve;
- Vertex *v, *w;
- Edge *e, *ne;
- Node *n;
- triList.appendHead(t);
- MARK_BIT(t,3);
-
- while(triList.numels())
- {
- t = (Triangle *)triList.popHead();
- if ((s = t->t1()) != NULL && !IS_BIT(s,3))
- {triList.appendTail(s); MARK_BIT(s,3); MARK_BIT(t->e1,3);}
- if ((s = t->t2()) != NULL && !IS_BIT(s,3))
- {triList.appendTail(s); MARK_BIT(s,3); MARK_BIT(t->e2,3);}
- if ((s = t->t3()) != NULL && !IS_BIT(s,3))
- {triList.appendTail(s); MARK_BIT(s,3); MARK_BIT(t->e3,3);}
- }
- FOREACHTRIANGLE (t, n) UNMARK_BIT(t, 3);
-
- FOREACHVERTEX(v, n) v->info = new List;
-
- FOREACHEDGE(e, n) if (!IS_BIT(e, 3))
- {
- ((List *)e->v1->info)->appendHead(e);
- ((List *)e->v2->info)->appendHead(e);
- }
-
- FOREACHVERTEX(v, n) if (((List *)v->info)->numels()==1) triList.appendHead(v);
- if (!triList.numels()) TMesh::error("Basic_TMesh::openToDisk: Couldn't find a root.\n");
-
- while(triList.numels())
- {
- v = (Vertex *)triList.popHead();
- ve = ((List *)v->info);
- if (ve->numels())
- {
- e = (Edge *)(ve->head()->data);
- MARK_BIT(e, 3);
- ve->popHead();
- w = e->oppositeVertex(v);
- ve = ((List *)w->info);
- ve->removeNode(e);
- if (ve->numels() == 1) triList.appendHead(w);
- }
- else
- {
- ve = v->VE();
- e = (Edge *)ve->head()->data; UNMARK_BIT(e, 3); ((List *)v->info)->appendHead(e);
- e = (Edge *)ve->head()->next()->data; UNMARK_BIT(e, 3); ((List *)v->info)->appendHead(e);
- delete(ve);
- }
- }
-
- FOREACHEDGE(e, n) if (!IS_BIT(e, 3) && !e->isOnBoundary())
- {
- ne = newEdge(e->v1, e->v2);
- ne->t1 = e->t1; e->t1 = NULL; E.appendHead(ne);
- ne->t1->replaceEdge(e, ne);
- }
-
- FOREACHEDGE(e, n) UNMARK_BIT(e, 3);
-
- FOREACHVERTEX(v, n) if (v->info) {delete(((List *)v->info)); v->info = NULL;}
- duplicateNonManifoldVertices();
- d_boundaries = d_handles = d_shells = 1;
-}
-
-
-//// Splits the edge 'e' by the point 'p'. ////
-
-Vertex *Basic_TMesh::splitEdge(Edge *e, Point *p, bool copy_mask)
-{
- if ((*p)==(*(e->v1))) return e->v1;
- if ((*p)==(*(e->v2))) return e->v2;
- Vertex *v3 = (e->t1 != NULL)?(e->t1->oppositeVertex(e)):(NULL);
- Vertex *v4 = (e->t2 != NULL)?(e->t2->oppositeVertex(e)):(NULL);
- Edge *be1 = (e->t1 != NULL)?(e->t1->nextEdge(e)):(NULL);
- Edge *be4 = (e->t2 != NULL)?(e->t2->prevEdge(e)):(NULL);
- Vertex *v = newVertex(p->x, p->y, p->z);
- Edge *ne = newEdge(v, e->v2);
- Edge *ne1 = (e->t1 != NULL)?(newEdge(v, v3)):(NULL);
- Edge *ne2 = (e->t2 != NULL)?(newEdge(v, v4)):(NULL);
- Triangle *nt1 = (e->t1 != NULL)?(newTriangle(ne1, ne,be1)):(NULL);
- Triangle *nt2 = (e->t2 != NULL)?(newTriangle(ne, ne2,be4)):(NULL);
-
- ne->t1 = nt1; ne->t2 = nt2;
- if (ne1 != NULL) {ne1->t1 = e->t1; ne1->t2 = nt1;}
- if (ne2 != NULL) {ne2->t1 = nt2; ne2->t2 = e->t2;}
- if (be1 != NULL) be1->replaceTriangle(e->t1, nt1);
- if (be4 != NULL) be4->replaceTriangle(e->t2, nt2);
- e->v2->e0 = (be1 != NULL)?(be1):(be4);
- e->v2 = v;
- v->e0 = e;
- if (e->t1 != NULL) e->t1->replaceEdge(be1, ne1);
- if (e->t2 != NULL) e->t2->replaceEdge(be4, ne2);
-
- if (copy_mask)
- {
- ne->mask = e->mask;
- if (nt1 != NULL) nt1->mask = e->t1->mask;
- if (nt2 != NULL) nt2->mask = e->t2->mask;
- }
-
- V.appendHead(v);
- E.appendHead(ne);
- if (ne1 != NULL) E.appendHead(ne1);
- if (ne2 != NULL) E.appendHead(ne2);
- if (nt1 != NULL) T.appendHead(nt1);
- if (nt2 != NULL) T.appendHead(nt2);
-
- return v;
-}
-
-
-//// Splits the trianlge 't' by the point 'p'. If 'corr' is TRUE ////
-//// the method does not perform the split if this causes the ////
-//// creation of a triangle with a vertex angle < MIN_ANG_TRI. ////
-
-Vertex *Basic_TMesh::splitTriangle(Triangle *t, Point *p, bool copy_mask)
-{
- Vertex *v1 = t->v1();
- Vertex *v2 = t->v2();
- Vertex *v3 = t->v3();
-
- Vertex *v = newVertex(p->x, p->y, p->z);
- Edge *ne1 = newEdge(v, v1);
- Edge *ne2 = newEdge(v, v2);
- Edge *ne3 = newEdge(v, v3);
- Triangle *nt1 = newTriangle(ne2, t->e3,ne3);
- Triangle *nt2 = newTriangle(ne3, t->e1,ne1);
- t->e3->replaceTriangle(t, nt1);
- t->e1->replaceTriangle(t, nt2);
- t->replaceEdge(t->e3, ne2);
- t->replaceEdge(t->e1, ne1);
- ne1->t1 = t; ne1->t2 = nt2;
- ne2->t1 = nt1; ne2->t2 = t;
- ne3->t1 = nt2; ne3->t2 = nt1;
- v->e0 = ne1;
-
- V.appendHead(v);
- E.appendHead(ne1);
- E.appendHead(ne2);
- E.appendHead(ne3);
- T.appendHead(nt1);
- T.appendHead(nt2);
-
- if (copy_mask)
- {
- nt1->mask = t->mask;
- nt2->mask = t->mask;
- }
-
- return v;
-}
-
-
-//////////////////////////////////////////////////////////////////
-// //
-// D E B U G AND WORK-IN-PROGRESS //
-// //
-//////////////////////////////////////////////////////////////////
-
-
-/////// Prints general information ///////////
-
-void Basic_TMesh::printReport()
-{
- eulerUpdate();
-
- TMesh::info("*** Basic_TMesh Report ***\n");
- TMesh::info("V: %d\n",V.numels());
- TMesh::info("E: %d\n",E.numels());
- TMesh::info("T: %d\n",T.numels());
-
- TMesh::info("Boundary: %d components.\n",boundaries());
- TMesh::info("Handles: %d.\n",handles());
- TMesh::info("Shells: %d.\n",shells());
-}
-
-
-// Unless there are bugs, the following should be exact ...
-
-bool Basic_TMesh::isInnerPoint(Point& p) const
-{
- if (T.numels() == 0) return false; // An ampty mesh does not enclose anything ...
-
- // We assume that the mesh is correctly oriented.
- Node *n;
- Vertex *v1, *v2, *v3;
- Triangle *t;
-
- // Ray casting along positive X direction
- Point p2(1, 0, 0);
- p2 += p;
- coord ad, min_distance = DBL_MAX;
- Point ip;
- Triangle *closest_triangle = NULL;
- Edge *e, *closest_edge = NULL;
- Vertex *closest_vertex = NULL;
-
- coord o1, o2, o3;
- FOREACHTRIANGLE(t, n)
- {
- v1 = t->v1(); v2 = t->v2(); v3 = t->v3();
- if (((v1->y > p.y && v2->y > p.y) || (v1->y < p.y && v2->y < p.y)) && ((v1->y > p.y && v3->y > p.y) || (v1->y < p.y && v3->y < p.y)))
- continue;
- if (((v1->z > p.z && v2->z > p.z) || (v1->z < p.z && v2->z < p.z)) && ((v1->z > p.z && v3->z > p.z) || (v1->z < p.z && v3->z < p.z)))
- continue;
- o1 = orient2D(p.y, p.z, v1->y, v1->z, v2->y, v2->z);
- o2 = orient2D(p.y, p.z, v2->y, v2->z, v3->y, v3->z);
- o3 = orient2D(p.y, p.z, v3->y, v3->z, v1->y, v1->z);
-
- if (o1 == 0 && o2 == 0 && o3 == 0) continue; // Degenerate triangle. Skip.
- else if (o1 == 0 && o2 == 0)
- {
- if ((ad = v2->x - p.x) == 0) return false; // Point is on surface
- else if (ad > 0 && adx - p.x) == 0) return false; // Point is on surface
- else if (ad > 0 && adx - p.x) == 0) return false; // Point is on surface
- else if (ad > 0 && ade2) : ((o2 == 0) ? (t->e3) : (t->e1));
- if ((p.y < e->v1->y && p.y < e->v2->y) || (p.y > e->v1->y && p.y > e->v2->y) ||
- (p.z < e->v1->z && p.z < e->v2->z) || (p.z > e->v1->z && p.z > e->v2->z)) continue;
- ip = Point::lineLineIntersection(p, p2, *e->v1, *e->v2);
- ad = ip.x - p.x;
- if (ad == 0) return false; // Point is on surface
- else if (ad > 0 && ad 0 && o2 > 0 && o3 > 0) || (o1 < 0 && o2 < 0 && o3 < 0))
- {
- ip = Point::linePlaneIntersection(p, p2, *v1, *v2, *v3);
- ad = ip.x - p.x;
- if (ad == 0) return false; // Point is on surface
- else if (ad > 0 && adVE();
- coord ad, mind = DBL_MAX;
- Point a = p - (*closest_vertex);
- FOREACHVEEDGE(ve, e, n)
- {
- Vertex *ov1 = e->oppositeVertex(closest_vertex);
- Point b = (*ov1) - (*closest_vertex);
- ad = (((a&b)*(a&b)) / ((b*b)*(a*a))) - 1;
- if (a*b < 0) ad = -ad;
- if (ad < mind) { mind = ad; closest_edge = e; }
- }
- delete ve;
- }
-
- // If cp is in the interior of an edge, select one of its incident triangles
- if (closest_edge != NULL)
- {
- if (closest_edge->isOnBoundary()) return false;
- Vertex *ov1 = closest_edge->t1->oppositeVertex(closest_edge);
- Vertex *ov2 = closest_edge->t2->oppositeVertex(closest_edge);
- coord o1 = p.exactOrientation(closest_edge->v1, closest_edge->v2, ov1);
- coord o2 = ov2->exactOrientation(closest_edge->v1, closest_edge->v2, ov1);
- closest_triangle = ((o1 >= 0 && o2 >= 0) || (o1 <= 0 && o2 <= 0)) ? (closest_edge->t2) : (closest_edge->t1);
- }
-
- // If closest point is in the interior of a triangle, just check orientation
- if (closest_triangle != NULL)
- {
- return (closest_triangle->getVector().x > 0);
- }
-
- return false;
-
- //if (!singular_case)
- //{
- // int parity = 0;
- // Point p2(1, 0, 0);
- // p2 += p;
- // FOREACHTRIANGLE(t, n)
- // {
- // v1 = t->v1(); v2 = t->v2(); v3 = t->v3();
- // if ((IS_BIT(v1, 5) == IS_BIT(v2, 5) && IS_BIT(v1, 5) == IS_BIT(v3, 5))) continue;
- // if ((IS_BIT(v1, 6) == IS_BIT(v2, 6) && IS_BIT(v1, 6) == IS_BIT(v3, 6))) continue;
- // coord o1 = orient2D(p.y, p.z, v1->y, v1->z, v2->y, v2->z);
- // coord o2 = orient2D(p.y, p.z, v2->y, v2->z, v3->y, v3->z);
- // coord o3 = orient2D(p.y, p.z, v3->y, v3->z, v1->y, v1->z);
- // if (o1 == 0 || o2 == 0 || o3 == 0) { singular_case = true; break; }
- // if ((o1 > 0 && o2 > 0 && o3 > 0) || (o1 < 0 && o2 < 0 && o3 < 0))
- // {
- // o1 = p.exactOrientation(v1, v2, v3);
- // if (o1 == 0) return false; // Point is on triangle
- // Point ip = Point::linePlaneIntersection(p, p2, v1, v2, v3);
- // if (ip.x>p.x)
- // {
- // if (o1 < 0) parity++; else if (o1 > 0) parity--;
- // }
- // }
- // }
- // if (!singular_case) return (parity == 1);
- //}
-
- // In case of singularity, revert to the following (slower) method
- // Pick the closest triangle
- //coord ad, min_d = DBL_MAX;
- //Triangle *gt;
- //FOREACHTRIANGLE(t, n) if ((ad = t->pointTriangleSquaredDistance(&p)) < min_d) { gt = t; min_d = ad; }
-
- //Edge *closest_edge = NULL;
- //Vertex *closest_vertex = NULL;
- //gt->pointTriangleSquaredDistance(&p, &closest_edge, &closest_vertex);
-
- //// If closest point is in the interior of gt, just check orientation
- //if (closest_edge == NULL) return (p.exactOrientation(gt->v1(), gt->v2(), gt->v3())<0);
-
- //// If cp is in the interior of an edge, check edge convexity (e->getConvexity())
- //if (closest_vertex == NULL) return (closest_edge->getConvexity() < 0);
-
- //// If cp is a vertex, find the triangle in VT whose normal is mostly aligned with (cp-p) and check orientation
- //Point normal = closest_vertex->getNormal(); // NOT ROBUST !!! This is an extremely particular case, but ...
- //return (((*closest_vertex-p)*normal)>0);
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/TMesh/triangle.cpp b/src/mesh_fix/src/TMesh/triangle.cpp
deleted file mode 100644
index 15fed33b7..000000000
--- a/src/mesh_fix/src/TMesh/triangle.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "triangle.h"
-#include
-
-namespace T_MESH
-{
-
-extern "C" double orient2d(double *, double *, double *);
-
-//////////////////// Constructor //////////////////////
-
-//!< AMF_ADD 1.1>
-Triangle::Triangle(){
- mask = 0;
- info = NULL;
-}
-
-Triangle::Triangle(Edge *a, Edge *b, Edge *c)
-{
- e1 = a;
- e2 = b;
- e3 = c;
- mask = 0;
- info = NULL;
-}
-
-
-//////////////////// Normal vector //////////////////////
-
-Point Triangle::getNormal() const
-{
- Vertex *va = v1(), *vb = v2(), *vc = v3();
- Point vd = (((*va)-(*vb))&((*vb)-(*vc)));
- coord l = vd.length();
-
- if (l == 0) return Point(0,0,0);
-
- return vd/l;
-}
-
-
-////// Directional vector ////////
-
-Point Triangle::getVector() const
-{
- Vertex *va = v1(), *vb = v2(), *vc = v3();
- return (((*va) - (*vb))&((*vb) - (*vc)));
-}
-
-
-/////////////////// Normal consistence check ////////////////////
-
-bool Triangle::checkAdjNor(const Triangle *t) const
-{
- Edge *e = commonEdge(t);
- if (e == NULL) return 1;
-
- Edge *ea = nextEdge(e);
- Edge *eb = t->nextEdge(e);
- if (ea->commonVertex(eb) == ea->commonVertex(e)) return 0;
-
- return 1;
-}
-
-
-//////////////////////// Triangle area /////////////////////////
-
-double Triangle::area() const
-{
- double a = e1->length(), b = e2->length(), c = e3->length();
- if (a==0.0 || b==0.0 || c==0.0) return 0.0;
- double p = (a+b+c)/2.0;
- p = p*(p-a)*(p-b)*(p-c); if (p<0) return 0.0;
- return sqrt(p);
-}
-
-
-/////////////////////// Triangle perimeter /////////////////////
-
-double Triangle::perimeter() const
-{
- return e1->length()+e2->length()+e3->length();
-}
-
-
-///////////// Barycenter ///////////////////////
-
-Point Triangle::getCenter() const
-{
- Point va = *v1(), vb = *v2(), vc = *v3();
- return (va+vb+vc)/3.0;
-}
-
-
-///////////////////////// Circlecenter /////////////////////////
-
-Point Triangle::getCircleCenter() const
-{
- Point va = *v1(), vb = *v2(), vc = *v3();
- Point q1 = vb-va;
- Point q2 = vc-va;
- Point n = q2&q1;
- Point m1 = e2->getMidPoint();
- Point m2 = e1->getMidPoint();
-
- return Point(n*va,q1*m1,q2*m2).linearSystem(n,q1,q2);
-}
-
-
-/////// Check wether the point is inside the triangle's bounding ball /////
-
-bool Triangle::inSphere(const Point *p) const
-{
- Point c = getCircleCenter();
- coord rad = c.squaredDistance(e1->v1);
-
- return (p->squaredDistance(&c) < rad);
-}
-
-
-//////////////////// Angle at a vertex /////////////////////
-
-double Triangle::getAngle(const Vertex *v) const
-{
- Vertex *va = v1(), *vb = v2(), *vc = v3();
- if (v == va) return v->getAngle(vb, vc);
- if (v == vb) return v->getAngle(va, vc);
- if (v == vc) return v->getAngle(vb, va);
-
- return -1.0;
-}
-
-
-/////////// Angle between the two directional vectors /////////
-
-double Triangle::getDAngle(const Triangle *t) const
-{
- Point thisNormal = getVector();
- Point otherNormal = t->getVector();
-
- if (thisNormal.isNull() || otherNormal.isNull()) return -1.0;
-
- return thisNormal.getAngle(otherNormal);
-}
-
-
-///////////// Distance from the plane of the triangle //////////////
-
-double Triangle::distanceFromPoint(const Point *p) const
-{
- return sqrt(TMESH_TO_DOUBLE(squaredDistanceFromPoint(p)));
-}
-
-///////////// Squared distance from the plane of the triangle //////////////
-
-coord Triangle::squaredDistanceFromPoint(const Point *p) const
-{
- Point CA = e1->toVector()&e2->toVector();
- coord CA2 = CA*CA;
-
- if (CA2 == 0) return -1.0;
- coord d = ((CA*(*p))-(CA*(*(e1->v1))));
-
- return (d*d)/CA2;
-}
-
-
-///////////// Distance of point from the triangle //////////////
-
-double Triangle::pointTriangleDistance(const Point *p, Point *cp) const
-{
- return sqrt(TMESH_TO_DOUBLE(pointTriangleSquaredDistance(p)));
-}
-
-
-///////////// Distance of point from the triangle //////////////
-
-coord Triangle::pointTriangleSquaredDistance(const Point *p, Edge **closest_edge, Vertex **closest_vertex) const
-{
- Vertex *va = v1(), *vb = v2(), *vc = v3();
- Point n(((*va)-(*vb))&((*vb)-(*vc)));
- if (n.x == 0 && n.y == 0 && n.z == 0) return -1.0;
-
- coord d1 = ((((*va)-(*vb))&((*vb)-(*p)))*n);
- coord d2 = ((((*vb)-(*vc))&((*vc)-(*p)))*n);
- coord d3 = ((((*vc)-(*va))&((*va)-(*p)))*n);
-
- if (d1 > 0 && d2 > 0 && d3 > 0) // Closest point in inner triangle
- {
- if (closest_edge != NULL) *closest_edge = NULL;
- if (closest_vertex != NULL) *closest_vertex = NULL;
- return squaredDistanceFromPoint(p);
- }
-
- if (d2 < 0) { va = vb; vb = vc; if (closest_edge != NULL) *closest_edge = e3; }
- else if (d3 < 0) { vb = va; va = vc; if (closest_edge != NULL) *closest_edge = e1; }
- else if (closest_edge != NULL) *closest_edge = e2;
-
- Point i(p->projection(va,vb));
- Point p1(i-(*va)); Point p2(i-(*vb));
-
- if (p1*p2 < 0) // Closest point on interior of one edge
- {
- return i.squaredDistance(p);
- }
-
- d1=p1.squaredLength(); d2=p2.squaredLength();
- if (d1 < d2) { if (closest_vertex != NULL) *closest_vertex = va; return p->squaredDistance(va); }
- else { if (closest_vertex != NULL) *closest_vertex = vb; return p->squaredDistance(vb); }
-}
-
-
-/////////// Projection of point 'p' on the plane of the triangle /////
-
-Point Triangle::project(const Point *p) const
-{
- Point n = getVector();
- if (n.isNull()) return INFINITE_POINT;
- return Point::linePlaneIntersection(*p, (*p) + n, *(v1()), *(v2()), *(v3()));
-}
-
-bool Triangle::isExactlyDegenerate() const
-{
- return (!v1()->exactMisalignment((v2()), (v3())));
-}
-
-//// get longest edge /////
-
-Edge *Triangle::getLongestEdge() const
-{
- coord l1 = e1->squaredLength();
- coord l2 = e2->squaredLength();
- coord l3 = e3->squaredLength();
- if (l1>=l2 && l1>=l3) return e1;
- if (l2>=l1 && l2>=l3) return e2;
- return e3;
-}
-
-Edge *Triangle::getCapEdge() const
-{
- Edge *e;
- e = e1; if (Point::pointInInnerSegment(oppositeVertex(e), e->v1, e->v2)) return e;
- e = e2; if (Point::pointInInnerSegment(oppositeVertex(e), e->v1, e->v2)) return e;
- e = e3; if (Point::pointInInnerSegment(oppositeVertex(e), e->v1, e->v2)) return e;
- return NULL;
-}
-
-///////////// Overlap check ////////////////////
-
-bool Triangle::overlaps() const
-{
- return (e1->overlaps() || e2->overlaps() || e3->overlaps());
-}
-
-Vertex *Triangle::commonVertex(const Triangle *t2) const
-{
- if (hasVertex(t2->v1())) return t2->v1();
- if (hasVertex(t2->v2())) return t2->v2();
- if (hasVertex(t2->v3())) return t2->v3();
- return NULL;
-}
-
-
-/// Debug
-
-void Triangle::printTriangle(FILE *fp) const
-{
- v1()->printPoint(fp);
- v2()->printPoint(fp);
- v3()->printPoint(fp);
-}
-
-
-// This can be made more efficient, I guess...
-
-bool Triangle::intersects(const Triangle *t2, bool justproper) const
-{
- Vertex *v11, *v12, *v13, *v21, *v22, *v23;
-
- if (justproper)
- {
- // This works for non-degenerate triangles. Not sure it will work for degeneracies too.
- v11 = v1(); v12 = v2(); v13 = v3();
- v21 = t2->v1(); v22 = t2->v2(); v23 = t2->v3();
- Vertex *eq1 = ((*v11) == (*v21)) ? (v21) : (((*v11) == (*v22)) ? (v22) : (((*v11) == (*v23)) ? (v23) : (NULL)));
- Vertex *eq2 = ((*v12) == (*v21)) ? (v21) : (((*v12) == (*v22)) ? (v22) : (((*v12) == (*v23)) ? (v23) : (NULL)));
- Vertex *eq3 = ((*v13) == (*v21)) ? (v21) : (((*v13) == (*v22)) ? (v22) : (((*v13) == (*v23)) ? (v23) : (NULL)));
- if (eq1 && eq2 && eq3) return false; // Triangles coincide
- Edge *ce1 = NULL, *ce2 = NULL;
- if (eq1 && eq2) { ce1 = e2; ce2 = (t2->e1->hasVertices(eq1, eq2)) ? (t2->e1) : ((t2->e2->hasVertices(eq1, eq2)) ? (t2->e2) : (t2->e3)); }
- if (eq2 && eq3) { ce1 = e3; ce2 = (t2->e1->hasVertices(eq3, eq2)) ? (t2->e1) : ((t2->e2->hasVertices(eq3, eq2)) ? (t2->e2) : (t2->e3)); }
- if (eq3 && eq1) { ce1 = e1; ce2 = (t2->e1->hasVertices(eq3, eq1)) ? (t2->e1) : ((t2->e2->hasVertices(eq3, eq1)) ? (t2->e2) : (t2->e3)); }
- if (ce1)
- {
- Vertex *ov = t2->oppositeVertex(ce2);
- return (ov->exactOrientation(v11, v12, v13) == 0 && ov->exactSameSideOnPlane(oppositeVertex(ce1), ce1->v1, ce1->v2));
- }
- Vertex *cv1 = NULL, *cv2 = NULL;
- if (eq1) { cv1 = v11; cv2 = eq1; }
- if (eq2) { cv1 = v12; cv2 = eq2; }
- if (eq3) { cv1 = v13; cv2 = eq3; }
- if (cv1) // If they share a vertex, intersection occurs if the opposite edge intersect the triangle
- {
- Edge *ee1 = oppositeEdge(cv1), *ee2 = t2->oppositeEdge(cv2);
- return (Point::segmentIntersectsTriangle(ee1->v1, ee1->v2, v21, v22, v23) ||
- Point::segmentIntersectsTriangle(ee2->v1, ee2->v2, v11, v12, v13));
- }
- }
- else
- {
- Edge *ce = commonEdge(t2);
- if (ce) // If they share an edge, intersection occurs only if t1 and t2 overlap
- {
- Vertex *ov = t2->oppositeVertex(ce);
- return (ov->exactOrientation(v1(), v2(), v3()) == 0 && ov->exactSameSideOnPlane(oppositeVertex(ce), ce->v1, ce->v2));
- }
-
- Vertex *cv = commonVertex(t2);
- v11 = v1(); v12 = v2(); v13 = v3();
- v21 = t2->v1(); v22 = t2->v2(); v23 = t2->v3();
- if (cv) // If they share a vertex, intersection occurs if the opposite edge intersect the triangle
- {
- Edge *ee1 = oppositeEdge(cv), *ee2 = t2->oppositeEdge(cv);
- return (Point::segmentIntersectsTriangle(ee1->v1, ee1->v2, v21, v22, v23) ||
- Point::segmentIntersectsTriangle(ee2->v1, ee2->v2, v11, v12, v13));
- }
- }
-
- // Fast reject by bounding box
- coord mx = MIN(v11->x, MIN(v13->x, v12->x));
- if (v21->x < mx && v22->x < mx && v23->x < mx) return false;
- mx = MAX(v11->x, MAX(v13->x, v12->x));
- if (v21->x > mx && v22->x > mx && v23->x > mx) return false;
- mx = MIN(v11->y, MIN(v13->y, v12->y));
- if (v21->y < mx && v22->y < mx && v23->y < mx) return false;
- mx = MAX(v11->y, MAX(v13->y, v12->y));
- if (v21->y > mx && v22->y > mx && v23->y > mx) return false;
- mx = MIN(v11->z, MIN(v13->z, v12->z));
- if (v21->z < mx && v22->z < mx && v23->z < mx) return false;
- mx = MAX(v11->z, MAX(v13->z, v12->z));
- if (v21->z > mx && v22->z > mx && v23->z > mx) return false;
-
- // Calculate relative orientations
- coord o11 = v11->exactOrientation(v21, v22, v23);
- coord o12 = v12->exactOrientation(v21, v22, v23);
- coord o13 = v13->exactOrientation(v21, v22, v23);
- if ((o11>0 && o12>0 && o13>0) || (o11<0 && o12<0 && o13<0)) return false; // t1 above/below t2
- coord o21 = v21->exactOrientation(v11, v12, v13);
- coord o22 = v22->exactOrientation(v11, v12, v13);
- coord o23 = v23->exactOrientation(v11, v12, v13);
- if ((o21>0 && o22>0 && o23>0) || (o21<0 && o22<0 && o23<0)) return false; // t2 above/below t1
-
- if (o11 == 0 && o12 == 0 && o13 == 0) // t1 and t2 are coplanar
- {
- if (Point::innerSegmentsCross(v11, v12, v21, v22)) return true;
- if (Point::innerSegmentsCross(v11, v12, v22, v23)) return true;
- if (Point::innerSegmentsCross(v11, v12, v23, v21)) return true;
- if (Point::innerSegmentsCross(v12, v13, v21, v22)) return true;
- if (Point::innerSegmentsCross(v12, v13, v22, v23)) return true;
- if (Point::innerSegmentsCross(v12, v13, v23, v21)) return true;
- if (Point::innerSegmentsCross(v13, v11, v21, v22)) return true;
- if (Point::innerSegmentsCross(v13, v11, v22, v23)) return true;
- if (Point::innerSegmentsCross(v13, v11, v23, v21)) return true;
- return (
- Point::pointInTriangle(v11, v21, v22, v23) ||
- Point::pointInTriangle(v12, v21, v22, v23) ||
- Point::pointInTriangle(v13, v21, v22, v23) ||
- Point::pointInTriangle(v21, v11, v12, v13) ||
- Point::pointInTriangle(v22, v11, v12, v13) ||
- Point::pointInTriangle(v23, v11, v12, v13));
- }
- else return (
- Point::segmentIntersectsTriangle(v11, v12, v21, v22, v23, o11, o12) ||
- Point::segmentIntersectsTriangle(v12, v13, v21, v22, v23, o12, o13) ||
- Point::segmentIntersectsTriangle(v13, v11, v21, v22, v23, o13, o11) ||
- Point::segmentIntersectsTriangle(v21, v22, v11, v12, v13, o21, o22) ||
- Point::segmentIntersectsTriangle(v22, v23, v11, v12, v13, o22, o23) ||
- Point::segmentIntersectsTriangle(v23, v21, v11, v12, v13, o23, o21));
-}
-
-} //namespace T_MESH
diff --git a/src/mesh_fix/src/TMesh/vertex.cpp b/src/mesh_fix/src/TMesh/vertex.cpp
deleted file mode 100644
index a06cebae8..000000000
--- a/src/mesh_fix/src/TMesh/vertex.cpp
+++ /dev/null
@@ -1,682 +0,0 @@
-/****************************************************************************
-* TMesh *
-* *
-* Consiglio Nazionale delle Ricerche *
-* Istituto di Matematica Applicata e Tecnologie Informatiche *
-* Sezione di Genova *
-* IMATI-GE / CNR *
-* *
-* Authors: Marco Attene *
-* Copyright(C) 2013: IMATI-GE / CNR *
-* All rights reserved. *
-* *
-* This program is dual-licensed as follows: *
-* *
-* (1) You may use TMesh as 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. *
-* In this case the 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 (http://www.gnu.org/licenses/gpl.txt) *
-* for more details. *
-* *
-* (2) You may use TMesh as part of a commercial software. In this case a *
-* proper agreement must be reached with the Authors and with IMATI-GE/CNR *
-* based on a proper licensing contract. *
-* *
-****************************************************************************/
-
-#include "vertex.h"
-#include "edge.h"
-#include "triangle.h"
-#include
-#include
-
-namespace T_MESH
-{
-
-//////////////////// Constructors ////////////////////////
-
-Vertex::Vertex() : Point()
-{
- e0 = NULL;
- mask = 0;
-}
-
-
-Vertex::Vertex(const coord& a, const coord& b, const coord& c) : Point(a,b,c)
-{
- e0 = NULL;
- mask = 0;
-}
-
-
-Vertex::Vertex(const Point *p) : Point(p->x, p->y, p->z)
-{
- e0 = NULL;
- mask = 0;
-}
-
-
-Vertex::Vertex(const Point& p) : Point(p.x, p.y, p.z)
-{
- e0 = NULL;
- mask = 0;
-}
-
-///////////////////// Destructor ///////////////////////
-
-Vertex::~Vertex()
-{
-}
-
-
-/////////////// VE relation ////////////////////////////
-
-List *Vertex::VE() const
-{
- Triangle *t;
- Edge *e;
- Vertex *v;
- List *ve = new List();
-
- if (e0 == NULL) return ve;
-
-
-
- e = e0;
- do
- {
- ve->appendTail(e);
- v = e->oppositeVertex(this);
- t = e->leftTriangle(this);
- if (t == NULL) break;
- e = t->oppositeEdge(v);
- } while (e != e0);
-
- if (e == e0 && ve->numels() > 1) return ve;
-
- ve->popHead();
- e = e0;
-
- do
- {
- ve->appendHead(e);
- v = e->oppositeVertex(this);
- t = e->rightTriangle(this);
- if (t == NULL) break;
- e = t->oppositeEdge(v);
- } while (e != e0);
-
- return ve;
-}
-
-/////////////// VV relation ////////////////////////////
-
-List *Vertex::VV() const
-{
- Triangle *t;
- Edge *e;
- Vertex *v;
- List *vv = new List();
-
- if (e0 == NULL) return vv;
-
- e = e0;
- do
- {
- v = e->oppositeVertex(this);
- vv->appendTail(v);
- t = e->leftTriangle(this);
- if (t == NULL) break;
- e = t->oppositeEdge(v);
- } while (e != e0);
-
- if (e == e0 && vv->numels() > 1) return vv;
-
- vv->popHead();
- e = e0;
- do
- {
- v = e->oppositeVertex(this);
- vv->appendHead(v);
- t = e->rightTriangle(this);
- if (t == NULL) break;
- e = t->oppositeEdge(v);
- } while (e != e0);
-
- return vv;
-}
-
-/////////////// VT relation ////////////////////////////
-
-List *Vertex::VT() const
-{
- Triangle *t;
- Edge *e;
- Vertex *v;
- List *vt = new List();
-
- if (e0 == NULL) return vt;
-
- e = e0;
- do
- {
- v = e->oppositeVertex(this);
- t = e->leftTriangle(this);
- if (t == NULL) break;
- vt->appendTail(t);
- e = t->oppositeEdge(v);
- } while (e != e0);
-
- if (e == e0 && vt->numels() > 1) return vt;
-
- e = e0;
- do
- {
- v = e->oppositeVertex(this);
- t = e->rightTriangle(this);
- if (t == NULL) break;
- vt->appendHead(t);
- e = t->oppositeEdge(v);
- } while (e != e0);
-
- return vt;
-}
-
-/////////////// Returns the edge (this,v2) ////////////////
-
-Edge *Vertex::getEdge(const Vertex *v2) const
-{
- List *ve = VE();
- Node *m;
- Edge *e;
-
- FOREACHVEEDGE(ve, e, m)
- if (e->oppositeVertex(this) == v2) {delete(ve); return e;}
-
- delete(ve);
- return NULL;
-}
-
-
-///////////// Returns the vertex valence ///////////////////////
-
-int Vertex::valence() const
-{
- List *ve = VE();
- int n = ve->numels();
- delete(ve);
- return n;
-}
-
-/////////////// Checks the boundary ////////////////////////////
-
-int Vertex::isOnBoundary() const
-{
- Triangle *t;
- Edge *e;
- Vertex *v;
-
- if (e0 == NULL) return 0;
-
- e = e0;
- do
- {
- v = e->oppositeVertex(this);
- t = e->leftTriangle(this);
- if (t == NULL) return 1;
- e = t->oppositeEdge(v);
- } while (e != e0);
-
- return 0;
-}
-
-
-/////////////// Next boundary edge ////////////////////////////
-
-Edge *Vertex::nextBoundaryEdge() const
-{
- Triangle *t;
- Edge *e;
- Vertex *v;
-
- if (e0 == NULL) return NULL;
-
- e = e0;
- do
- {
- v = e->oppositeVertex(this);
- t = e->leftTriangle(this);
- if (t == NULL) return e;
- e = t->oppositeEdge(v);
- } while (e != e0);
-
- return NULL;
-}
-
-
-/////////////// Next boundary vertex ////////////////////////////
-
-Vertex *Vertex::nextOnBoundary() const
-{
- Edge *e = nextBoundaryEdge();
- if (e != NULL) return e->oppositeVertex(this);
-
- return NULL;
-}
-
-
-/////////////// Previous boundary edge ////////////////////////////
-
-Edge *Vertex::prevBoundaryEdge() const
-{
- Triangle *t;
- Edge *e;
- Vertex *v;
-
- if (e0 == NULL) return NULL;
-
- e = e0;
- do
- {
- v = e->oppositeVertex(this);
- t = e->rightTriangle(this);
- if (t == NULL) return e;
- e = t->oppositeEdge(v);
- } while (e != e0);
-
- return NULL;
-}
-
-
-/////////////// Previous boundary vertex ////////////////////////////
-
-Vertex *Vertex::prevOnBoundary() const
-{
- Edge *e = prevBoundaryEdge();
- if (e != NULL) return e->oppositeVertex(this);
-
- return NULL;
-}
-
-//// TRUE iff vertex neighborhood is a flat disk. Always FALSE for boundary vertices.
-bool Vertex::isFlat() const
-{
- List *ve = VE();
- Node *n;
- Edge *e;
-
- FOREACHVEEDGE(ve, e, n)
- if (e->getConvexity() != 0) { delete ve; return false; }
-
- delete ve;
- return true;
-}
-
-//// TRUE iff vertex neighborhood is made of either two flat halfdisks or one flat halfdisk on a rectilinear boundary.
-bool Vertex::isDoubleFlat(Edge **e1, Edge **e2) const
-{
- List *ve = VE();
- Node *n;
- Edge *e;
- int nne = 0;
- *e1 = *e2 = NULL;
-
- FOREACHVEEDGE(ve, e, n)
- if (e->getConvexity() != 0)
- {
- if (++nne > 2) { delete ve; return false; }
- else if (nne == 1) *e1 = e;
- else *e2 = e;
- }
- delete ve;
- if (nne == 0) return true; // This means that vertex is flat
- if (nne == 1) return false; // This should not be possible, but just in case...
- return (!((*e1)->oppositeVertex(this)->exactMisalignment(this, (*e2)->oppositeVertex(this))));
-}
-
-//// Unlinks the vertex if it is either Flat() or DoubleFlat(). On success, the function returns TRUE,
-//// the vertex neighborhood is retriangulated, and the geometric realization does not change.
-bool Vertex::removeIfRedundant(bool check_neighborhood)
-{
- Edge *e, *e1 = NULL, *e2 = NULL;
- if (!isDoubleFlat(&e1, &e2)) return false;
-
- Node *n;
- Vertex *vo1, *vo2;
- List *ve;
-
- if (check_neighborhood)
- {
- ve = VT();
- Triangle *t;
- FOREACHVTTRIANGLE(ve, t, n) if (t->isExactlyDegenerate()) { delete ve; return false; }
- delete ve;
- ve = VE();
- FOREACHVEEDGE(ve, e, n) if (e->overlaps()) { delete ve; return false; }
- } else ve = VE();
-
- if (e1 != NULL) ve->removeNode(e1); // means isDoubleFlat()
- if (e2 != NULL) ve->removeNode(e2); // means isDoubleFlat()
- if (e2 != NULL && *e1->oppositeVertex(this) == *e2->oppositeVertex(this)) { delete ve; return false; }
-
- while (1)
- {
- FOREACHVEEDGE(ve, e, n)
- {
- vo1 = e->t1->oppositeVertex(e);
- vo2 = e->t2->oppositeVertex(e);
- if (!e->v1->exactSameSideOnPlane(e->v2, vo1, vo2) && vo1->exactMisalignment(e->v1, vo2) && vo1->exactMisalignment(e->v2, vo2))
- {
- if (!e->swap()) { delete ve; return false; }
- break;
- }
- }
- if (n != NULL) ve->removeCell(n);
- else break;
- }
-
- if (e1 != NULL) e = e1; // means isDoubleFlat()
- else if (ve->numels() == 3) e = (Edge *)ve->head()->data;
- else
- {
- FOREACHVEEDGE(ve, e, n)
- if (!e->t1->oppositeVertex(e)->exactMisalignment(this, e->t2->oppositeVertex(e))) break;
- if (n == NULL) { delete ve; return false; } // Should not happen...
- else e = (Edge *)((n == ve->head()) ? (ve->tail()) : (n->prev()))->data;
- }
- delete ve;
-
- if (e->v1 == this) e->invert();
- if (e->collapseOnV1() == NULL) return false; // This is a very rare case. Should be treated, but does not hurt too much.
- else return true;
-}
-
-///// Vertex normal as weighted average of the incident triangle normals ////
-///// The weight is the incidence angle. ////
-///// Possible degenerate triangles are not taken into account. ////
-
-Point Vertex::getNormal() const
-{
- List *vt = VT();
- Node *n;
- Triangle *t;
- coord pa;
- Point tnor, ttn;
-
- FOREACHVTTRIANGLE(vt, t, n)
- {
- pa = t->getAngle(this);
- ttn = t->getNormal();
- if (!ttn.isNull()) tnor = tnor+(ttn*pa);
- }
- delete(vt);
-
- if (tnor.isNull()) return Point(0,0,0);
-
- tnor.normalize();
- return tnor;
-}
-
-
-////////// Returns the angle between the two boundary edges ////////
-
-double Vertex::getBoundaryAngle() const
-{
- Edge *e1 = prevBoundaryEdge();
- Edge *e2 = nextBoundaryEdge();
- if (e1 == NULL || e2 == NULL) return -1.0;
- Vertex *v1 = e1->oppositeVertex(this);
- Vertex *v2 = e2->oppositeVertex(this);
- double ang = getAngle(v1, v2);
-
- return ang;
-}
-
-
-////////// Returns the discriminant for triangulation ////////
-
-double Vertex::getAngleForTriangulation() const
-{
- Edge *e1 = prevBoundaryEdge();
- Edge *e2 = nextBoundaryEdge();
- if (e1 == NULL || e2 == NULL) return DBL_MAX;
- Triangle *t1 = e1->getBoundaryTriangle();
- Triangle *t2 = e2->getBoundaryTriangle();
- Vertex *v1 = e1->oppositeVertex(this);
- Vertex *v2 = e2->oppositeVertex(this);
- if ((*v2)==(*v1)) return -2;
- if (distance(v1)*distance(v2) == 0.0) return -1;
-
- double ang = getAngle(v1, v2);
- if (ang == M_PI) return 3*M_PI;
- if (ang == 0) return 0;
-
- Edge e3(v1,v2);
- Triangle t(e1,e2,&e3);
- double da1 = t.getDAngle(t1);
- double da2 = t.getDAngle(t2);
-
- if (da1==M_PI && da2==M_PI) return (DBL_MAX/2.0);
- if (da1==M_PI || da2==M_PI) return (DBL_MAX/4.0);
-
- return da1+da2+ang;
-}
-
-
-////////// Returns the AP discriminant for triangulation ////////
-
-double Vertex::getAngleOnAveragePlane(Point *nor) const
-{
- Edge *e1 = prevBoundaryEdge();
- Edge *e2 = nextBoundaryEdge();
- if (e1 == NULL || e2 == NULL) return DBL_MAX;
- Vertex *v1 = e1->oppositeVertex(this);
- Vertex *v2 = e2->oppositeVertex(this);
- Point p, p1, p2;
- p1.setValue(v1);
- p2.setValue(v2);
- p.setValue(this);
- p.project(nor);
- p1.project(nor);
- p2.project(nor);
- if (p.distance(p1)*p.distance(p2) == 0.0)
- {
- TMesh::warning("getAngleOnAveragePlane: coincident projections\n");
- return 0.0;
- }
- double ang = p.getAngle(&p1, &p2);
- if (nor->side3D(&p1, &p, &p2) < 0) ang = -(ang-(2*M_PI));
-
- return ang;
-}
-
-
-///// mean curvature at the vertex: sum of signed dihedral angles ////
-
-double Vertex::totalDihedralAngle() const
-{
- List *ve = VE();
- double mc = 0;
- Edge *e;
- Node *n;
-
- FOREACHVEEDGE(ve, e, n)
- if (e->isOnBoundary()) {delete(ve); return DBL_MAX;}
- else mc -= (e->dihedralAngle()-M_PI);
- mc /= ve->numels();
-
- delete(ve);
-
- return mc;
-}
-
-
-///// Sum of all the incident angles ////
-
-double Vertex::totalAngle() const
-{
- List *ve = VE();
- double ta = 0.0;
- Edge *e;
- Node *n;
-
- FOREACHVEEDGE(ve, e, n)
- if (e->isOnBoundary()) {delete(ve); return -1.0;}
- else ta += e->leftTriangle(this)->getAngle(this);
-
- delete(ve);
-
- return ta;
-}
-
-
-/////// Voronoi area around the vertex ///////////////////
-
-double Vertex::voronoiArea() const
-{
- List *vt = VT();
- Node *n;
- Triangle *t;
- double va = 0.0;
-
- FOREACHVTTRIANGLE(vt, t, n) va += t->area();
- delete(vt);
-
- return va/3.0;
-}
-
-
-// Closes the gap starting from this vertex
-// If 'check_geom' is true, the zipping stops
-// whether the coordinates of the vertices to
-// be zipped are not equal.
-
-int Vertex::zip(const bool check_geom)
-{
- Node *n;
- Edge *e;
-
- List *ve = VE();
- Edge *be1 = (Edge *)ve->head()->data;
- Edge *be2 = (Edge *)ve->tail()->data;
- delete(ve);
- if (!be1->isOnBoundary() || !be2->isOnBoundary()) return 0;
- Vertex *ov1 = be1->oppositeVertex(this);
- Vertex *ov2 = be2->oppositeVertex(this);
-
- if (check_geom && ((*ov1)!=(*ov2))) return 0;
-
- if (ov1 != ov2)
- {
- ve = ov2->VE();
- FOREACHVEEDGE(ve, e, n) e->replaceVertex(ov2, ov1);
- delete(ve);
- ov2->e0 = NULL;
- }
-
- Triangle *t = (be2->t1!=NULL)?(be2->t1):(be2->t2);
- t->replaceEdge(be2, be1);
- be1->replaceTriangle(NULL, t);
- be2->v1=be2->v2=NULL;
- e0 = ov1->e0 = be1;
- return 1+ov1->zip(check_geom);
-}
-
-
-/////// Progressive Mesh: Vertex split ///////////////////
-
-//Edge *Vertex::inverseCollapse(Vertex *v2, Vertex *v3, Vertex *v4)
-//{
-// Edge *e, *e1, *e2=NULL, *e3=NULL, *e4;
-// Triangle *t1, *t2, *ta1, *ta4;
-// Node *n;
-// Vertex *tmp;
-//
-// List *ve = VE();
-// FOREACHVEEDGE(ve, e, n)
-// {
-// tmp = e->oppositeVertex(this);
-// if (tmp == v3) e2 = e;
-// else if (tmp == v4) e3 = e;
-// }
-//
-// if (!e2 || !e3) {delete(ve); return NULL;}
-//
-// ta1 = e2->rightTriangle(this);
-// ta4 = e3->leftTriangle(this);
-//
-// FOREACHVEEDGE(ve, e, n) if (e == e3) break;
-// FOREACHNODECIRCULAR((*ve), n, n)
-// {
-// e = ((Edge *)n->data);
-// if (e == e2) break;
-// else e->replaceVertex(this, v2);
-// }
-// delete(ve);
-//
-// e = new Edge(this, v2);
-// e1 = new Edge(v2, v3);
-// e4 = new Edge(v2, v4);
-// t1 = newTriangle(e, e1, e2);
-// t2 = newTriangle(e, e3, e4);
-//
-// e->t1 = t1; e->t2 = t2;
-// e2->replaceTriangle(ta1, t1);
-// e3->replaceTriangle(ta4, t2);
-// if (ta1) ta1->replaceEdge(e2, e1);
-// if (ta4) ta4->replaceEdge(e3, e4);
-// e1->t1 = t1; e1->t2 = ta1;
-// e4->t1 = ta4; e4->t2 = t2;
-// v2->e0 = e0 = e;
-//
-//// Point p = (*this)-((*v2)-(*this));
-//// x = p.x; y = p.y; z = p.z;
-//
-// return e;
-//}
-
-
-/////// Progressive Mesh: Vertex split ///////////////////
-
-Edge *Vertex::inverseCollapse(Vertex *v2, Edge *e, Edge *e1, Edge *e2, Edge *e3, Edge *e4, Triangle *t1, Triangle *t2)
-{
- Triangle *ta1, *ta4;
- Node *n;
- Edge *f;
-
- ta1 = e2->rightTriangle(this);
- ta4 = e3->leftTriangle(this);
-
- List *ve = VE();
- FOREACHVEEDGE(ve, f, n) if (f == e3) break;
- FOREACHNODECIRCULAR((*ve), n, n)
- {
- f = ((Edge *)n->data);
- if (f == e2) break;
- else f->replaceVertex(this, v2);
- }
- delete(ve);
-
- e->v1 = this; e->v2 = v2;
- e1->v1 = v2; e1->v2 = e2->oppositeVertex(this);
- e4->v1 = v2; e4->v2 = e3->oppositeVertex(this);
- t1->e1 = e; t1->e2 = e1; t1->e3 = e2;
- t2->e1 = e; t2->e2 = e3; t2->e3 = e4;
-
- e->t1 = t1; e->t2 = t2;
- e2->replaceTriangle(ta1, t1);
- e3->replaceTriangle(ta4, t2);
- if (ta1) ta1->replaceEdge(e2, e1);
- if (ta4) ta4->replaceEdge(e3, e4);
- e1->t1 = t1; e1->t2 = ta1;
- e4->t1 = ta4; e4->t2 = t2;
- v2->e0 = e0 = e;
-
- return e;
-}
-
-} //namespace T_MESH
diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt
index c73d16799..81a7740ba 100644
--- a/src/slic3r/CMakeLists.txt
+++ b/src/slic3r/CMakeLists.txt
@@ -214,8 +214,6 @@ set(SLIC3R_GUI_SOURCES
Utils/Http.hpp
Utils/FixModelByWin10.cpp
Utils/FixModelByWin10.hpp
- Utils/FixModelByMeshFix.cpp
- Utils/FixModelByMeshFix.hpp
Utils/OctoPrint.cpp
Utils/OctoPrint.hpp
Utils/Duet.cpp
@@ -262,7 +260,7 @@ add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES})
encoding_check(libslic3r_gui)
-target_link_libraries(libslic3r_gui libslic3r avrdude cereal imgui GLEW::GLEW OpenGL::GL hidapi libcurl meshfix ${wxWidgets_LIBRARIES})
+target_link_libraries(libslic3r_gui libslic3r avrdude cereal imgui GLEW::GLEW OpenGL::GL hidapi libcurl ${wxWidgets_LIBRARIES})
if (MSVC)
target_link_libraries(libslic3r_gui Setupapi.lib)
diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp
index d28e1a64e..c3aaa2f4e 100644
--- a/src/slic3r/GUI/GUI_Factories.cpp
+++ b/src/slic3r/GUI/GUI_Factories.cpp
@@ -694,20 +694,8 @@ wxMenuItem* MenuFactory::append_menu_item_fix_through_netfabb(wxMenu* menu)
if (!is_windows10())
return nullptr;
wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _L("Fix through the Netfabb"), "",
- [](wxCommandEvent&) { obj_list()->repair_mesh(ObjectList::rmaNetfabb); }, "", menu,
- []() {return plater()->can_repair_mesh(); }, m_parent);
-
- return menu_item;
-}
-
-
-wxMenuItem* MenuFactory::append_menu_item_fix_through_meshfix(wxMenu* menu)
-{
- if (is_windows10())
- return nullptr;
- wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _L("Fix through MeshFix (experimental)"), "",
- [](wxCommandEvent&) { obj_list()->repair_mesh(ObjectList::rmaMeshfix); }, "", menu,
- []() {return plater()->can_repair_mesh(); }, m_parent);
+ [](wxCommandEvent&) { obj_list()->fix_through_netfabb(); }, "", menu,
+ []() {return plater()->can_fix_through_netfabb(); }, m_parent);
return menu_item;
}
@@ -935,7 +923,6 @@ void MenuFactory::create_common_object_menu(wxMenu* menu)
append_menu_item_scale_selection_to_fit_print_volume(menu);
append_menu_item_fix_through_netfabb(menu);
- append_menu_item_fix_through_meshfix(menu);
append_menu_item_simplify(menu);
append_menu_items_mirror(menu);
}
diff --git a/src/slic3r/GUI/GUI_Factories.hpp b/src/slic3r/GUI/GUI_Factories.hpp
index 26799c733..0c478a97b 100644
--- a/src/slic3r/GUI/GUI_Factories.hpp
+++ b/src/slic3r/GUI/GUI_Factories.hpp
@@ -92,7 +92,6 @@ private:
wxMenuItem* append_menu_item_printable(wxMenu* menu);
void append_menu_items_osx(wxMenu* menu);
wxMenuItem* append_menu_item_fix_through_netfabb(wxMenu* menu);
- wxMenuItem* append_menu_item_fix_through_meshfix(wxMenu* menu);
wxMenuItem* append_menu_item_simplify(wxMenu* menu);
void append_menu_item_export_stl(wxMenu* menu);
void append_menu_item_reload_from_disk(wxMenu* menu);
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 21f0ad81a..7d11113ac 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -28,7 +28,6 @@
#include
#include "slic3r/Utils/FixModelByWin10.hpp"
-#include "slic3r/Utils/FixModelByMeshFix.hpp"
#ifdef __WXMSW__
#include "wx/uiaction.h"
@@ -917,7 +916,7 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me
{
if (is_windows10() && m_objects_model->HasWarningIcon(item) &&
mouse_pos.x > 2 * wxGetApp().em_unit() && mouse_pos.x < 4 * wxGetApp().em_unit())
- repair_mesh(rmaNetfabb);
+ fix_through_netfabb();
else if (evt_context_menu)
show_context_menu(evt_context_menu); // show context menu for "Name" column too
}
@@ -4032,7 +4031,7 @@ void ObjectList::rename_item()
update_name_in_model(item);
}
-void ObjectList::repair_mesh(ObjectList::REPAIR_MESH_ALG alg)
+void ObjectList::fix_through_netfabb()
{
// Do not fix anything when a gizmo is open. There might be issues with updates
// and what is worse, the snapshot time would refer to the internal stack.
@@ -4052,28 +4051,28 @@ void ObjectList::repair_mesh(ObjectList::REPAIR_MESH_ALG alg)
// clear selections from the non-broken models if any exists
// and than fill names of models to repairing
if (vol_idxs.empty()) {
-#if !FIX_MESH_ALWAYS
+#if !FIX_THROUGH_NETFABB_ALWAYS
for (int i = int(obj_idxs.size())-1; i >= 0; --i)
if (object(obj_idxs[i])->get_repaired_errors_count() == 0)
obj_idxs.erase(obj_idxs.begin()+i);
-#endif // FIX_MESH_ALWAYS
+#endif // FIX_THROUGH_NETFABB_ALWAYS
for (int obj_idx : obj_idxs)
model_names.push_back(object(obj_idx)->name);
}
else {
ModelObject* obj = object(obj_idxs.front());
-#if !FIX_MESH_ALWAYS
+#if !FIX_THROUGH_NETFABB_ALWAYS
for (int i = int(vol_idxs.size()) - 1; i >= 0; --i)
if (obj->get_repaired_errors_count(vol_idxs[i]) == 0)
vol_idxs.erase(vol_idxs.begin() + i);
-#endif // FIX_MESH_ALWAYS
+#endif // FIX_THROUGH_NETFABB_ALWAYS
for (int vol_idx : vol_idxs)
model_names.push_back(obj->volumes[vol_idx]->name);
}
auto plater = wxGetApp().plater();
- auto fix_and_update_progress = [this, plater, model_names, alg](const int obj_idx, const int vol_idx,
+ auto fix_and_update_progress = [this, plater, model_names](const int obj_idx, const int vol_idx,
int model_idx,
wxProgressDialog& progress_dlg,
std::vector& succes_models,
@@ -4092,19 +4091,8 @@ void ObjectList::repair_mesh(ObjectList::REPAIR_MESH_ALG alg)
plater->clear_before_change_mesh(obj_idx);
std::string res;
- bool result = false;
- switch (alg) {
- case rmaNetfabb:
- result = fix_model_by_win10_sdk_gui(*(object(obj_idx)), vol_idx, progress_dlg, msg, res);
- break;
- case rmaMeshfix:
- result = fix_model_by_meshfix(*(object(obj_idx)), vol_idx, progress_dlg, msg, res);
- break;
- default:
- break;
- }
- if (!result) return false;
-
+ if (!fix_model_by_win10_sdk_gui(*(object(obj_idx)), vol_idx, progress_dlg, msg, res))
+ return false;
wxGetApp().plater()->changed_mesh(obj_idx);
plater->changed_mesh(obj_idx);
@@ -4120,19 +4108,19 @@ void ObjectList::repair_mesh(ObjectList::REPAIR_MESH_ALG alg)
return true;
};
- Plater::TakeSnapshot snapshot(plater, _L("Repair model mesh"));
+ Plater::TakeSnapshot snapshot(plater, _L("Fix through NetFabb"));
// Open a progress dialog.
- wxProgressDialog progress_dlg(_L("Repair model mesh"), "", 100, find_toplevel_parent(plater),
+ wxProgressDialog progress_dlg(_L("Fixing through NetFabb"), "", 100, find_toplevel_parent(plater),
wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
int model_idx{ 0 };
if (vol_idxs.empty()) {
int vol_idx{ -1 };
for (int obj_idx : obj_idxs) {
-#if !FIX_MESH_ALWAYS
+#if !FIX_THROUGH_NETFABB_ALWAYS
if (object(obj_idx)->get_repaired_errors_count(vol_idx) == 0)
continue;
-#endif // FIX_MESH_ALWAYS
+#endif // FIX_THROUGH_NETFABB_ALWAYS
if (!fix_and_update_progress(obj_idx, vol_idx, model_idx, progress_dlg, succes_models, failed_models))
break;
model_idx++;
@@ -4165,7 +4153,7 @@ void ObjectList::repair_mesh(ObjectList::REPAIR_MESH_ALG alg)
}
if (msg.IsEmpty())
msg = _L("Repairing was canceled");
- plater->get_notification_manager()->push_notification(NotificationType::RepairMeshFinished, NotificationManager::NotificationLevel::PrintInfoShortNotificationLevel, boost::nowide::narrow(msg));
+ plater->get_notification_manager()->push_notification(NotificationType::NetfabbFinished, NotificationManager::NotificationLevel::PrintInfoShortNotificationLevel, boost::nowide::narrow(msg));
}
void ObjectList::simplify()
diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp
index d9f1b7ea6..51d69eaee 100644
--- a/src/slic3r/GUI/GUI_ObjectList.hpp
+++ b/src/slic3r/GUI/GUI_ObjectList.hpp
@@ -37,7 +37,7 @@ typedef std::pair t_layer_height_range;
typedef std::map t_layer_config_ranges;
// Manifold mesh may contain self-intersections, so we want to always allow fixing the mesh.
-#define FIX_MESH_ALWAYS 1
+#define FIX_THROUGH_NETFABB_ALWAYS 1
namespace GUI {
@@ -367,8 +367,7 @@ public:
void instances_to_separated_objects(const int obj_idx);
void split_instances();
void rename_item();
- enum REPAIR_MESH_ALG{rmaNetfabb, rmaMeshfix};
- void repair_mesh(REPAIR_MESH_ALG alg);
+ void fix_through_netfabb();
void simplify();
void update_item_error_icon(const int obj_idx, int vol_idx) const ;
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
index 263419cbe..18e58efb8 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
@@ -130,7 +130,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
if (m_fix_throught_netfab_bitmap->GetBitmap().GetRefData() == wxNullBitmap.GetRefData())
return;
- wxGetApp().obj_list()->repair_mesh(ObjectList::rmaNetfabb);
+ wxGetApp().obj_list()->fix_through_netfabb();
update_warning_icon_state(wxGetApp().obj_list()->get_mesh_errors_info());
});
diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp
index e14dcb294..9265cb55e 100644
--- a/src/slic3r/GUI/NotificationManager.hpp
+++ b/src/slic3r/GUI/NotificationManager.hpp
@@ -109,8 +109,8 @@ enum class NotificationType
// Give user advice to simplify object with big amount of triangles
// Contains ObjectID for closing when object is deleted
SimplifySuggestion,
- // information about finished model repairing (blocking proccess)
- RepairMeshFinished,
+ // information about netfabb is finished repairing model (blocking proccess)
+ NetfabbFinished,
// Short meesage to fill space between start and finish of export
ExportOngoing,
};
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index df9eb2104..81c57bae0 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1935,7 +1935,7 @@ struct Plater::priv
bool can_split_to_volumes() const;
bool can_arrange() const;
bool can_layers_editing() const;
- bool can_repair_mesh() const;
+ bool can_fix_through_netfabb() const;
bool can_simplify() const;
bool can_set_instance_to_object() const;
bool can_mirror() const;
@@ -4642,15 +4642,15 @@ bool Plater::priv::can_delete_all() const
return !model.objects.empty();
}
-bool Plater::priv::can_repair_mesh() const
+bool Plater::priv::can_fix_through_netfabb() const
{
std::vector obj_idxs, vol_idxs;
sidebar->obj_list()->get_selection_indexes(obj_idxs, vol_idxs);
-#if FIX_MESH_ALWAYS
+#if FIX_THROUGH_NETFABB_ALWAYS
// Fixing always.
return ! obj_idxs.empty() || ! vol_idxs.empty();
-#else // FIX_MESH_ALWAYS
+#else // FIX_THROUGH_NETFABB_ALWAYS
// Fixing only if the model is not manifold.
if (vol_idxs.empty()) {
for (auto obj_idx : obj_idxs)
@@ -4664,7 +4664,7 @@ bool Plater::priv::can_repair_mesh() const
if (model.objects[obj_idx]->get_repaired_errors_count(vol_idx) > 0)
return true;
return false;
-#endif // FIX_MESH_ALWAYS
+#endif // FIX_THROUGH_NETFABB_ALWAYS
}
bool Plater::priv::can_simplify() const
@@ -6848,7 +6848,7 @@ bool Plater::can_delete_all() const { return p->can_delete_all(); }
bool Plater::can_increase_instances() const { return p->can_increase_instances(); }
bool Plater::can_decrease_instances() const { return p->can_decrease_instances(); }
bool Plater::can_set_instance_to_object() const { return p->can_set_instance_to_object(); }
-bool Plater::can_repair_mesh() const { return p->can_repair_mesh(); }
+bool Plater::can_fix_through_netfabb() const { return p->can_fix_through_netfabb(); }
bool Plater::can_simplify() const { return p->can_simplify(); }
bool Plater::can_split_to_objects() const { return p->can_split_to_objects(); }
bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); }
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index a50fd66f9..f59f138d4 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -309,7 +309,7 @@ public:
bool can_increase_instances() const;
bool can_decrease_instances() const;
bool can_set_instance_to_object() const;
- bool can_repair_mesh() const;
+ bool can_fix_through_netfabb() const;
bool can_simplify() const;
bool can_split_to_objects() const;
bool can_split_to_volumes() const;
diff --git a/src/slic3r/Utils/FixModelByMeshFix.cpp b/src/slic3r/Utils/FixModelByMeshFix.cpp
deleted file mode 100644
index 150b7c103..000000000
--- a/src/slic3r/Utils/FixModelByMeshFix.cpp
+++ /dev/null
@@ -1,403 +0,0 @@
-#include "tmesh.h"
-
-#include "FixModelByMeshFix.hpp"
-#include "libslic3r/TriangleMesh.hpp"
-#include "libslic3r/Model.hpp"
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-#include "libslic3r/Model.hpp"
-#include "libslic3r/Print.hpp"
-#include "libslic3r/PresetBundle.hpp"
-#include "libslic3r/Format/3mf.hpp"
-#include "../GUI/GUI.hpp"
-#include "../GUI/I18N.hpp"
-#include "../GUI/MsgDialog.hpp"
-
-#include
-#include
-
-namespace Slic3r {
-
-class RepairCanceledException: public std::exception {
-public:
- const char* what() const throw () {
- return "Model repair has been cancelled";
- }
-};
-
-class RepairFailedException: public std::exception {
-public:
- const char* what() const throw () {
- return "Model repair has failed";
- }
-};
-
-namespace detail {
-
-using namespace T_MESH;
-
-static int ensure_tmesh_initialization = (TMesh::init(), 0);
-
-double closestPair(List *bl1, List *bl2, Vertex **closest_on_bl1, Vertex **closest_on_bl2)
- {
- Node *n, *m;
- Vertex *v, *w;
- double adist, mindist = DBL_MAX;
-
- FOREACHVVVERTEX(bl1, v, n)
- FOREACHVVVERTEX(bl2, w, m)
- if ((adist = w->squaredDistance(v)) < mindist)
- {
- mindist = adist;
- *closest_on_bl1 = v;
- *closest_on_bl2 = w;
- }
-
- return mindist;
-}
-
-bool joinClosestComponents(Basic_TMesh *tin)
- {
- Vertex *v, *w, *gv, *gw;
- Triangle *t, *s;
- Node *n;
- List triList, boundary_loops, *one_loop;
- List **bloops_array;
- int i, j, numloops;
-
- // Mark triangles with connected component's unique ID
- i = 0;
- FOREACHVTTRIANGLE((&(tin->T)), t, n) t->info = NULL;
- FOREACHVTTRIANGLE((&(tin->T)), t, n) if (t->info == NULL)
- {
- i++;
- triList.appendHead(t);
- t->info = new intWrapper(i);
-
- while (triList.numels())
- {
- t = (Triangle *)triList.popHead();
- if ((s = t->t1()) != NULL && s->info == NULL) {triList.appendHead(s); s->info = new intWrapper(i);}
- if ((s = t->t2()) != NULL && s->info == NULL) {triList.appendHead(s); s->info = new intWrapper(i);}
- if ((s = t->t3()) != NULL && s->info == NULL) {triList.appendHead(s); s->info = new intWrapper(i);}
- }
- }
-
- if (i<2)
- {
- FOREACHVTTRIANGLE((&(tin->T)), t, n) t->info = NULL;
- // JMesh::info("Mesh is a single component. Nothing done.");
- return false;
- }
-
- FOREACHVTTRIANGLE((&(tin->T)), t, n)
- {
- t->v1()->info = t->v2()->info = t->v3()->info = t->info;
- }
-
- FOREACHVVVERTEX((&(tin->V)), v, n) if (!IS_VISITED2(v) && v->isOnBoundary())
- {
- w = v;
- one_loop = new List;
- do
- {
- one_loop->appendHead(w); MARK_VISIT2(w);
- w = w->nextOnBoundary();
- }while (w != v);
- boundary_loops.appendHead(one_loop);
- }
- FOREACHVVVERTEX((&(tin->V)), v, n) UNMARK_VISIT2(v);
-
- bloops_array = (List **)boundary_loops.toArray();
- numloops = boundary_loops.numels();
-
- double adist,
- mindist = DBL_MAX;
-
- gv = NULL;
- for (i = 0; i < numloops; i++)
- for (j = 0; j < numloops; j++)
- if (((Vertex*) bloops_array[i]->head()->data)->info != ((Vertex*) bloops_array[j]->head()->data)->info)
- {
- adist = closestPair(bloops_array[i], bloops_array[j], &v, &w);
- if (adist < mindist) {
- mindist = adist;
- gv = v;
- gw = w;
- }
- }
-
- if (gv != NULL)
- tin->joinBoundaryLoops(gv, gw, 1, 0);
-
- FOREACHVTTRIANGLE((&(tin->T)), t, n)
- t->info = NULL;
- FOREACHVVVERTEX((&(tin->V)), v, n)
- v->info = NULL;
-
- free(bloops_array);
- while ((one_loop = (List*) boundary_loops.popHead()) != NULL)
- delete one_loop;
-
- return (gv != NULL);
-}
-
-class Basic_TMesh_Adapter: public Basic_TMesh {
-public:
- void load_indexed_triangle_set(const indexed_triangle_set &its) {
-
- for (const auto &vertex : its.vertices) {
- this->V.appendTail(this->newVertex(vertex.x(), vertex.y(), vertex.z()));
- }
-
- int nv = this->V.numels();
- Node *n = this->V.head();
- ExtVertex **tmp = (ExtVertex**) malloc(sizeof(ExtVertex*) * nv);
- for (int index = 0; index < nv; ++index) {
- tmp[index] = new ExtVertex(static_cast(n->data));
- n = n->next();
- }
-
- for (const auto &face : its.indices) {
- if (face.x() == face.y() || face.y() == face.z() || face.z() == face.x()) {
- continue;
- }
- this->CreateIndexedTriangle(tmp, face.x(), face.y(), face.z());
- }
-
- closeLoadingSession(this->T.numels(), tmp, false);
- }
-
- indexed_triangle_set to_indexed_triangle_set() {
- indexed_triangle_set out;
- out.vertices.resize(this->V.numels());
- out.indices.resize(this->T.numels());
-
- Node *n = this->V.head();
- for (int vertex_idx = 0; vertex_idx < this->V.numels(); ++vertex_idx) {
- T_MESH::Vertex *v = static_cast(n->data);
- out.vertices[vertex_idx] = Vec3f { float(v->x), float(v->y), float(v->z) };
- n = n->next();
- //store vertex index in the first coord, makes export of faces simple (inspired by saveOBJ method)
- v->x = vertex_idx;
- }
-
- n = this->T.head();
- for (int face_idx = 0; face_idx < this->T.numels(); ++face_idx) {
- T_MESH::Triangle *t = static_cast(n->data);
- out.indices[face_idx] = Vec3i { int(t->v1()->x), int(t->v2()->x), int(t->v3()->x) };
- n = n->next();
- }
-
- return out;
- }
-
- bool meshclean_single_iteration(int inner_loops, const std::atomic &canceled) {
- bool ni, nd;
- Triangle *t;
- Node *m;
-
- nd = strongDegeneracyRemoval(inner_loops);
- if (canceled)
- throw RepairCanceledException();
- deselectTriangles();
- invertSelection();
- ni = strongIntersectionRemoval(inner_loops);
- if (canceled)
- throw RepairCanceledException();
- if (ni && nd) {
- FOREACHTRIANGLE(t, m)
- if (t->isExactlyDegenerate())
- ni = false;
- if (ni)
- return true;
- }
-
- return false;
- }
-
-private:
-
- void closeLoadingSession(int loaded_faces, ExtVertex **tmp, bool triangulate) {
- int i, nv = this->V.numels();
- if (tmp != NULL)
- {
- for (i = 0; i < nv; i++)
- delete (tmp[i]);
- free(tmp);
- }
- fixConnectivity();
- this->d_boundaries = this->d_handles = this->d_shells = 1;
- }
-};
-
-}
-
-bool fix_model_by_meshfix(ModelObject &model_object, int volume_idx, wxProgressDialog &progress_dlg,
- const wxString &msg_header, std::string &fix_result) {
- std::mutex mtx;
- std::condition_variable condition;
- struct Progress {
- std::string message;
- int percent = 0;
- bool updated = false;
- } progress;
- std::atomic canceled = false;
- std::atomic finished = false;
-
- std::vector volumes;
- if (volume_idx == -1)
- volumes = model_object.volumes;
- else
- volumes.emplace_back(model_object.volumes[volume_idx]);
-
- // Executing the calculation in a background thread, so that the COM context could be created with its own threading model.
- // (It seems like wxWidgets initialize the COM contex as single threaded and we need a multi-threaded context).
- bool success = false;
- size_t ivolume = 0;
- auto on_progress = [&mtx, &condition, &ivolume, &volumes, &progress](const char *msg, unsigned prcnt) {
- std::unique_lock lock(mtx);
- progress.message = msg;
- progress.percent = (int) floor((float(prcnt) + float(ivolume) * 100.f) / float(volumes.size()));
- progress.updated = true;
- condition.notify_all();
- };
- auto worker_thread = boost::thread(
- [&model_object, &volumes, &ivolume, on_progress, &success, &canceled, &finished]() {
- try {
- std::vector meshes_repaired;
- meshes_repaired.reserve(volumes.size());
- for (ModelVolume *mv : volumes) {
- std::vector parts = its_split(mv->mesh().its);
- unsigned percent_per_part = 95 / parts.size();
- for (size_t part_idx = 0; part_idx < parts.size(); ++part_idx) {
- unsigned progress_part_base = part_idx * percent_per_part;
-
- detail::Basic_TMesh_Adapter tin { };
- on_progress(L("Loading source model"), progress_part_base);
- if (canceled)
- throw RepairCanceledException();
- tin.load_indexed_triangle_set(parts[part_idx]);
- tin.boundaries();
- on_progress(L("Join closest components"), unsigned(progress_part_base + 0.1 * percent_per_part));
- if (canceled)
- throw RepairCanceledException();
- joinClosestComponents(&tin);
- tin.deselectTriangles();
- tin.boundaries();
- // Keep only the largest component (i.e. with most triangles)
- on_progress(L("Remove smallest components"),
- unsigned(progress_part_base + 0.2 * percent_per_part));
- if (canceled)
- throw RepairCanceledException();
- tin.removeSmallestComponents();
-
- // Fill holes
- on_progress(L("Check holes"), unsigned(progress_part_base + 0.3 * percent_per_part));
- if (canceled)
- throw RepairCanceledException();
- if (tin.boundaries()) {
- on_progress(L("Patch small holes"),
- unsigned(progress_part_base + 0.4 * percent_per_part));
- if (canceled)
- throw RepairCanceledException();
- tin.fillSmallBoundaries(0, true);
- }
-
- on_progress(L("Geometry check"), unsigned(progress_part_base + 0.5 * percent_per_part));
- if (canceled)
- throw RepairCanceledException();
- // Run geometry correction
- if (!tin.boundaries()) {
- int iteration = 0;
- on_progress(L("Start iterative correction"),
- unsigned(progress_part_base + 0.55 * percent_per_part));
- tin.deselectTriangles();
- tin.invertSelection();
- bool fixed = false;
- while (iteration < 10 && !fixed) { //default constants taken from TMesh library
- fixed = tin.meshclean_single_iteration(3, canceled);
- on_progress(L("Fixing geometry"),
- progress_part_base
- + percent_per_part * std::min(0.9, 0.6 + iteration * 0.08)); // majority of objects will finish in 4 iterations
- if (canceled)
- throw RepairCanceledException();
- iteration++;
- }
- }
-
-// if (tin.boundaries() || tin.T.numels() == 0) {
-// throw RepairFailedException();
-// }
- parts[part_idx] = tin.to_indexed_triangle_set();
- }
-
- for (size_t part_idx = 1; part_idx < parts.size(); ++part_idx) {
- its_merge(parts[0], parts[part_idx]);
- }
-
- meshes_repaired.emplace_back(std::move(parts[0]));
- }
-
- for (size_t i = 0; i < volumes.size(); ++i) {
- volumes[i]->set_mesh(std::move(meshes_repaired[i]));
- volumes[i]->calculate_convex_hull();
- volumes[i]->set_new_unique_id();
- }
- model_object.invalidate_bounding_box();
- --ivolume;
- on_progress(L("Model repair finished"), 100);
- success = true;
- finished = true;
- } catch (RepairCanceledException& /* ex */) {
- canceled = true;
- finished = true;
- on_progress(L("Model repair canceled"), 100);
- } catch (std::exception &ex) {
- success = false;
- finished = true;
- on_progress(ex.what(), 100);
- }
- });
-
- while (!finished) {
- std::unique_lock lock(mtx);
- condition.wait_for(lock, std::chrono::milliseconds(250), [&progress] {
- return progress.updated;
- });
- // decrease progress.percent value to avoid closing of the progress dialog
- if (!progress_dlg.Update(progress.percent - 1, msg_header + _(progress.message)))
- canceled = true;
- else
- progress_dlg.Fit();
- progress.updated = false;
- }
-
- worker_thread.join();
-
- if (canceled) {
- // Nothing to show.
- } else if (success) {
- fix_result = "";
- } else {
- fix_result = progress.message;
- }
-
- return !canceled;
-}
-
-}
diff --git a/src/slic3r/Utils/FixModelByMeshFix.hpp b/src/slic3r/Utils/FixModelByMeshFix.hpp
deleted file mode 100644
index bde1530a9..000000000
--- a/src/slic3r/Utils/FixModelByMeshFix.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef SRC_SLIC3R_UTILS_FIXMODELBYMESHFIX_HPP_
-#define SRC_SLIC3R_UTILS_FIXMODELBYMESHFIX_HPP_
-
-#include
-#include
-
-class wxProgressDialog;
-
-namespace Slic3r {
-
-class Model;
-class ModelObject;
-class Print;
-
-bool fix_model_by_meshfix(ModelObject &model_object, int volume_idx, wxProgressDialog &progress_dlg,
- const wxString &msg_header, std::string &fix_result);
-
-}
-
-#endif /* SRC_SLIC3R_UTILS_FIXMODELBYMESHFIX_HPP_ */
diff --git a/src/slic3r/Utils/FixModelByWin10.cpp b/src/slic3r/Utils/FixModelByWin10.cpp
index dc50777dc..296c58622 100644
--- a/src/slic3r/Utils/FixModelByWin10.cpp
+++ b/src/slic3r/Utils/FixModelByWin10.cpp
@@ -326,8 +326,9 @@ public:
// fix_result containes a message if fixing failed
bool fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx, wxProgressDialog& progress_dialog, const wxString& msg_header, std::string& fix_result)
{
- std::mutex mtx;
- std::condition_variable condition;
+ std::mutex mutex;
+ std::condition_variable condition;
+ std::unique_lock lock(mutex);
struct Progress {
std::string message;
int percent = 0;
@@ -346,8 +347,8 @@ bool fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx, wxPro
// (It seems like wxWidgets initialize the COM contex as single threaded and we need a multi-threaded context).
bool success = false;
size_t ivolume = 0;
- auto on_progress = [&mtx, &condition, &ivolume, &volumes, &progress](const char *msg, unsigned prcnt) {
- std::unique_lock lock(mtx);
+ auto on_progress = [&mutex, &condition, &ivolume, &volumes, &progress](const char *msg, unsigned prcnt) {
+ std::lock_guard lk(mutex);
progress.message = msg;
progress.percent = (int)floor((float(prcnt) + float(ivolume) * 100.f) / float(volumes.size()));
progress.updated = true;
@@ -423,7 +424,6 @@ bool fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx, wxPro
}
});
while (! finished) {
- std::unique_lock lock(mtx);
condition.wait_for(lock, std::chrono::milliseconds(250), [&progress]{ return progress.updated; });
// decrease progress.percent value to avoid closing of the progress dialog
if (!progress_dialog.Update(progress.percent-1, msg_header + _(progress.message)))