diff --git a/.github/workflows/cmake-single-platform.yml b/.github/workflows/cmake-single-platform.yml
new file mode 100644
index 0000000..c2fb718
--- /dev/null
+++ b/.github/workflows/cmake-single-platform.yml
@@ -0,0 +1,43 @@
+# This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage.
+# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml
+name: CMake on a single platform
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+env:
+ # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
+ BUILD_TYPE: Release
+
+jobs:
+ build:
+ # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
+ # You can convert this to a matrix build if you need cross-platform coverage.
+ # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install deps
+ run: sudo apt install -y libopengl-dev libgl1-mesa-dev libxrandr-dev libxi-dev libxinerama-dev libgl-dev libxcursor-dev libmpfr-dev libmpfrc++-dev libblas-dev liblapack-dev
+
+ - name: Configure CMake
+ # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
+ # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
+ run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_VISUALIZATION=OFF
+
+ - name: Build
+ # Build your program with the given configuration
+ run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
+
+ - name: Build tests
+ run: cmake --build ${{github.workspace}}/build --target penner_tests --config ${{env.BUILD_TYPE}}
+
+ - name: Test
+ working-directory: ${{github.workspace}}/build
+ run: ctest --output-on-failure --build-config ${{env.BUILD_TYPE}}
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8959ef6..3eb56a1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,8 +4,11 @@ project(PennerOptimization)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_compile_options(-fPIC)
+add_compile_options(-Wno-register)
set(DIR_EXT "${CMAKE_CURRENT_SOURCE_DIR}/ext")
+list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+
# Set options if top level
if (PROJECT_IS_TOP_LEVEL)
# Options to generate python bindings
@@ -26,17 +29,34 @@ if (PROJECT_IS_TOP_LEVEL)
option(BUILD_CURVATURE_METRIC_TESTS "Build tests" ON)
option(CHECK_VALIDITY "Check validity pre and post conditions" ON)
+
# Set default libigl and suitesparse options
option(LIBIGL_PREDICATES "Use Predicates" ON)
- set ( SUITESPARSE_ENABLE_PROJECTS "suitesparse_config;cholmod;spqr" )
+ #set ( SUITESPARSE_ENABLE_PROJECTS "suitesparse_config;cholmod;spqr" )
option ( SUITESPARSE_USE_CUDA OFF )
endif()
+set ( SUITESPARSE_ENABLE_PROJECTS "${SUITESPARSE_ENABLE_PROJECTS};suitesparse_config;cholmod" CACHE STRING "" FORCE)
list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
-include(boost)
include(eigen)
+include(boost)
+# create a fake BoostConfig.cmake before libigl runs and force Boost_DIR
+# to it so ignore_package (which uses no FORCE) cannot override it.
+set(_fake_boost_dir "${CMAKE_BINARY_DIR}/cmake/FakeBoost")
+file(MAKE_DIRECTORY "${_fake_boost_dir}")
+file(WRITE "${_fake_boost_dir}/BoostConfig.cmake"
+ "set(Boost_FOUND TRUE)\nset(Boost_system_FOUND TRUE)\nset(Boost_thread_FOUND TRUE)\n")
+file(WRITE "${_fake_boost_dir}/BoostConfigVersion.cmake"
+ "set(PACKAGE_VERSION 1.83.0)\nset(PACKAGE_VERSION_COMPATIBLE TRUE)\nset(PACKAGE_VERSION_EXACT FALSE)\n")
+set(Boost_DIR "${_fake_boost_dir}" CACHE PATH "" FORCE)
+
+if(BUILD_CURVATURE_METRIC_TESTS)
+ include(Catch2)
+ include(CTest)
+endif()
+
# Optionally get multiprecision libraries
if(USE_MULTIPRECISION OR USE_MULTIPRECISION_OVERLAY)
# Turning this on activates mpfr in the conformal code
@@ -55,7 +75,7 @@ endif()
if (USE_COMISO)
add_compile_definitions(USE_COMISO)
set(LIBIGL_COPYLEFT_CORE ON CACHE BOOL "" FORCE)
- #se. (LIBIGL_COPYLEFT_COMISO ON CACHE BOOL "" FORCE)
+ #set(LIBIGL_COPYLEFT_COMISO ON CACHE BOOL "" FORCE)
#option(LIBIGL_COPYLEFT_COMISO "Use COSIMO" ON)
#set(COMISO_ENABLE_SUITESPARSE_DEFAULT OFF)
set(COMISO_NO_INSTALL ON)
@@ -90,15 +110,14 @@ endif()
# conformal ideal delaunay library
if(USE_SUITESPARSE)
add_compile_definitions(USE_SUITESPARSE)
- set(SUITESPARSE_LIBS
+ list(APPEND SUITESPARSE_LIBS
SuiteSparse::SuiteSparseConfig
- SuiteSparse::SPQR
+ #SuiteSparse::SPQR
SuiteSparse::CHOLMOD
)
endif()
# Get external libraries
-include(boost)
include(conformal_ideal_delaunay)
include(libigl)
include(spectra)
@@ -110,7 +129,7 @@ find_package(HDF5 REQUIRED COMPONENTS CXX)
# get optimization library
if (USE_UV_OPTIMIZATION)
add_compile_definitions(USE_UV_OPTIMIZATION)
- include(symmetric-dirichlet)
+ include(seamless-optimization)
else()
include(json)
endif()
diff --git a/LICENSE.GPL b/LICENSE.GPL
new file mode 100644
index 0000000..53d1f3d
--- /dev/null
+++ b/LICENSE.GPL
@@ -0,0 +1,675 @@
+ 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/LICENSE.MPL2 b/LICENSE.MPL2
new file mode 100644
index 0000000..14e2f77
--- /dev/null
+++ b/LICENSE.MPL2
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/README.md b/README.md
index 4429531..e7afa80 100644
--- a/README.md
+++ b/README.md
@@ -81,6 +81,87 @@ To engender future work in this exciting direction, we provide a library `Penner
2. Various energy functionals and constrained optimization methods for meshes with Penner coordinates
3. Layout and refinement methods to generate a parameterization for a mesh from arbitrary Penner coordinates, i.e., the parameterization is an embedding in the uv plane of the metric defined by the Penner coordinate.
+### Library Structure
+
+- Field
+ - Cross Field: Methods for generating cross fields as represented by four rotationally symmetric tangent vectors.
+ - Facet Field: Methods for generating cross fields using legacy facet field file representations.
+ - Field: Methods to generate field directions and cones from an nrosy field. (TODO: Move rosy and combing field functions here)
+ - Forms: Methods for creating and manipulating one forms on a surface, represented as anti-symmetric halfedge values.
+ - Frame Field: TODO: move assorted functions here to appropriate locations
+ - Intrinsic Field: TODO: Needs cleanup
+- Optimization
+ - Core: Underlying methods for differentiable intrinsic metrics, including (a) area and angle values, and (b) length, Penner, shear, and conformal coordinates.
+ - Area: Methods to compute the area of triangles from intrinsic lengths
+ - Common: TODO
+ - Cone Metric: Core representation of a differentiable intrinsic metric on an underlying halfedge mesh
+ - Constraint: Methods to compute triangle inequality and differentiable cone angle constraints.
+ - Flip Matrix Generator: Data structure to iteratively compute the change of coordinate matrix for intrinsic flips
+ - Globals: (TODO: Put structs in relevant files)
+ - Projection: Methods to project a metric conformally to cone constraints, and to project metric coordinate vectors to the tangent space of the constraint submanifold.
+ - Reparametrization: Methods for changing edge and interior barycentric coordinates as determined by hyperbolic edge translations. (TODO: This name is pretty confusing in a parameterization library. Change to something better like `barycentric`, and move to parameterization)
+ - Shear: Methods to compute the shear coordinates of a metric from Penner coordinates and shear coordinate bases, linearly independent from the conformal scaling space.
+ - Metric Optimization: Methods for optimizing distortion energies for an intrinsic metric with constraints
+ - Convergence: (TODO: a single function; move somewhere else)
+ - Energies: Differentiable per-face energy functions with gradients for metric optimization
+ - Energy Functor: Class for differentiable distortion measures supporting evaluation, gradients, and Hessians
+ - Energy Weights: Methods to scale per-element values by element weights
+ - Explicit Optimization: Methods to optimize a metric with angle constraints using an explicit basis complimentary to the conformal scaling space.
+ - Implicit Optimization: Method to optimize distortion with constraints using a walk-on-manifold approach in a full space of metric coordinates using projection
+ - Nonlinear Optimization: Methods to perform advanced nonlinear optimization, including conjugate gradient and L-BFGS-B
+ - Parameterization: (TODO: move to top level. This is fundamental and common code.)
+ - Interpolation: Data structures to compute pointwise maps between two intrinsic metrics.
+ - Layout: Methods to layout a uv parameterization determined by intrinsic lengths (TODO: cleanup and documentation)
+ - Refinement: Methods to refine a triangulation with an accompanying overlay layout sufficiently to ensure the parametrization does not have inverted elements. (TODO: replace `refinement` with `simplification` or something of this sort; check what is in the paper)
+ - Translation: Method to compute hyperbolic translations determining a continuous map between two intrinsic metrics
+ - Triangulation: Methods for triangulating self overlapping polygons in the plane
+ - Util: TODO: Mostly utility for unit tests and validation. Redistribute this code.
+- Holonomy: Library for parametrizing surfaces with full seamless constraints with arbitrary holonomy signatures
+ - Core: Basic utilities for tracking dual loops on a surface
+ - Boundary Basis: Basis loops for boundary alignment constraints
+ - Common: Assorted utilities
+ - Dual Lengths: Compute lengths of dual edges on a surface (TODO: move)
+ - Dual Loop: Data structures for representing dual loops on a surface with efficient queries of edge and path intersections
+ - Dual Segment: Minimal representation of dual paths on a surface as list of atomic face crossings
+ - Homology Basis: Construct homology basis loops for a surface.
+ - Quality: Compute triangle quality measures on a mesh (TODO: move)
+ - Viewer: Assorted viewers
+ - Holonomy:
+ - Cones: Compute cones, as well as related queries and modification heuristics (TODO: move to field, and consolidate cone code here)
+ - Constraints: Holonomy angle constraints, including cone and dual loop constraints.
+ - Holonomy: Compute holonomy of dual loops on a surface with metric
+ - Marked Penner Cone Metric: Differentiable cone metric with full holonomy signature constraints
+ - Newton: Modified least squares Newton method for holonomy angle constraints
+ - Rotation Form: Method to compute the rotation of a field across edges from a cross field (TODO: integrate with field code)
+ - Similarity: TODO. It makes sense to keep this here, since it can satisfy full holonomy signature constraints, but is not integral to the codebase
+- Feature: Library for parametrizing surfaces with both seamless and feature alignment constraints
+ - Core
+ - Boundary Path: Data structure for tracking the line of symmetry between two boundary vertices
+ - Common: TODO
+ - Component Mesh: Methods and data structures for splitting a disconnected mesh into separate components, as well as corresponding reindexing maps.
+ - IO: Methods to write/read edges to/from file.
+ - Quads: Methods to compute relevant quad mesh statistics (TODO: Only contains valence computation; Unify with other quad related code)
+ - Union Meshes: Methods to combine collections of meshes into a single mesh with multiple components.
+ - VF Corners: Methods for representing mesh edges using opposite corners.
+ - Viewer: Assorted viewers
+ - Dirichlet: Methods for enforcing hard and optimizing soft feature alignment constraints (TODO: consider renaming)
+ - Angle Constraint Relaxer: Method to compute a relaxed angle constraint system that maintains total vertex angles while relaxing feature edge alignment.
+ - Cone Perturber: Data structure to modify sector angle constraints for feature alignment
+ - Constraints: Methods to compute feature aligned seamless constraints and associated Jacobians
+ - Dirichlet Penner Cone Metric: Extension of the differentiable cone metric using Penner coordinates to include full feature aligned seamless constraints (TODO: finish documenting)
+ - Optimization: Two-phase optimization method for alignment of relaxed angle constraint
+ - Experimental: (TODO: Remove)
+ - Feature: Methods to find
+ - Error: Methods to compute feature alignment error
+ - Features: Method to find feature edges on a surface and hard feature constraint subsets
+ - Gluing: Methods to get cut mesh edge and vertex correspondences
+ - Surgery: Methods to cut, refine, and stitch meshes and their parametrizations
+ - Cut Mesh Layout: Methods to parameterize the uv components of a cut mesh
+ - Cut Metric Generator: Data structure to generate fields and differentiable metrics for a mesh cut along feature lines.
+ - Refinement: Data structure with limited support to refine the faces and edges of a mesh for feature alignment
+ - Stitching: Method to stitch a mesh cut along feature lines and parametrized, possibly with edge refinement, into a single parametrized mesh.
+ - Util: Union Find: (TODO: Move to global utility)
+
## Citation
```
diff --git a/cmake/Catch2.cmake b/cmake/Catch2.cmake
index 44577de..589941b 100644
--- a/cmake/Catch2.cmake
+++ b/cmake/Catch2.cmake
@@ -6,6 +6,6 @@ Include(FetchContent)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
- GIT_TAG v3.0.1
+ GIT_TAG v3.15.0
)
-FetchContent_MakeAvailable(Catch2)
\ No newline at end of file
+FetchContent_MakeAvailable(Catch2)
diff --git a/cmake/conformal_ideal_delaunay.cmake b/cmake/conformal_ideal_delaunay.cmake
index 461c7ad..27d218f 100644
--- a/cmake/conformal_ideal_delaunay.cmake
+++ b/cmake/conformal_ideal_delaunay.cmake
@@ -6,5 +6,9 @@ FetchContent_Declare(
GIT_TAG penner_optimization
)
FetchContent_MakeAvailable(conformal_ideal_delaunay)
+
+if(TARGET conformal_ideal_delaunay AND APPLE)
+ target_compile_options(conformal_ideal_delaunay PRIVATE -Wno-extra-tokens)
+endif()
target_compile_features(conformal_cpp PRIVATE cxx_std_20)
diff --git a/cmake/highfive.cmake b/cmake/deprecated/highfive.cmake
similarity index 100%
rename from cmake/highfive.cmake
rename to cmake/deprecated/highfive.cmake
diff --git a/cmake/seamless-optimization.cmake b/cmake/seamless-optimization.cmake
new file mode 100644
index 0000000..9e5651c
--- /dev/null
+++ b/cmake/seamless-optimization.cmake
@@ -0,0 +1,14 @@
+if(TARGET SymmetricDirichletLib)
+ return()
+endif()
+
+
+include(FetchContent)
+FetchContent_Declare(
+ seamless-optimization
+ SYSTEM
+ GIT_REPOSITORY https://github.com/rjc8237/seamless-optimization.git
+ GIT_TAG main
+)
+FetchContent_MakeAvailable(seamless-optimization)
+
diff --git a/cmake/symmetric-dirichlet.cmake b/cmake/symmetric-dirichlet.cmake
deleted file mode 100644
index f2d143f..0000000
--- a/cmake/symmetric-dirichlet.cmake
+++ /dev/null
@@ -1,14 +0,0 @@
-if(TARGET SymmetricDirichletLib)
- return()
-endif()
-
-
-include(FetchContent)
-FetchContent_Declare(
- symmetric-dirichlet
- SYSTEM
- GIT_REPOSITORY https://github.com/rjc8237/symmetric-dirichlet.git
- GIT_TAG merge
-)
-FetchContent_MakeAvailable(symmetric-dirichlet)
-
diff --git a/include/feature/feature/core/boundary_path.h b/include/feature/feature/core/boundary_path.h
index 9415f7e..fd7daeb 100644
--- a/include/feature/feature/core/boundary_path.h
+++ b/include/feature/feature/core/boundary_path.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
@@ -5,6 +13,12 @@
namespace Penner {
namespace Feature {
+/**
+ * @brief Data structure for tracking the line of symmetry between two boundary vertices. Also
+ * supports computation of the length of the line and the gradient with repect to Penner coordinates.
+ *
+ */
+
/**
* @brief Representation of a boundary edge path. If the boundary edge is unflipped and lies along
* the symmetry line, then this is just a single halfedge in the primal mesh. If the edge is
@@ -149,4 +163,4 @@ class BoundaryPath
std::tuple, MatrixX> build_boundary_paths(const Mesh& m);
} // namespace Feature
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/feature/feature/core/common.h b/include/feature/feature/core/common.h
index 91ffc4c..899873a 100644
--- a/include/feature/feature/core/common.h
+++ b/include/feature/feature/core/common.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/interface.h"
@@ -6,6 +14,11 @@
#include "holonomy/holonomy/marked_penner_cone_metric.h"
#include "holonomy/holonomy/newton.h"
+/**
+ * @brief Assorted utility functions.
+ *
+ */
+
namespace Penner {
namespace Feature {
@@ -13,7 +26,6 @@ using Holonomy::DualLoop;
using Holonomy::MarkedPennerConeMetric;
using Holonomy::NewtonParameters;
using Holonomy::MarkedMetricParameters;
-typedef std::array VertexEdge;
/**
* @brief Compute the square of a scalar.
@@ -69,4 +81,4 @@ std::vector> reindex_endpoints(
} // namespace Feature
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/feature/feature/core/component_mesh.h b/include/feature/feature/core/component_mesh.h
index adf693a..e5b489a 100644
--- a/include/feature/feature/core/component_mesh.h
+++ b/include/feature/feature/core/component_mesh.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
@@ -7,6 +15,14 @@
#include "feature/util/union_find.h"
#include "holonomy/holonomy/marked_penner_cone_metric.h"
+/**
+ * @brief Methods and data structures for splitting a disconnected mesh into separate components,
+ * as well as corresponding reindexing maps.
+ *
+ * Separate methods for both halfedge and VF representations.
+ *
+ */
+
namespace Penner {
namespace Feature {
@@ -27,6 +43,13 @@ class ComponentMesh
*/
ComponentMesh(const Mesh& m);
+ /**
+ * @brief Construct a collection of components for the global (possibly disconnected) mesh using
+ * precomputed component information
+ *
+ * @param m: (possibly disconnected) manifold mesh
+ * @param components: component index for each face of the mesh
+ */
ComponentMesh(const Mesh& m, const Eigen::VectorXi& components);
/**
diff --git a/include/feature/feature/core/io.h b/include/feature/feature/core/io.h
index 3c3cfd9..1195628 100644
--- a/include/feature/feature/core/io.h
+++ b/include/feature/feature/core/io.h
@@ -1,10 +1,24 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
+#include "feature/core/vf_corners.h"
namespace Penner {
namespace Feature {
+/**
+ * @brief Methods to write/read edges to/from file, including feature, boundary, and seam edges.
+ *
+ */
+
/**
* @brief Write feature edges to a 0-indexed list in the following format:
*
@@ -91,10 +105,22 @@ void write_boundary(
const Eigen::MatrixXi& F,
const Eigen::MatrixXi& F_uv);
+/**
+ * @brief Write mesh edges to file in the format:
+ * v x0 y0 z0
+ * v x1 y1 z1
+ * ...
+ * l v0 v1
+ * ...
+ *
+ * @param filename: output edge geometry file
+ * @param V: mesh vertices
+ * @param F: mesh edges
+ */
void write_edges(
const std::string& filename,
const Eigen::MatrixXd& V,
const Eigen::MatrixXi& E);
} // namespace Feature
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/feature/feature/core/quads.h b/include/feature/feature/core/quads.h
index 04b05e1..13b0c6d 100644
--- a/include/feature/feature/core/quads.h
+++ b/include/feature/feature/core/quads.h
@@ -1,8 +1,21 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
+/**
+ * @brief Methods to compute relevant quad mesh statistics, including degree valences.
+ *
+ */
+
namespace Penner {
namespace Feature {
diff --git a/include/feature/feature/core/union_meshes.h b/include/feature/feature/core/union_meshes.h
index 5f4ec3b..f0791bc 100644
--- a/include/feature/feature/core/union_meshes.h
+++ b/include/feature/feature/core/union_meshes.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
@@ -6,10 +14,14 @@
#include "holonomy/holonomy/marked_penner_cone_metric.h"
#include "feature/util/union_find.h"
+/**
+ * @brief Methods to combine collections of meshes into a single mesh with multiple components.
+ *
+ */
+
namespace Penner {
namespace Feature {
-
/**
* @brief Count the total number of vertices in set of mesh components.
*
diff --git a/include/feature/feature/core/vf_corners.h b/include/feature/feature/core/vf_corners.h
index 58d9e97..647699e 100644
--- a/include/feature/feature/core/vf_corners.h
+++ b/include/feature/feature/core/vf_corners.h
@@ -1,10 +1,37 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
+/**
+ * @brief Methods for representing mesh edges using opposite corners.
+ *
+ * The representations are:
+ * Mask: a Fx3 boolean mask for marking corners
+ * Corner: a simple face and local corner index pair (f, i), with i in {0, 1, 2}
+ * Face Edge: pair of both VF corners opposite the edge
+ *
+ * Supports conversion between different representations, as well as conversion to and from
+ * vertex pairs and halfedge indices.
+ *
+ * Also includes various edge utilities, such pruning redundant corners, taking mask differences,
+ * and finding parametrization seams.
+ *
+ */
+
namespace Penner {
namespace Feature {
+
+typedef std::array VertexEdge;
+
/**
* @brief Representation of an edge as the two opposite face corners
*
@@ -253,19 +280,6 @@ Eigen::MatrixXd transfer_halfedge_function_to_corner(
const Eigen::MatrixXi& F,
const VectorX& halfedge_func);
-/**
- * @brief Find the seams of the parameterization of a closed mesh.
- *
- * TODO: Extend to open meshes
- *
- * @param F: mesh faces
- * @param FT: mesh layout faces
- * @return |F|x3 mask of corners opposite seam edges
- */
-Eigen::MatrixXi find_seams(
- const Eigen::MatrixXi& F,
- const Eigen::MatrixXi& FT);
-
/**
* @brief Given a mask of corners opposite edges, generate the corresponding edge geometry.
*
diff --git a/include/feature/feature/core/viewer.h b/include/feature/feature/core/viewer.h
index 12aba87..585d5e1 100644
--- a/include/feature/feature/core/viewer.h
+++ b/include/feature/feature/core/viewer.h
@@ -1,9 +1,22 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
// TODO: Cleaning pass
+/**
+ * @brief Assorted viewers.
+ *
+ */
+
namespace Penner {
namespace Feature {
diff --git a/include/feature/feature/dirichlet/angle_constraint_relaxer.h b/include/feature/feature/dirichlet/angle_constraint_relaxer.h
index 0e20075..5d081fc 100644
--- a/include/feature/feature/dirichlet/angle_constraint_relaxer.h
+++ b/include/feature/feature/dirichlet/angle_constraint_relaxer.h
@@ -1,9 +1,23 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
#include "feature/dirichlet/dirichlet_penner_cone_metric.h"
+/**
+ * @brief Method to compute a relaxed angle constraint system that maintains total vertex angles
+ * while relaxing feature edge alignment.
+ *
+ */
+
namespace Penner {
namespace Feature {
diff --git a/include/feature/feature/dirichlet/cone_perturber.h b/include/feature/feature/dirichlet/cone_perturber.h
index c9e9f97..6e554b5 100644
--- a/include/feature/feature/dirichlet/cone_perturber.h
+++ b/include/feature/feature/dirichlet/cone_perturber.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
@@ -6,6 +14,10 @@
#include "feature/feature/gluing.h"
#include
+/**
+ * @brief Data structure to modify sector angle constraints for feature alignment
+ *
+ */
namespace Penner {
namespace Feature {
@@ -77,4 +89,4 @@ class ConePerturber
};
} // namespace Feature
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/feature/feature/dirichlet/constraint.h b/include/feature/feature/dirichlet/constraint.h
index e3a0da0..cd0f465 100644
--- a/include/feature/feature/dirichlet/constraint.h
+++ b/include/feature/feature/dirichlet/constraint.h
@@ -1,9 +1,23 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
#include "feature/dirichlet/dirichlet_penner_cone_metric.h"
+/**
+ * @brief Methods to compute feature aligned seamless constraints, which includes boundary length
+ * consistency constraints, and associated Jacobians
+ *
+ */
+
namespace Penner {
namespace Feature {
diff --git a/include/feature/feature/dirichlet/dirichlet_penner_cone_metric.h b/include/feature/feature/dirichlet/dirichlet_penner_cone_metric.h
index 6920262..6c0c789 100644
--- a/include/feature/feature/dirichlet/dirichlet_penner_cone_metric.h
+++ b/include/feature/feature/dirichlet/dirichlet_penner_cone_metric.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/boundary_path.h"
@@ -7,6 +15,13 @@
#include "holonomy/holonomy/marked_penner_cone_metric.h"
#include "holonomy/holonomy/constraint.h"
+/**
+ * @brief Extension of the differentiable cone metric using Penner coordinates
+ * to include both dual loop holonomy constraints and boundary length consistency
+ * constraints, which allow for feature aligned seamless metric constraints.
+ *
+ */
+
namespace Penner {
namespace Feature {
@@ -121,7 +136,7 @@ class DirichletPennerConeMetric : public Holonomy::MarkedPennerConeMetric
virtual std::unique_ptr project_to_constraint(
SolveStats& solve_stats,
- std::shared_ptr proj_params) const override;
+ std::shared_ptr proj_params) const override;
virtual void write_status_log(std::ostream& stream, bool write_header = false) override;
diff --git a/include/feature/feature/dirichlet/optimization.h b/include/feature/feature/dirichlet/optimization.h
index 2c0a7c2..c0715d3 100644
--- a/include/feature/feature/dirichlet/optimization.h
+++ b/include/feature/feature/dirichlet/optimization.h
@@ -1,9 +1,22 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
#include "feature/dirichlet/dirichlet_penner_cone_metric.h"
#include "holonomy/holonomy/newton.h"
+/**
+ * @brief Two-phase optimization method for alignment of relaxed angle constraint.
+ *
+ */
+
namespace Penner {
namespace Feature {
diff --git a/include/feature/feature/experimental/boundary_constraint_generator.h b/include/feature/feature/experimental/boundary_constraint_generator.h
index cd9d5c1..6a15cfe 100644
--- a/include/feature/feature/experimental/boundary_constraint_generator.h
+++ b/include/feature/feature/experimental/boundary_constraint_generator.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
diff --git a/include/feature/feature/experimental/boundary_constraint_validator.h b/include/feature/feature/experimental/boundary_constraint_validator.h
index 92e28ed..1c6d3d5 100644
--- a/include/feature/feature/experimental/boundary_constraint_validator.h
+++ b/include/feature/feature/experimental/boundary_constraint_validator.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
diff --git a/include/feature/feature/experimental/energy.h b/include/feature/feature/experimental/energy.h
index 849b920..5bf4863 100644
--- a/include/feature/feature/experimental/energy.h
+++ b/include/feature/feature/experimental/energy.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
@@ -15,10 +23,10 @@ class ConeEnergy : public Optimization::EnergyFunctor
/// Sum of square cone error energy.
///
/// @param[in] cone_metric: mesh topology
- ConeEnergy(const Optimization::PennerConeMetric& cone_metric);
+ ConeEnergy(const PennerConeMetric& cone_metric);
private:
- Optimization::PennerConeMetric m_cone_metric;
+ PennerConeMetric m_cone_metric;
virtual Scalar energy(const VectorX& metric_coords) const override;
virtual VectorX gradient(const VectorX& metric_coords) const override;
diff --git a/include/feature/feature/experimental/junctions.h b/include/feature/feature/experimental/junctions.h
index f63d043..12d1a3c 100644
--- a/include/feature/feature/experimental/junctions.h
+++ b/include/feature/feature/experimental/junctions.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
diff --git a/include/feature/feature/experimental/layout_optimizer.h b/include/feature/feature/experimental/layout_optimizer.h
index ff238a0..6f4f28d 100644
--- a/include/feature/feature/experimental/layout_optimizer.h
+++ b/include/feature/feature/experimental/layout_optimizer.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
diff --git a/include/feature/feature/experimental/marked_refinement.h b/include/feature/feature/experimental/marked_refinement.h
index fc48cc4..553b18b 100644
--- a/include/feature/feature/experimental/marked_refinement.h
+++ b/include/feature/feature/experimental/marked_refinement.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
diff --git a/include/feature/feature/experimental/misc.h b/include/feature/feature/experimental/misc.h
index 942093a..23f306b 100644
--- a/include/feature/feature/experimental/misc.h
+++ b/include/feature/feature/experimental/misc.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
struct ParametrizedMesh
{
@@ -47,4 +55,4 @@ struct ParametrizedOverlayMesh
Eigen::MatrixXi F_uv;
std::vector Fn_to_F;
std::vector> endpoints;
-};
+};
\ No newline at end of file
diff --git a/include/feature/feature/experimental/newton.h b/include/feature/feature/experimental/newton.h
index 62695ec..ac4d18f 100644
--- a/include/feature/feature/experimental/newton.h
+++ b/include/feature/feature/experimental/newton.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
diff --git a/include/feature/feature/experimental/patches.h b/include/feature/feature/experimental/patches.h
index 329237e..846ef96 100644
--- a/include/feature/feature/experimental/patches.h
+++ b/include/feature/feature/experimental/patches.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
diff --git a/include/feature/feature/experimental/polygon_cones.h b/include/feature/feature/experimental/polygon_cones.h
index 6c7240b..046d059 100644
--- a/include/feature/feature/experimental/polygon_cones.h
+++ b/include/feature/feature/experimental/polygon_cones.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
diff --git a/include/feature/feature/experimental/transfer.h b/include/feature/feature/experimental/transfer.h
index 2345a6e..19b0559 100644
--- a/include/feature/feature/experimental/transfer.h
+++ b/include/feature/feature/experimental/transfer.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
diff --git a/include/feature/feature/feature/error.h b/include/feature/feature/feature/error.h
index 6e6b7c1..7c1876d 100644
--- a/include/feature/feature/feature/error.h
+++ b/include/feature/feature/feature/error.h
@@ -1,9 +1,23 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
#include "feature/core/vf_corners.h"
+/**
+ * @brief Methods to compute feature alignment error. Also includes methods to determine
+ * misaligned edges and numerically degenerate triangles.
+ *
+ */
+
namespace Penner {
namespace Feature {
@@ -160,4 +174,4 @@ int check_flip(const Eigen::MatrixXd& uv, const Eigen::MatrixXi& FT);
Eigen::MatrixXd compute_height(const Eigen::MatrixXd& uv, const Eigen::MatrixXi& FT);
} // namespace Feature
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/feature/feature/feature/features.h b/include/feature/feature/feature/features.h
index 3dce9cc..77ef349 100644
--- a/include/feature/feature/feature/features.h
+++ b/include/feature/feature/feature/features.h
@@ -1,11 +1,31 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
#include "feature/util/union_find.h"
+#include "feature/core/vf_corners.h"
#include "holonomy/holonomy/marked_penner_cone_metric.h"
+/**
+ * @brief Method to find feature edges on a surface and hard feature constraint subsets.
+ *
+ * Uses dihedral angle to determine feature edges. Also includes options to set features manually,
+ * and methods to prune features based on component size.
+ *
+ * Also includes methods to remove feature graph cycles to use as hard feature constraints, and
+ * to greedily remove additional features.
+ *
+ */
+
namespace Penner {
namespace Feature {
diff --git a/include/feature/feature/feature/gluing.h b/include/feature/feature/feature/gluing.h
index 2a176b9..deee777 100644
--- a/include/feature/feature/feature/gluing.h
+++ b/include/feature/feature/feature/gluing.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
@@ -6,6 +14,11 @@
namespace Penner {
namespace Feature {
+/**
+ * @brief Methods to get cut mesh edge and vertex correspondences, as well as total vertex cone angles.
+ *
+ */
+
/**
* @brief Given a mesh with vertex pairings arising from cuts, generate pairings of cut edges.
*
diff --git a/include/feature/feature/interface.h b/include/feature/feature/interface.h
index b8cefda..0b5b5c3 100644
--- a/include/feature/feature/interface.h
+++ b/include/feature/feature/interface.h
@@ -1,9 +1,17 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
#include "feature/dirichlet/dirichlet_penner_cone_metric.h"
#include "feature/feature/features.h"
-#include "holonomy/field/intrinsic_field.h"
+#include "field/intrinsic_field.h"
#include "feature/core/vf_corners.h"
#include "holonomy/interface.h"
@@ -234,4 +242,4 @@ class AlignedMetricGenerator
} // namespace Feature
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/feature/feature/pybind.h b/include/feature/feature/pybind.h
index d875e8a..12d53e8 100644
--- a/include/feature/feature/pybind.h
+++ b/include/feature/feature/pybind.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#ifdef PYBIND
#ifndef MULTIPRECISION
diff --git a/include/feature/feature/surgery/cut_mesh_layout.h b/include/feature/feature/surgery/cut_mesh_layout.h
index 1ba06f8..432e5c3 100644
--- a/include/feature/feature/surgery/cut_mesh_layout.h
+++ b/include/feature/feature/surgery/cut_mesh_layout.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
@@ -6,6 +14,11 @@
namespace Penner {
namespace Feature {
+/**
+ * @brief Methods to parameterize the uv components of a cut mesh, aligning each component with uv isolines.
+ *
+ */
+
/**
* @brief Parametrize a cut mesh with optimized metric.
*
diff --git a/include/feature/feature/surgery/cut_metric_generator.h b/include/feature/feature/surgery/cut_metric_generator.h
index 7bc3251..5ab97d6 100644
--- a/include/feature/feature/surgery/cut_metric_generator.h
+++ b/include/feature/feature/surgery/cut_metric_generator.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
@@ -7,6 +15,12 @@
namespace Penner {
namespace Feature {
+/**
+ * @brief Data structure to generate fields and differentiable metrics for a mesh cut
+ * along feature lines.
+ *
+ */
+
class CutMetricGenerator
{
public:
@@ -174,4 +188,4 @@ class CutMetricGenerator
};
} // namespace Feature
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/feature/feature/surgery/refinement.h b/include/feature/feature/surgery/refinement.h
index fb8fba6..54e2b30 100644
--- a/include/feature/feature/surgery/refinement.h
+++ b/include/feature/feature/surgery/refinement.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/boundary_path.h"
@@ -6,6 +14,16 @@
#include "feature/feature/features.h"
#include "holonomy/holonomy/marked_penner_cone_metric.h"
+/**
+ * @brief Data structure with limited support to refine the faces and edges of a mesh for feature alignment.
+ *
+ * Only intended for use with the limited mesh refinement needed for ensuring the validity
+ * of the feature alignment problem, including refining faces with more than one feature edge,
+ * and refining edges to ensure every facet component of the feature cut mesh has at least one adjacent
+ * hard feature constraint
+ *
+ */
+
namespace Penner {
namespace Feature {
diff --git a/include/feature/feature/surgery/stitching.h b/include/feature/feature/surgery/stitching.h
index 64f2731..6a17198 100644
--- a/include/feature/feature/surgery/stitching.h
+++ b/include/feature/feature/surgery/stitching.h
@@ -1,8 +1,22 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
+/**
+ * @brief Method to stitch a mesh cut along feature lines and parametrized, possibly with edge refinement,
+ * into a single parametrized mesh.
+ *
+ */
+
namespace Penner {
namespace Feature {
diff --git a/include/feature/feature/util/union_find.h b/include/feature/feature/util/union_find.h
index 45046b3..f8bbf79 100644
--- a/include/feature/feature/util/union_find.h
+++ b/include/feature/feature/util/union_find.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "feature/core/common.h"
@@ -101,6 +109,8 @@ class UnionFind
}
/**
+<<<<<<< HEAD
+=======
* @brief Get a representative element for each set.
*
* @return vector of one element per set
@@ -123,6 +133,7 @@ class UnionFind
}
/**
+>>>>>>> resolution
* @brief Build labels for the set elements.
*
* @return map from elements to set index
diff --git a/include/field/field/comiso.h b/include/field/field/comiso.h
new file mode 100644
index 0000000..b533924
--- /dev/null
+++ b/include/field/field/comiso.h
@@ -0,0 +1,197 @@
+// Copyright (C) 2026 Ryan Capouellez
+//
+// 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 .
+
+#pragma once
+
+// WARNING: CoMISo uses a more restrictive copyleft license
+#if USE_COMISO
+#include
+#include
+#include
+
+#include "field/rounder.h"
+
+namespace Penner {
+namespace Field {
+
+
+
+// TODO Make option and make cone rounder code public
+class ConeMISolver : public COMISO::MISolver
+{
+public:
+ ConeMISolver() {};
+ void solve_cone_rounding(
+ CSCMatrix& _A,
+ Vecd& _x,
+ Vecd& _rhs,
+ Veci& _to_round,
+ Rounder& rounder) {
+ // StopWatch
+ COMISO::StopWatch sw;
+ double time_search_next_integer = 0;
+
+ // some statistics
+ n_local_ = 0;
+ n_cg_ = 0;
+ n_full_ = 0;
+
+ // reset cholmod step flag
+ cholmod_step_done_ = false;
+
+ Veci to_round(_to_round);
+ // copy to round vector and make it unique
+ std::sort(to_round.begin(), to_round.end());
+ Veci::iterator last_unique;
+ last_unique = std::unique(to_round.begin(), to_round.end());
+ int r = last_unique - to_round.begin();
+ to_round.resize( r);
+
+ // initalize old indices
+ Veci old_idx(_rhs.size());
+ for(unsigned int i=0; i 2) std::cerr << "initial full solution" << std::endl;
+ direct_solver_.calc_system_gmm(_A);
+ direct_solver_.solve(_x, _rhs);
+
+ cholmod_step_done_ = true;
+
+ ++n_full_;
+ }
+
+ // neighbors for local optimization
+ Vecui neigh_i;
+
+ // Vector for reduced solution
+ Vecd xr(_x);
+
+ // loop until solution computed
+ for(unsigned int i=0; i 0)
+ {
+ std::cerr << "Integer DOF's left: " << to_round.size()-(i+1) << " ";
+ if( noisy_ > 1)
+ std::cerr << "residuum_norm: " << COMISO_GMM::residuum_norm( _A, xr, _rhs) << std::endl;
+ }
+
+ // position in round vector
+ std::vector tr_best;
+
+ sw.start();
+
+ RoundingSet rset;
+ rset.set_threshold(multiple_rounding_threshold_);
+
+ // find index yielding smallest rounding error
+ for(unsigned int j=0; j 5)
+ std::cerr << "round " << tr_best.size() << " variables simultaneously\n";
+
+ // clear neigh for local update
+ neigh_i.clear();
+
+ for(unsigned int j = 0; j 2) std::cerr << "final full solution" << std::endl;
+
+ if( gmm::mat_ncols( _A) > 0)
+ {
+ if(cholmod_step_done_)
+ direct_solver_.update_system_gmm(_A);
+ else
+ direct_solver_.calc_system_gmm(_A);
+
+ direct_solver_.solve( xr, _rhs);
+ ++n_full_;
+ }
+ }
+
+ // store solution values to result vector
+ for(unsigned int i=0; i
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
-#include "holonomy/core/common.h"
+#include "metric/common.h"
+
+/**
+ * @brief Methods for generating cross fields as represented by four rotationally symmetric
+ * tangent vectors.
+ *
+ */
namespace Penner {
-namespace Holonomy {
+namespace Field {
/**
* @brief Load rawfield data format used by Directional.
@@ -65,4 +79,4 @@ std::array reduce_curl(
const std::vector& fixed_faces);
} // namespace Feature
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/field/facet_field.h b/include/field/field/facet_field.h
similarity index 75%
rename from include/holonomy/holonomy/field/facet_field.h
rename to include/field/field/facet_field.h
index b5db9c9..a484a3a 100644
--- a/include/holonomy/holonomy/field/facet_field.h
+++ b/include/field/field/facet_field.h
@@ -1,10 +1,23 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
-#include "holonomy/core/common.h"
+#include "metric/common.h"
namespace Penner {
-namespace Holonomy {
+namespace Field {
+
+/**
+ * @brief Methods for generating cross fields using legacy facet field file representations.
+ *
+ */
/**
* @brief Load a per-facet frame field with edge matchings from file
@@ -48,4 +61,4 @@ std::tuple generate_halfedge_from_face_matchin
int version=0);
} // namespace Feature
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/field/field/field.h b/include/field/field/field.h
new file mode 100644
index 0000000..874cd5e
--- /dev/null
+++ b/include/field/field/field.h
@@ -0,0 +1,35 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
+
+#pragma once
+#include "metric/common.h"
+
+/**
+ * @brief Methods to generate field directions and cones from an nrosy field.
+ *
+ */
+
+namespace Penner {
+namespace Field {
+
+/**
+ * @brief Generate a cross field for a mesh
+ *
+ * @param V: mesh vertices
+ * @param F: mesh faces
+ * @return |F|x3 frame field of per-face field direction vectors
+ * @return per-vertex cone angles corresponding to the frame field
+ */
+std::tuple> generate_cross_field(
+ const Eigen::MatrixXd& V,
+ const Eigen::MatrixXi& F);
+
+
+} // namespace Field
+} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/field/forms.h b/include/field/field/forms.h
similarity index 74%
rename from include/holonomy/holonomy/field/forms.h
rename to include/field/field/forms.h
index 1c56594..6f49558 100644
--- a/include/holonomy/holonomy/field/forms.h
+++ b/include/field/field/forms.h
@@ -1,10 +1,30 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
-#include "holonomy/core/common.h"
-#include "holonomy/core/dual_loop.h"
+#include "metric/common.h"
+#include "metric/cone_metric.h"
+
+/**
+ * @brief Methods for creating and manipulating one forms on a surface, represented as
+ * anti-symmetric halfedge values.
+ *
+ * These halfedge values are interpretable as the integrated values of the form along the
+ * oriented halfedges.
+ *
+ * Includes methods to check whether forms are valid and closed, to integrate closed one
+ * forms over a disk, and to scale vertices by integrated one forms.
+ *
+ */
namespace Penner {
-namespace Holonomy {
+namespace Field {
/**
* @brief Determine if a one form is valid.
@@ -16,7 +36,7 @@ namespace Holonomy {
bool is_valid_one_form(const Mesh& m, const VectorX& one_form);
/**
- * @brief Determine if a one form is closed
+ * @brief Determine if a one form is closed, meaning the sum of halfedge values in a face is zero
*
* @param m: mesh
* @param one_form: per-halfedge one-form
@@ -24,33 +44,6 @@ bool is_valid_one_form(const Mesh& m, const VectorX& one_form);
*/
bool is_closed_one_form(const Mesh& m, const VectorX& one_form);
-/**
- * @brief Given a list of dual loops, compute a matrix with columns given by the corresponding
- * closed one forms for the dual loops.
- *
- * @param m: mesh
- * @param dual_loops: loops defining the one forms
- * @return matrix of dual loop one forms
- */
-MatrixX build_dual_loop_basis_one_form_matrix(
- const Mesh& m,
- const std::vector>& dual_loops);
-
-/**
- * @brief Given a mesh and a homology basis, compute a matrix for the space of closed one forms
- * with the first |V| (or |V| - 1) columns corresponding to vertex hat function derivatives and the
- * last 2g corresponding to the homology basis loops.
- *
- * @param m: mesh
- * @param homology_basis_loops: homology basis loops for the mesh
- * @param eliminate_vertex: remove the last vertex of the mesh so that the matrix is full rank
- * @return matrix with basis forms as columns
- */
-MatrixX build_closed_one_form_matrix(
- const Mesh& m,
- const std::vector>& homology_basis_loops,
- bool eliminate_vertex = false);
-
/**
* @brief Compute the matrix that integrates a closed one-form over a cut of the mesh to a disk.
*
@@ -129,5 +122,5 @@ VectorX scale_edges_by_zero_form(
const VectorX& metric_coords,
const VectorX& zero_form);
-} // namespace Holonomy
+} // namespace Field
} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/field/frame_field.h b/include/field/field/frame_field.h
similarity index 85%
rename from include/holonomy/holonomy/field/frame_field.h
rename to include/field/field/frame_field.h
index 63f7a18..6ac750f 100644
--- a/include/holonomy/holonomy/field/frame_field.h
+++ b/include/field/field/frame_field.h
@@ -1,11 +1,23 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
-#include "holonomy/core/common.h"
-#include "holonomy/field/intrinsic_field.h"
+#include "field/intrinsic_field.h"
+
+/**
+ * @brief TODO: Redistribute this code
+ *
+ */
namespace Penner {
-namespace Holonomy {
+namespace Field {
/**
* @brief Generate the reference tangent direction of a face along the oriented edge opposite
@@ -59,7 +71,7 @@ Eigen::MatrixXd generate_reference_field(
* @param theta: offset angles of a representative cross field direction relative to the reference
* @return per-face representative direction matrix
*/
-Eigen::MatrixXd generate_field(
+Eigen::MatrixXd generate_frame_field(
const Eigen::MatrixXd& V,
const Eigen::MatrixXi& F,
const Eigen::MatrixXd& reference_field,
@@ -129,6 +141,48 @@ void write_frame_field(
const Eigen::MatrixXd& kappa,
const Eigen::MatrixXi& period_jump);
+/**
+ * @brief Write a rosy field to file.
+ *
+ * The format is
+ * ```
+ *
+ * 4
+ *
+ * ...
+ * ```
+ * where d is a representative direction on the face.
+ *
+ * @param output_filename: file location to serialize the frame field
+ * @param V: mesh vertices
+ * @param F: mesh faces
+ * @param reference_field: per-face reference tangent direction matrix
+ * @param theta: offset angles of a representative cross field direction relative to the reference
+ */
+void write_rosy_field(
+ const std::string& output_filename,
+ const Eigen::MatrixXd& V,
+ const Eigen::MatrixXi& F,
+ const Eigen::MatrixXd& reference_field,
+ const Eigen::VectorXd& theta);
+
+/**
+ * @brief Write a combed frame field to file.
+ *
+ *
+ * ...
+ * ```
+ * where d1 and d2 are the two combed field direction
+ *
+ * @param output_filename: file location to serialize the frame field
+ * @param PD1: per-face u direction matrix
+ * @param PD2: per-face b direction matrix
+ */
+void write_combed_field(
+ const std::string& output_filename,
+ const Eigen::MatrixXd& PD1,
+ const Eigen::MatrixXd& PD2);
+
std::tuple
maximize_combed_frame_alignment(
const Eigen::MatrixXd& V,
@@ -152,24 +206,21 @@ std::tuple
load_combed_field(const std::string& ffield_file);
/**
- * @brief Write a combed frame field to file.
+ * @brief Load a rosy field from file.
*
* The format is
* ```
*
- *
+ * 4
+ *
* ...
* ```
- * where d1 and d2 are the two combed field direction
+ * where d is a representative direction on the face.
*
- * @param output_filename: file location to serialize the frame field
- * @param PD1: per-face u direction matrix
- * @param PD2: per-face b direction matrix
+ * @param input_filename: file location of the rosy field
+ * @return per-face representative field direction
*/
-void write_combed_field(
- const std::string& output_filename,
- const Eigen::MatrixXd& PD1,
- const Eigen::MatrixXd& PD2);
+Eigen::MatrixXd load_rosy_field(const std::string& input_filename);
/**
* @brief Load a frame field from file.
@@ -254,4 +305,4 @@ Eigen::VectorXi transfer_period_jumps_to_halfedge(
const Eigen::MatrixXi& corner_period_jump);
} // namespace Feature
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/field/intrinsic_field.h b/include/field/field/intrinsic_field.h
similarity index 86%
rename from include/holonomy/holonomy/field/intrinsic_field.h
rename to include/field/field/intrinsic_field.h
index a080b00..92ae87c 100644
--- a/include/holonomy/holonomy/field/intrinsic_field.h
+++ b/include/field/field/intrinsic_field.h
@@ -1,6 +1,15 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
-#include "holonomy/core/common.h"
+#include "metric/common.h"
+#include "metric/cone_metric.h"
// TODO: This needs a lot of cleanup. To make it clean:
// - The rounder should be moved to another file, and the CoMISo changes made in a fork
@@ -8,7 +17,7 @@
// - The double code should be much cleaner, e.g., by making a derived class
namespace Penner {
-namespace Holonomy {
+namespace Field {
/**
* @brief Parameters for cross field generation
@@ -63,6 +72,14 @@ class IntrinsicNRosyField
Eigen::VectorXd& face_angle,
Eigen::MatrixXd& corner_kappa,
Eigen::MatrixXi& corner_period_jump) const;
+ void get_field(
+ const Mesh& m,
+ const std::vector& vtx_reindex,
+ const Eigen::MatrixXi& F,
+ Eigen::VectorXi& reference_corner,
+ Eigen::VectorXd& face_angle,
+ Eigen::MatrixXd& corner_kappa,
+ Eigen::MatrixXi& corner_period_jump) const;
void get_halfedge_field(
const Mesh& m,
@@ -88,6 +105,18 @@ class IntrinsicNRosyField
const Eigen::VectorXd& face_theta,
const Eigen::MatrixXd& corner_kappa,
const Eigen::MatrixXi& corner_period_jump);
+ void set_field(
+ const Mesh& m,
+ const std::vector& vtx_reindex,
+ const Eigen::MatrixXi& F,
+ const Eigen::VectorXd& face_theta,
+ const Eigen::MatrixXd& corner_kappa,
+ const Eigen::MatrixXi& corner_period_jump);
+ void set_theta(
+ const Mesh& m,
+ const Eigen::VectorXd& face_theta);
+
+ Scalar min_angle = 0.;
void set_halfedge_field(
const Mesh& m,
@@ -213,5 +242,5 @@ void initialize_double_priority_kappa(const Mesh& m, const std::vector generate_min_cones(const Mesh& m, int min_cone=1);
std::vector build_double_dual_bfs_forest(const Mesh& m, const std::vector roots);
-} // namespace Holonomy
-} // namespace Penner
+} // namespace Field
+} // namespace Penner
\ No newline at end of file
diff --git a/include/field/field/rounder.h b/include/field/field/rounder.h
new file mode 100644
index 0000000..aef2056
--- /dev/null
+++ b/include/field/field/rounder.h
@@ -0,0 +1,150 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "metric/common.h"
+#include "metric/cone_metric.h"
+#include "util/vector.h"
+#include "util/map.h"
+
+// TODO: This needs a lot of cleanup. To make it clean:
+// - The rounder should be moved to another file, and the CoMISo changes made in a fork
+// - The facet principal curvature should be in another file
+// - The double code should be much cleaner, e.g., by making a derived class
+
+namespace Penner {
+namespace Field {
+
+class Rounder {
+public:
+ Rounder(
+ const Mesh& m,
+ const std::vector& _var2he,
+ const std::vector& _halfedge_var_id,
+ const std::vector& _base_cones,
+ const std::vector& _min_cones)
+ : var2he(_var2he)
+ , halfedge_var_id(_halfedge_var_id)
+ , base_cones(_base_cones)
+ , min_cones(_min_cones)
+ , is_rounded(m.n_halfedges(), false)
+ , values(m.n_halfedges(), 0)
+ , to(vector_compose(m.v_rep, m.to))
+ , opp(m.opp)
+ , is_double(m.type[0] > 0)
+ {
+ int num_halfedges = m.n_halfedges();
+ int num_vertices = m.n_ind_vertices();
+ cone_period_jumps = std::vector>(num_vertices, std::vector());
+ for (int hij = 0; hij < num_halfedges; ++hij)
+ {
+ // only add variable period jumps
+ if (halfedge_var_id[hij] == -1) continue;
+
+ // add halfedge to tip
+ int vj = m.v_rep[m.to[hij]];
+ cone_period_jumps[vj].push_back(hij);
+
+ // add opposite halfedge to base
+ int hji = m.opp[hij];
+ int vi = m.v_rep[m.to[hji]];
+ cone_period_jumps[vi].push_back(hji);
+ }
+ }
+
+ int compute_cone_correction(int hij)
+ {
+ int vj = to[hij];
+ int cone = base_cones[vj];
+ for (int h : cone_period_jumps[vj])
+ {
+ cone += (is_double) ? (2 * values[h]) : values[h];
+ }
+
+ return (min_cones[vj] - cone);
+ }
+
+ bool is_zero_cone(int hij)
+ {
+ int vj = to[hij];
+ int cone = base_cones[vj];
+ for (int h : cone_period_jumps[vj])
+ {
+ if ((h != hij) && (!is_rounded[h])) return false;
+ cone += (is_double) ? (2 * values[h]) : values[h];
+ }
+
+ return (cone < min_cones[vj]);
+ }
+
+ int test_round(int id, Scalar x)
+ {
+ int hij = var2he[id];
+ //int rounded_value = ((x)<0?int((x)-0.5):int((x)+0.5));
+ int rounded_value = lround(x);
+ int hji = opp[hij];
+ values[hij] = rounded_value;
+ values[hji] = -rounded_value;
+ bool is_tip_cone = is_zero_cone(hij);
+ bool is_base_cone = is_zero_cone(hji);
+
+ if ((is_tip_cone) && (is_base_cone))
+ {
+ spdlog::warn("Cone at both tip and base of period jump halfedge");
+ return rounded_value;
+ }
+ if (is_tip_cone)
+ {
+ spdlog::trace("Cone at tip of period jump halfedge");
+ int n = compute_cone_correction(hij);
+ if (n > 1) spdlog::trace("correction at tip is {}", n);
+ if (n < 0) spdlog::error("correction at tip is {}", n);
+ return rounded_value + n;
+ }
+ if (is_base_cone)
+ {
+ spdlog::trace("Cone at base of period jump halfedge");
+ int n = compute_cone_correction(hji);
+ if (n > 1) spdlog::trace("correction at base is {}", n);
+ if (n < 0) spdlog::error("correction at tip is {}", n);
+ return rounded_value - n;
+ }
+
+ return rounded_value;
+
+ }
+
+ int commit_round(int id, Scalar x)
+ {
+ int rounded_value = test_round(id, x);
+ int hij = var2he[id];
+ int hji = opp[hij];
+ values[hij] = rounded_value;
+ values[hji] = -rounded_value;
+ is_rounded[hij] = true;
+ is_rounded[hji] = true;
+ return rounded_value;
+ }
+
+private:
+ std::vector var2he;
+ std::vector halfedge_var_id;
+ std::vector base_cones;
+ std::vector min_cones;
+ std::vector is_rounded;
+ std::vector values;
+ std::vector> cone_period_jumps;
+ std::vector to;
+ std::vector opp;
+ bool is_double;
+
+};
+
+}
+}
\ No newline at end of file
diff --git a/include/holonomy/holonomy/core/boundary_basis.h b/include/holonomy/holonomy/core/boundary_basis.h
index b56c70e..b12fb7c 100644
--- a/include/holonomy/holonomy/core/boundary_basis.h
+++ b/include/holonomy/holonomy/core/boundary_basis.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
@@ -6,6 +14,21 @@
namespace Penner {
namespace Holonomy {
+/**
+ * @brief Methods to generate basis dual loops for the double of meshes with boundary.
+ *
+ * These loops correspond to alignment constraints between different boundary components
+ * of a mesh with boundary. For a mesh with b boundary components, b - 1 constraints are needed.
+ * The constraint measures the holonomy between a base boundary component and another component.
+ *
+ * In the doubled mesh for a mesh with boundary, the paths between components become dual loops.
+ *
+ * Note that the double mesh has b - 1 handles corresponding to the boundary loops, which results
+ * in an increase in genus of 2b - 2. However, the holonomy of b - 1 loops are determined by cone
+ * angle constraints and symmetry.
+ *
+ */
+
/**
* @brief Class to generate boundary loops and boundary path basis loops
*/
@@ -66,4 +89,4 @@ class BoundaryBasisGenerator
};
} // namespace Holonomy
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/core/common.h b/include/holonomy/holonomy/core/common.h
index 1882ada..4b48aea 100644
--- a/include/holonomy/holonomy/core/common.h
+++ b/include/holonomy/holonomy/core/common.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include
@@ -9,15 +17,19 @@
#include
#include "optimization/interface.h"
-#include "optimization/core/common.h"
-#include "optimization/core/cone_metric.h"
+#include "metric/common.h"
+#include "metric/cone_metric.h"
#include "util/vector.h"
+/**
+ * @brief Assorted utility functions.
+ *
+ */
+
namespace Penner {
namespace Holonomy {
// Typedefs
-using Optimization::DifferentiableConeMetric;
typedef Eigen::Matrix RowVectors2i;
@@ -34,64 +46,6 @@ Type square(const Type& a)
return a * a;
}
-/**
- * @brief Compute the dot product of two 3D vectors.
- *
- * @tparam vector representation of R3 supporting indexing
- * @param v1: first vector
- * @param v2: second vector
- * @return dot product of the two vectors
- */
-template
-double dot_prod(const VectorType& v1, const VectorType& v2)
-{
- return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
-}
-
-/**
- * @brief Compute the cross product of two 3D vectors.
- *
- * @tparam vector representation of R3 supporting indexing
- * @param v1: first vector
- * @param v2: second vector
- * @return cross product of the two vectors
- */
-template
-VectorType cross_prod(const VectorType& v1, const VectorType& v2)
-{
- return VectorType(
- v1[1] * v2[2] - v1[2] * v2[1],
- v1[2] * v2[0] - v1[0] * v2[2],
- v1[0] * v2[1] - v1[1] * v2[0]);
-}
-
-/**
- * @brief Compute the signed angle between two 3D vectors around a normal axis.
- *
- * @tparam vector representation of R3 supporting indexing
- * @param v1: first vector
- * @param v2: second vector
- * @param normal: normal vector representing the axis of rotation
- * @return signed angle between the two vectors around the axis of rotation
- */
-template
-double signed_angle(const VectorType& v1, const VectorType& v2, const VectorType& normal)
-{
- double s = dot_prod(normal, cross_prod(v1, v2));
- double c = dot_prod(v1, v2);
- const double angle = (s == 0 && c == 0) ? 0.0 : atan2(s, c);
- return angle;
-}
-
-/**
- * @brief Compute the real modulus of x mod y
- *
- * @param x: positive number to mod
- * @param y: positive modulus
- * @return x (mod y)
- */
-inline
-Scalar pos_fmod(Scalar x, Scalar y) { return (0 == y) ? x : x - y * floor(x / y); }
/**
* @brief Compute the Euler characteristic of the mesh
diff --git a/include/holonomy/holonomy/core/dual_lengths.h b/include/holonomy/holonomy/core/dual_lengths.h
index 6944aa5..453db05 100644
--- a/include/holonomy/holonomy/core/dual_lengths.h
+++ b/include/holonomy/holonomy/core/dual_lengths.h
@@ -1,9 +1,23 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
#include "util/spanning_tree.h"
+/**
+ * @brief Method to compute the dual edge lengths. Also includes a related method to compute
+ * the length of loops formed by adding an edge to a dual spanning tree.
+ *
+ */
+
namespace Penner {
namespace Holonomy {
@@ -30,4 +44,4 @@ std::vector compute_dual_loop_length_weights(
const DualTree& dual_tree);
} // namespace Holonomy
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/core/dual_loop.h b/include/holonomy/holonomy/core/dual_loop.h
index 75f5405..59c98b9 100644
--- a/include/holonomy/holonomy/core/dual_loop.h
+++ b/include/holonomy/holonomy/core/dual_loop.h
@@ -1,19 +1,74 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
#include "holonomy/core/dual_segment.h"
+/**
+ * @brief Methods to manage dual loops on a surface. Includes classes to represent dual loops on a surface
+ * and data structures to quickly query intersections of the loops with edges of the underlying mesh.
+ *
+ */
+
namespace Penner {
namespace Holonomy {
+/**
+ * @brief Representation of a dual segment as two halfedges in a face at the start
+ * and end of the dual segment.
+ *
+ */
typedef std::array DualSegment;
+/**
+ * @brief Utility class to map from halfedges to dual loop segments that intersect it,
+ * using a dense vector representation,
+ *
+ * WARNING: Memory usage is O(|E|), so it scales poorly for large meshes with many edges
+ *
+ */
class DenseHalfedgeMap {
public:
+ /**
+ * @brief Construct a halfedge map with a fixed capacity.
+ *
+ * @param num_halfedges: total number of halfedges in the mesh
+ */
DenseHalfedgeMap(int num_halfedges);
+
+ /**
+ * @brief Remove all segment entries from all halfedges.
+ */
void clear();
+
+ /**
+ * @brief Add entry for a segment in a halfedge.
+ *
+ * @param halfedge_index: halfedge containing segment
+ * @param segment_index: segment intersecting halfedge
+ */
void add_segment(int halfedge_index, int segment_index);
+
+ /**
+ * @brief Remove all segments from a given halfedge
+ *
+ * @param halfedge_index: halfedge in mesh
+ */
void erase_entry(int halfedge_index);
+
+ /**
+ * @brief Get all segments in the given halfedge
+ *
+ * @param halfedge_index: index of a halfedge in the mesh
+ * @return segments in the halfedge.
+ */
const std::vector& get_halfedge_segments(int halfedge_index);
private:
std::vector m_h_num_segments;
@@ -26,18 +81,51 @@ class DenseHalfedgeMap {
std::vector m_temp_list;
};
+/**
+ * @brief Utility class to map from halfedges to dual loop segments that intersect it,
+ * using a sparse map representation,
+ *
+ */
class SparseHalfedgeMap {
public:
+ /**
+ * @brief Construct an empty halfedge map.
+ */
SparseHalfedgeMap();
+
+ /**
+ * @brief Remove all segment entries from all halfedges.
+ */
void clear();
+
+ /**
+ * @brief Add entry for a segment in a halfedge.
+ *
+ * @param halfedge_index: halfedge containing segment
+ * @param segment_index: segment intersecting halfedge
+ */
void add_segment(int halfedge_index, int segment_index);
+
+ /**
+ * @brief Remove all segments from a given halfedge.
+ *
+ * @param halfedge_index: halfedge in mesh
+ */
void erase_entry(int halfedge_index);
+
+ /**
+ * @brief Get all segments in the given halfedge.
+ *
+ * @param halfedge_index: index of a halfedge in the mesh
+ * @return segments in the halfedge, or an empty list if none exist
+ */
const std::vector& get_halfedge_segments(int halfedge_index);
private:
std::unordered_map> m_h2segments;
std::vector m_empty_list;
};
+// By default, use sparse representation
typedef SparseHalfedgeMap HalfedgeMap;
/**
@@ -47,8 +135,27 @@ typedef SparseHalfedgeMap HalfedgeMap;
class DualLoop
{
public:
+ /**
+ * @brief Update the dual loop after a counter-clockwise flip in the underlying mesh.
+ *
+ * @param m: underlying mesh before the flip
+ * @param halfedge_index: halfedge to be flipped
+ */
virtual void update_under_ccw_flip(const Mesh& m, int halfedge_index) = 0;
+
+ /**
+ * @brief Generate the ordered sequence of face indices the dual loop traverses.
+ *
+ * @param m: underlying mesh
+ * @return sequence of face indices in traversal order
+ */
virtual std::vector generate_face_sequence(const Mesh& m) const = 0;
+
+ /**
+ * @brief Create a heap-allocated copy of this dual loop.
+ *
+ * @return owning pointer to a cloned dual loop of the same concrete type
+ */
virtual std::unique_ptr clone() const = 0;
virtual ~DualLoop() = default;
@@ -59,6 +166,12 @@ class DualLoop
class DualSegmentIterator
{
public:
+ /**
+ * @brief Construct an iterator positioned at the start or end of the loop.
+ *
+ * @param parent: dual loop being iterated
+ * @param is_start: true to position at the first segment, false for the end sentinel
+ */
DualSegmentIterator(const DualLoop& parent, bool is_start = true)
: m_parent(parent)
, m_is_start(is_start)
@@ -67,6 +180,11 @@ class DualLoop
m_current_segment_index = m_start_segment_index;
}
+ /**
+ * @brief Advance the iterator to the next segment (pre-increment).
+ *
+ * @return reference to this iterator after advancing
+ */
DualSegmentIterator& operator++()
{
m_is_start = false;
@@ -74,6 +192,11 @@ class DualLoop
return *this;
}
+ /**
+ * @brief Advance the iterator to the next segment (post-increment).
+ *
+ * @return copy of this iterator before advancing
+ */
DualSegmentIterator operator++(int)
{
DualSegmentIterator temp = *this;
@@ -81,6 +204,16 @@ class DualLoop
return temp;
}
+ /**
+ * @brief Check equality with another iterator.
+ *
+ * Two iterators are equal when they point to the same segment index and
+ * both share the same start/non-start state (to distinguish begin from end
+ * on a closed loop).
+ *
+ * @param rhs: iterator to compare against
+ * @return true if iterators are equal
+ */
bool is_equal(const DualSegmentIterator& rhs) const
{
return (
@@ -98,11 +231,21 @@ class DualLoop
return (!(lhs == rhs));
}
+ /**
+ * @brief Check whether the iterator has traversed the entire loop.
+ *
+ * @return true if the iterator has wrapped back to the start segment
+ */
bool is_end()
{
return ((!m_is_start) && (m_current_segment_index == m_start_segment_index));
}
+ /**
+ * @brief Dereference the iterator to obtain the current dual segment.
+ *
+ * @return dual segment at the current position
+ */
DualSegment operator*() { return m_parent.get_dual_segment(m_current_segment_index); }
private:
@@ -127,8 +270,27 @@ class DualLoop
DualSegmentIterator end() const { return DualSegmentIterator(*this, false); }
protected:
+ /**
+ * @brief Return the index of the segment following the given one in the loop.
+ *
+ * @param segment_index: index of the current segment
+ * @return index of the next segment
+ */
virtual int get_next(int segment_index) const = 0;
+
+ /**
+ * @brief Return the index of the canonical first segment used to initialize iteration.
+ *
+ * @return starting segment index
+ */
virtual int get_start_segment_index() const = 0;
+
+ /**
+ * @brief Return the dual segment stored at the given index.
+ *
+ * @param segment_index: index of the segment to retrieve
+ * @return dual segment (pair of halfedge indices bounding a face crossing)
+ */
virtual DualSegment get_dual_segment(int segment_index) const = 0;
};
@@ -195,42 +357,97 @@ class DualLoopConnectivity : public DualLoop
void enable_validity_checks() { m_check_validity = true; }
protected:
- // Connectivity getters
+ /**
+ * @brief Return the total number of allocated segment slots (including deleted ones).
+ *
+ * @return number of segment slots
+ */
int count_segment_indices() const { return m_next.size(); }
+ /**
+ * @brief Return the index of the segment following the given one in the loop.
+ *
+ * @param segment_index: index of the current segment
+ * @return index of the next segment
+ */
int get_next(int segment_index) const override
{
assert(is_valid_segment_index(segment_index));
return m_next[segment_index];
}
+ /**
+ * @brief Return the index of the segment preceding the given one in the loop.
+ *
+ * @param segment_index: index of the current segment
+ * @return index of the previous segment
+ */
int get_prev(int segment_index) const
{
assert(is_valid_segment_index(segment_index));
return m_prev[segment_index];
}
+ /**
+ * @brief Return the start halfedge of the given segment.
+ *
+ * @param segment_index: index of the segment
+ * @return halfedge index at which the segment enters its face
+ */
int get_start(int segment_index) const
{
assert(is_valid_segment_index(segment_index));
return m_start[segment_index];
}
+ /**
+ * @brief Return the end halfedge of the given segment.
+ *
+ * @param segment_index: index of the segment
+ * @return halfedge index at which the segment exits its face
+ */
int get_end(int segment_index) const
{
assert(is_valid_segment_index(segment_index));
return m_end[segment_index];
}
+ /**
+ * @brief Check whether a segment slot has been freed.
+ *
+ * @param segment_index: index of the segment slot
+ * @return true if the slot is deleted and available for reuse
+ */
bool is_deleted(int segment_index) const { return m_is_deleted[segment_index]; }
// Index based segment management
int get_start_segment_index() const override;
DualSegment get_dual_segment(int segment_index) const override;
- // Validity tests
+ /**
+ * @brief Check whether a segment index is within bounds and not deleted.
+ *
+ * @param segment_index: index to validate
+ * @return true if the index refers to a live segment
+ */
bool is_valid_segment_index(int segment_index) const;
+
+ /**
+ * @brief Verify that the next/prev linkage is internally consistent.
+ *
+ * @return true if all segments form a well-linked circular list
+ */
bool is_valid_connectivity() const;
+
+ /**
+ * @brief Verify that the dual loop correctly overlays the given mesh.
+ *
+ * Checks that every segment's halfedges belong to a common face and that
+ * consecutive segments share an edge crossing.
+ *
+ * @param m: underlying mesh
+ * @return true if the dual loop is geometrically valid on the mesh
+ */
bool is_valid_dual_loop(const Mesh& m) const;
private:
@@ -251,17 +468,51 @@ class DualLoopConnectivity : public DualLoop
bool m_check_validity = false;
- // Atomic loop change operations
+ /**
+ * @brief Split a segment at an interior halfedge, inserting a new segment.
+ *
+ * Used when a flip introduces an edge that bisects an existing segment.
+ *
+ * @param segment_index: segment to split
+ * @param halfedge_index: new halfedge crossing the segment
+ * @param opposite_halfedge: opposite halfedge of the crossing edge
+ */
void split_segment(int segment_index, int halfedge_index, int opposite_halfedge);
+
+ /**
+ * @brief Swap the endpoints of two adjacent segments across a flipped edge.
+ *
+ * @param first_segment_index: first segment involved in the flip
+ * @param second_segment_index: second segment involved in the flip
+ * @param halfedge_index: halfedge that was flipped
+ * @param opposite_halfedge: opposite halfedge of the flipped edge
+ */
void flip_segments(
int first_segment_index,
int second_segment_index,
int halfedge_index,
int opposite_halfedge);
+
+ /**
+ * @brief Merge two consecutive segments into one, removing the shared crossing.
+ *
+ * @param first_segment_index: segment whose end will be extended
+ * @param second_segment_index: segment to be absorbed and deleted
+ */
void combine_segments(int first_segment_index, int second_segment_index);
- // Index memory management
+ /**
+ * @brief Allocate a new segment slot, reusing a freed index if available.
+ *
+ * @return index of the newly created segment slot
+ */
int create_segment_index();
+
+ /**
+ * @brief Mark a segment slot as deleted and return it to the free list.
+ *
+ * @param segment_index: index of the segment to free
+ */
void delete_segment_index(int segment_index);
// TODO Add garbage collector for resizing
@@ -328,13 +579,59 @@ class DualLoopList : public DualLoop
int count_segment_indices() const { return m_dual_path.size(); }
};
+/**
+ * @brief Manager that maps mesh edges to the dual loops crossing them.
+ *
+ * Provides O(1) lookup of which dual loops intersect a given edge, and supports
+ * bulk registration of all edges crossed by a loop.
+ */
class DualLoopManager{
public:
+ /**
+ * @brief Construct a manager sized for the given number of edges.
+ *
+ * @param num_edges: total number of edges in the mesh
+ */
DualLoopManager(int num_edges);
+
+ /**
+ * @brief Remove all edge-to-loop associations.
+ */
void clear();
+
+ /**
+ * @brief Record that a dual loop crosses a given edge.
+ *
+ * @param edge_index: edge intersected by the loop
+ * @param loop_index: index of the dual loop
+ */
void add_loop(int edge_index, int loop_index);
+
+ /**
+ * @brief Register all edges crossed by a dual loop.
+ *
+ * Iterates over every segment of @p dual_loop, determines which mesh edge each
+ * segment crosses, and calls add_loop() for each edge-loop pair.
+ *
+ * @param loop_index: index of the dual loop being registered
+ * @param m: underlying mesh
+ * @param dual_loop: dual loop whose edge crossings will be recorded
+ */
void register_loop_edges(int loop_index, const Mesh& m, const DualLoop& dual_loop);
+
+ /**
+ * @brief Remove all loop associations for a given edge.
+ *
+ * @param edge_index: edge whose loop entries will be cleared
+ */
void erase_entry(int edge_index);
+
+ /**
+ * @brief Get all dual loops crossing a given edge.
+ *
+ * @param edge_index: index of the edge to query
+ * @return loop indices crossing the edge
+ */
const std::vector& get_edge_loops(int edge_index);
private:
std::vector m_e_num_loops;
diff --git a/include/holonomy/holonomy/core/dual_segment.h b/include/holonomy/holonomy/core/dual_segment.h
index 29e6621..c542af4 100644
--- a/include/holonomy/holonomy/core/dual_segment.h
+++ b/include/holonomy/holonomy/core/dual_segment.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
@@ -5,6 +13,20 @@
namespace Penner {
namespace Holonomy {
+/**
+ * @brief Methods to manage sequences of dual segments (pairs of halfedges bounding a face crossing path) on a mesh,
+ * including methods to convert to or from dual loop sequences and to update under counter clockwise edge flips.
+ *
+ * These methods are largely superseded by the Dual Loop representations, which support more efficient
+ * queries, but are useful as a minimal representation for quick implementations and comparison.
+ *
+ */
+
+/**
+ * @brief Representation of a dual segment as two halfedges in a face at the start
+ * and end of the dual segment.
+ *
+ */
typedef std::array DualSegment;
/**
diff --git a/include/holonomy/holonomy/core/homology_basis.h b/include/holonomy/holonomy/core/homology_basis.h
index bac00c1..4bff11c 100644
--- a/include/holonomy/holonomy/core/homology_basis.h
+++ b/include/holonomy/holonomy/core/homology_basis.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
@@ -5,6 +13,16 @@
#include "holonomy/core/dual_loop.h"
#include "util/spanning_tree.h"
+/**
+ * @brief Methods to generate basis dual loops for a mesh. A closed genus g surface has
+ * 2g basis loops.
+ *
+ * For meshes with boundary, this generates the basis loops that do not bound holes.
+ * Basis loops corresponding holes are generally irrelevant in the seamless context,
+ * but can be generated by the Boundary Basis methods.
+ *
+ */
+
namespace Penner {
namespace Holonomy {
diff --git a/include/holonomy/holonomy/core/quality.h b/include/holonomy/holonomy/core/quality.h
index aac459b..b9a35b6 100644
--- a/include/holonomy/holonomy/core/quality.h
+++ b/include/holonomy/holonomy/core/quality.h
@@ -1,5 +1,18 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#include "holonomy/core/common.h"
+/**
+ * @brief Methods to compute the quality of triangles in a mesh.
+ *
+ */
+
namespace Penner {
namespace Holonomy {
diff --git a/include/holonomy/holonomy/core/viewer.h b/include/holonomy/holonomy/core/viewer.h
index 0a7b425..90e4493 100644
--- a/include/holonomy/holonomy/core/viewer.h
+++ b/include/holonomy/holonomy/core/viewer.h
@@ -1,20 +1,40 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
#include "holonomy/holonomy/marked_penner_cone_metric.h"
-#include "optimization/core/viewer.h"
+#include "metric/viewer.h"
#ifdef ENABLE_VISUALIZATION
#include "polyscope/surface_mesh.h"
#endif
+/**
+ * @brief Collection of viewers.
+ *
+ */
+
namespace Penner {
namespace Holonomy {
-using Optimization::generate_doubled_mesh;
-using Optimization::generate_FV_halfedge_data;
-
+/**
+ * @brief View a frame field on a mesh.
+ *
+ * @param V: mesh vertices
+ * @param F: mesh faces
+ * @param frame_field: per-face frame directions
+ * @param Th_hat: target cone angles at vertices
+ * @param mesh_handle: (optional) name for the surface mesh in the viewer
+ * @param scale: (optional) glyph scale for displayed frame vectors
+ */
void view_frame_field(
const Eigen::MatrixXd& V,
const Eigen::MatrixXi& F,
@@ -23,6 +43,7 @@ void view_frame_field(
std::string mesh_handle="",
Scalar scale=0.005);
+
/**
* @brief View a cross field on a mesh.
*
@@ -43,12 +64,31 @@ void view_cross_field(
const Eigen::MatrixXi& period_jump,
std::string mesh_handle = "intrinsic_field_mesh");
+/**
+ * @brief View a vector field on a mesh.
+ *
+ * @param V: mesh vertices
+ * @param F: mesh faces
+ * @param vector_field: per-face tangent vectors to display
+ * @param mesh_handle: (optional) name for the surface mesh in the viewer
+ */
void view_vector_field(
const Eigen::MatrixXd& V,
const Eigen::MatrixXi& F,
const Eigen::MatrixXd& vector_field,
std::string mesh_handle="");
+/**
+ * @brief View a rotation form on a mesh as a per-edge colormap.
+ *
+ * @param m: underlying mesh
+ * @param vtx_reindex: map from mesh vertex indices to original vertex indices
+ * @param V: mesh vertices
+ * @param rotation_form: per-halfedge rotation angles
+ * @param Th_hat: target cone angles at vertices
+ * @param mesh_handle: (optional) name for the surface mesh in the viewer
+ * @param show: (optional) if true, open the viewer
+ */
void view_rotation_form(
const Mesh& m,
const std::vector& vtx_reindex,
@@ -58,6 +98,15 @@ void view_rotation_form(
std::string mesh_handle="",
bool show=true);
+/**
+ * @brief View the holonomy constraint error of a cone metric as a per-vertex colormap.
+ *
+ * @param marked_metric: marked Penner cone metric with holonomy constraints
+ * @param vtx_reindex: map from mesh vertex indices to original vertex indices
+ * @param V: mesh vertices
+ * @param mesh_handle: (optional) name for the surface mesh in the viewer
+ * @param show: (optional) if true, open the viewer
+ */
void view_constraint_error(
const MarkedPennerConeMetric& marked_metric,
const std::vector& vtx_reindex,
@@ -84,6 +133,16 @@ void view_seamless_parameterization(
bool show=true);
+/**
+ * @brief View the homology basis loops of a marked cone metric on a mesh.
+ *
+ * @param marked_metric: marked Penner cone metric containing the homology basis
+ * @param vtx_reindex: map from mesh vertex indices to original vertex indices
+ * @param V: mesh vertices
+ * @param num_homology_basis_loops: (optional) number of basis loops to display; -1 shows all
+ * @param mesh_handle: (optional) name for the surface mesh in the viewer
+ * @param show: (optional) if true, open the viewer
+ */
void view_homology_basis(
const MarkedPennerConeMetric& marked_metric,
const std::vector& vtx_reindex,
@@ -92,11 +151,35 @@ void view_homology_basis(
std::string mesh_handle="",
bool show=true);
+/**
+ * @brief Compute per-edge seamless error metrics for a UV parameterization.
+ *
+ * Returns four per-edge vectors measuring how far the parameterization deviates
+ * from seamlessness across each interior edge.
+ *
+ * @param F: mesh faces (vertex indices)
+ * @param uv: UV vertex positions
+ * @param F_uv: UV faces (uv vertex indices, parallel to F)
+ * @return tuple of (translation error, rotation error, period jump error, total error)
+ */
std::tuple compute_seamless_error(
const Eigen::MatrixXi& F,
const Eigen::MatrixXd& uv,
const Eigen::MatrixXi& F_uv);
+/**
+ * @brief View parameterization quality metrics as per-face colormaps.
+ *
+ * Displays distortion measures (e.g., conformal and isometric distortion) to
+ * assess the quality of a UV parameterization.
+ *
+ * @param V: mesh vertices
+ * @param F: mesh faces
+ * @param uv: uv vertex positions
+ * @param FT: uv faces
+ * @param mesh_handle: (optional) name for the surface mesh in the viewer
+ * @param show: (optional) if true, open the viewer
+ */
void view_parameterization_quality(
const Eigen::MatrixXd& V,
const Eigen::MatrixXi& F,
@@ -105,16 +188,48 @@ void view_parameterization_quality(
std::string mesh_handle="",
bool show=true);
+/**
+ * @brief Compute the per-corner angle error of a UV parameterization.
+ *
+ * Measures how much the UV angles deviate from being quantized to multiples
+ * of Pi/2.
+ *
+ * @param F: mesh faces (vertex indices)
+ * @param uv: UV vertex positions
+ * @param F_uv: UV faces (uv vertex indices, parallel to F)
+ * @return per-corner angle errors
+ */
VectorX compute_angle_error(
const Eigen::MatrixXi& F,
const Eigen::MatrixXd& uv,
const Eigen::MatrixXi& F_uv);
+/**
+ * @brief Compute the Euclidean length of a UV edge.
+ *
+ * @param uv_0: first UV coordinate
+ * @param uv_1: second UV coordinate
+ * @return length of the segment from uv_0 to uv_1
+ */
Scalar compute_uv_length(const Eigen::Vector2d& uv_0, const Eigen::Vector2d& uv_1);
+/**
+ * @brief Compute the cosine of the angle at uv_0 in the triangle (uv_0, uv_1, origin).
+ *
+ * @param uv_0: vertex at which the angle is measured
+ * @param uv_1: opposite vertex
+ * @return cosine of the angle at uv_0
+ */
Scalar uv_cos_angle(const Eigen::Vector2d& uv_0, const Eigen::Vector2d& uv_1);
+/**
+ * @brief Compute the angle at uv_0 in the triangle (uv_0, uv_1, origin).
+ *
+ * @param uv_0: vertex at which the angle is measured
+ * @param uv_1: opposite vertex
+ * @return angle in radians at uv_0
+ */
Scalar uv_angle(const Eigen::Vector2d& uv_0, const Eigen::Vector2d& uv_1);
} // namespace Holonomy
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/field/field.h b/include/holonomy/holonomy/field/field.h
deleted file mode 100644
index e61eb71..0000000
--- a/include/holonomy/holonomy/field/field.h
+++ /dev/null
@@ -1,23 +0,0 @@
-
-#pragma once
-
-#include "holonomy/core/common.h"
-
-namespace Penner {
-namespace Holonomy {
-
-/**
- * @brief Generate a cross field for a mesh
- *
- * @param V: mesh vertices
- * @param F: mesh faces
- * @return |F|x3 frame field of per-face field direction vectors
- * @return per-vertex cone angles corresponding to the frame field
- */
-std::tuple> generate_cross_field(
- const Eigen::MatrixXd& V,
- const Eigen::MatrixXi& F);
-
-
-} // namespace Holonomy
-} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/holonomy/cones.h b/include/holonomy/holonomy/holonomy/cones.h
index a07bd18..1f650ff 100644
--- a/include/holonomy/holonomy/holonomy/cones.h
+++ b/include/holonomy/holonomy/holonomy/cones.h
@@ -1,8 +1,22 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
#include "holonomy/holonomy/marked_penner_cone_metric.h"
+/**
+ * @brief Methods to compute cones on a surface from field data, as well as various
+ * queries and methods to modify invalid or challenging cone configurations.
+ *
+ */
+
namespace Penner {
namespace Holonomy {
@@ -80,4 +94,4 @@ std::pair count_cones(const Mesh& m);
bool is_interior(const Mesh& m, int vi);
} // namespace Holonomy
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/holonomy/constraint.h b/include/holonomy/holonomy/holonomy/constraint.h
index 8ad11fe..6224012 100644
--- a/include/holonomy/holonomy/holonomy/constraint.h
+++ b/include/holonomy/holonomy/holonomy/constraint.h
@@ -1,24 +1,64 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
#include "holonomy/holonomy/marked_penner_cone_metric.h"
+/**
+ * @brief Holonomy signature constraints, including vertex cone angles and dual loop angle constraints.
+ * Also includes methods to compute the constraint Jacobians, which are needed for first-order methods.
+ *
+ */
+
namespace Penner {
namespace Holonomy {
/**
- * @brief Compute dual loop holonomy angles for a mesh with given angles
+ * @brief
*
* @param[in] m: mesh topology
* @param[in] homology_basis_loops: dual loops for holonomy angle computation
* @param[in] alpha: per-halfedge angles for the mesh
* @return vector of dual loop holonomy angles
*/
-VectorX
-Kappa(const Mesh& m, const std::vector>& homology_basis_loops, const VectorX& alpha);
+VectorX Kappa(const Mesh& m, const std::vector>& homology_basis_loops, const VectorX& alpha);
VectorX Kappa(const MarkedPennerConeMetric& marked_metric, const VectorX& alpha);
+/**
+ * @brief Given a list of dual loops, compute a matrix with columns given by the corresponding
+ * closed one forms for the dual loops.
+ *
+ * @param m: mesh
+ * @param dual_loops: loops defining the one forms
+ * @return matrix of dual loop one forms
+ */
+MatrixX build_dual_loop_basis_one_form_matrix(
+ const Mesh& m,
+ const std::vector>& dual_loops);
+
+/**
+ * @brief Given a mesh and a homology basis, compute a matrix for the space of closed one forms
+ * with the first |V| (or |V| - 1) columns corresponding to vertex hat function derivatives and the
+ * last 2g corresponding to the homology basis loops.
+ *
+ * @param m: mesh
+ * @param homology_basis_loops: homology basis loops for the mesh
+ * @param eliminate_vertex: remove the last vertex of the mesh so that the matrix is full rank
+ * @return matrix with basis forms as columns
+ */
+MatrixX build_closed_one_form_matrix(
+ const Mesh& m,
+ const std::vector>& homology_basis_loops,
+ bool eliminate_vertex = false);
+
/**
* @brief Compute vertex cone holonomy constraints
*
diff --git a/include/holonomy/holonomy/holonomy/holonomy.h b/include/holonomy/holonomy/holonomy/holonomy.h
index d7ce7e5..5163a38 100644
--- a/include/holonomy/holonomy/holonomy/holonomy.h
+++ b/include/holonomy/holonomy/holonomy/holonomy.h
@@ -1,8 +1,22 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
#include "holonomy/holonomy/marked_penner_cone_metric.h"
+/**
+ * @brief Methods to compute the holonomy of dual loops on a surface with metric data,
+ * as well as the rotation of a field under the dual loop.
+ *
+ */
+
namespace Penner {
namespace Holonomy {
diff --git a/include/holonomy/holonomy/holonomy/marked_penner_cone_metric.h b/include/holonomy/holonomy/holonomy/marked_penner_cone_metric.h
index 8cafc58..08518ee 100644
--- a/include/holonomy/holonomy/holonomy/marked_penner_cone_metric.h
+++ b/include/holonomy/holonomy/holonomy/marked_penner_cone_metric.h
@@ -1,10 +1,25 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
#include "holonomy/core/dual_loop.h"
#include "holonomy/core/homology_basis.h"
-#include "optimization/core/cone_metric.h"
+#include "metric/cone_metric.h"
+
+/**
+ * @brief Extension of the differentiable cone metric using Penner coordinates
+ * to include dual loop holonomy constraints, which allow for full seamless metric
+ * constraints.
+ *
+ */
namespace Penner {
namespace Holonomy {
@@ -23,7 +38,7 @@ bool is_valid_mesh(const Mesh& m);
/**
* @brief Class to represent a mesh with a Penner metric and homology basis markings
*/
-class MarkedPennerConeMetric : public Optimization::PennerConeMetric
+class MarkedPennerConeMetric : public PennerConeMetric
{
public:
// Additional constraints for homology loops
@@ -132,7 +147,7 @@ class MarkedPennerConeMetric : public Optimization::PennerConeMetric
// TODO Use Newton
virtual std::unique_ptr project_to_constraint(
SolveStats& solve_stats,
- std::shared_ptr proj_params =
+ std::shared_ptr proj_params =
nullptr) const override;
// Flip method
diff --git a/include/holonomy/holonomy/holonomy/newton.h b/include/holonomy/holonomy/holonomy/newton.h
index 6e1074a..54bb61e 100644
--- a/include/holonomy/holonomy/holonomy/newton.h
+++ b/include/holonomy/holonomy/holonomy/newton.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
@@ -7,6 +15,12 @@
#include
+/**
+ * @brief Modified Newton method to find a Marked Penner Cone Metric satisfying holonomy
+ * signature constraints.
+ *
+ */
+
namespace Penner {
namespace Holonomy {
diff --git a/include/holonomy/holonomy/holonomy/rotation_form.h b/include/holonomy/holonomy/holonomy/rotation_form.h
index a026190..621cb13 100644
--- a/include/holonomy/holonomy/holonomy/rotation_form.h
+++ b/include/holonomy/holonomy/holonomy/rotation_form.h
@@ -1,7 +1,24 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
-#include "holonomy/field/intrinsic_field.h"
+#include "field/intrinsic_field.h"
+
+/**
+ * @brief Methods to compute a rotation form, either from an existing field or generated
+ * using a cross-field optimization method.
+ *
+ * The rotation form is a minimal representation of a cross field (up to global phase),
+ * encoding the rotation of the field across edges.
+ *
+ */
namespace Penner {
namespace Holonomy {
@@ -23,13 +40,13 @@ VectorX generate_rotation_form_from_cross_field(
const Eigen::MatrixXi& F,
const Eigen::MatrixXd& frame_field);
-VectorX generate_intrinsic_rotation_form(const Mesh& m, const FieldParameters& field_params);
+VectorX generate_intrinsic_rotation_form(const Mesh& m, const Field::FieldParameters& field_params);
VectorX generate_intrinsic_rotation_form(
const Mesh& m,
const std::vector& vtx_reindex,
const Eigen::MatrixXd& V,
- const FieldParameters& field_params);
+ const Field::FieldParameters& field_params);
} // namespace Holonomy
} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/interface.h b/include/holonomy/holonomy/interface.h
index 9005170..5eeed38 100644
--- a/include/holonomy/holonomy/interface.h
+++ b/include/holonomy/holonomy/interface.h
@@ -1,7 +1,15 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
-#include "holonomy/field/field.h"
+#include "field/field.h"
#include "holonomy/holonomy/rotation_form.h"
#include "holonomy/holonomy/marked_penner_cone_metric.h"
#include "holonomy/similarity/similarity_penner_cone_metric.h"
@@ -225,14 +233,14 @@ std::vector extend_vtx_reindex(
std::tuple> generate_intrinsic_rotation_form(
const Eigen::MatrixXd& V,
const Eigen::MatrixXi& F,
- const FieldParameters& field_params);
+ const Field::FieldParameters& field_params);
std::vector compute_kappa(
const Mesh& discrete_metric,
const VectorX& rotation_form,
const std::vector>& basis_loops);
-Optimization::DiscreteMetric generate_discrete_metric(const Mesh& m);
+DiscreteMetric generate_discrete_metric(const Mesh& m);
} // namespace Holonomy
} // namespace Penner
\ No newline at end of file
diff --git a/include/holonomy/holonomy/pybind.h b/include/holonomy/holonomy/pybind.h
index 8b4c71d..19b7eee 100644
--- a/include/holonomy/holonomy/pybind.h
+++ b/include/holonomy/holonomy/pybind.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#ifdef PYBIND
#ifndef MULTIPRECISION
diff --git a/include/holonomy/holonomy/similarity/conformal.h b/include/holonomy/holonomy/similarity/conformal.h
index 2227a63..6e9eca7 100644
--- a/include/holonomy/holonomy/similarity/conformal.h
+++ b/include/holonomy/holonomy/similarity/conformal.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
diff --git a/include/holonomy/holonomy/similarity/constraint.h b/include/holonomy/holonomy/similarity/constraint.h
index a7e4173..3be7a55 100644
--- a/include/holonomy/holonomy/similarity/constraint.h
+++ b/include/holonomy/holonomy/similarity/constraint.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
diff --git a/include/holonomy/holonomy/similarity/energy.h b/include/holonomy/holonomy/similarity/energy.h
index c1c29f7..126728a 100644
--- a/include/holonomy/holonomy/similarity/energy.h
+++ b/include/holonomy/holonomy/similarity/energy.h
@@ -1,3 +1,11 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
diff --git a/include/holonomy/holonomy/similarity/layout.h b/include/holonomy/holonomy/similarity/layout.h
index db8e5f6..a29af77 100644
--- a/include/holonomy/holonomy/similarity/layout.h
+++ b/include/holonomy/holonomy/similarity/layout.h
@@ -1,9 +1,17 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
#include "holonomy/similarity/similarity_penner_cone_metric.h"
-#include "optimization/parameterization/interpolation.h"
+#include "parametrization/interpolation.h"
#include "conformal_ideal_delaunay/OverlayMesh.hh"
diff --git a/include/holonomy/holonomy/similarity/similarity_penner_cone_metric.h b/include/holonomy/holonomy/similarity/similarity_penner_cone_metric.h
index f729d43..b1bbee9 100644
--- a/include/holonomy/holonomy/similarity/similarity_penner_cone_metric.h
+++ b/include/holonomy/holonomy/similarity/similarity_penner_cone_metric.h
@@ -1,7 +1,15 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include "holonomy/core/common.h"
-#include "holonomy/field/forms.h"
+#include "field/forms.h"
#include "holonomy/holonomy/marked_penner_cone_metric.h"
namespace Penner {
@@ -52,7 +60,7 @@ class SimilarityPennerConeMetric : public MarkedPennerConeMetric
bool only_free_vertices) const override;
std::unique_ptr project_to_constraint(
SolveStats& solve_stats,
- std::shared_ptr proj_params =
+ std::shared_ptr proj_params =
nullptr) const override;
// Discrete metric methods
@@ -61,12 +69,12 @@ class SimilarityPennerConeMetric : public MarkedPennerConeMetric
// One form getters and setters
void set_one_form(const VectorX& one_form)
{
- assert(is_closed_one_form(*this, one_form));
+ assert(Field::is_closed_one_form(*this, one_form));
m_one_form = one_form;
}
void set_one_form_direction(const VectorX& one_form_direction)
{
- assert(is_closed_one_form(*this, one_form_direction));
+ assert(Field::is_closed_one_form(*this, one_form_direction));
m_one_form_direction = one_form_direction;
}
const VectorX& get_one_form() const { return m_one_form; }
@@ -104,4 +112,4 @@ void MakeSimilarityDelaunay(
bool Ptolemy = true);
} // namespace Holonomy
-} // namespace Penner
\ No newline at end of file
+} // namespace Penner
diff --git a/include/optimization/optimization/core/area.h b/include/metric/metric/area.h
similarity index 50%
rename from include/optimization/optimization/core/area.h
rename to include/metric/metric/area.h
index 73dd657..03a4e4b 100644
--- a/include/optimization/optimization/core/area.h
+++ b/include/metric/metric/area.h
@@ -1,40 +1,23 @@
-/*********************************************************************************
-* This file is part of reference implementation of SIGGRAPH Asia 2023 Paper *
-* `Metric Optimization in Penner Coordinates` *
-* v1.0 *
-* *
-* The MIT License *
-* *
-* Permission is hereby granted, free of charge, to any person obtaining a *
-* copy of this software and associated documentation files (the "Software"), *
-* to deal in the Software without restriction, including without limitation *
-* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
-* and/or sell copies of the Software, and to permit persons to whom the *
-* Software is furnished to do so, subject to the following conditions: *
-* *
-* The above copyright notice and this permission notice shall be included in *
-* all copies or substantial portions of the Software. *
-* *
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
-* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE *
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
-* IN THE SOFTWARE. *
-* *
-* Author(s): *
-* Ryan Capouellez, Denis Zorin, *
-* Courant Institute of Mathematical Sciences, New York University, USA *
-* * *
-*********************************************************************************/
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
-#include "optimization/core/common.h"
-#include "optimization/core/cone_metric.h"
+/**
+ * @brief Methods to compute the area of triangles from intrinsic lengths, along
+ * with the derivatives with respect to lengths and log lengths.
+ *
+ */
+
+#include "metric/common.h"
+#include "metric/cone_metric.h"
namespace Penner {
-namespace Optimization {
/// Compute the squared area of the triangle with edge lengths li, lj, lk using
/// the numerically stable version of Heron's formula.
@@ -91,5 +74,4 @@ VectorX squared_area_length_derivatives(const Mesh& m);
/// @return map from halfedges to the derivative of the square of the area of the face containing it
VectorX squared_area_log_length_derivatives(const Mesh& m);
-} // namespace Optimization
} // namespace Penner
\ No newline at end of file
diff --git a/include/metric/metric/common.h b/include/metric/metric/common.h
new file mode 100644
index 0000000..4c7814a
--- /dev/null
+++ b/include/metric/metric/common.h
@@ -0,0 +1,54 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+/**
+ * @brief Assorted utility functions.
+ *
+ */
+
+#include "util/common.h"
+#include "metric/globals.h"
+
+#include
+#include
+
+#include
+#include
+
+namespace Penner {
+
+// Check if two vectors are component-wise equal, up to a tolerance.
+//
+/// @param[in] v: first vector to compare
+/// @param[in] w: second vector to compare
+/// @param[in] eps: tolerance for equality
+/// @return true iff ||v - i||_inf < eps
+bool vector_equal(VectorX v, VectorX w, Scalar eps = 1e-10);
+
+/// Check if a matrix contains a nan
+///
+/// @param[in] mat: matrix to check
+/// @return true iff mat contains a nan
+bool matrix_contains_nan(const Eigen::MatrixXd& mat);
+
+// Compute the sup norm of a vector.
+//
+/// @param[in] v: vector
+/// @return sup norm of v
+Scalar sup_norm(const VectorX& v);
+
+// Compute the sup norm of a matrix.
+//
+/// @param[in] matrix: matrix
+/// @return sup norm of the matrix
+Scalar matrix_sup_norm(const MatrixX& matrix);
+
+
+} // namespace Penner
\ No newline at end of file
diff --git a/include/optimization/optimization/core/cone_metric.h b/include/metric/metric/cone_metric.h
similarity index 85%
rename from include/optimization/optimization/core/cone_metric.h
rename to include/metric/metric/cone_metric.h
index e0e50cd..ae1d1d5 100644
--- a/include/optimization/optimization/core/cone_metric.h
+++ b/include/metric/metric/cone_metric.h
@@ -1,43 +1,28 @@
-/*********************************************************************************
-* This file is part of reference implementation of SIGGRAPH Asia 2023 Paper *
-* `Metric Optimization in Penner Coordinates` *
-* v1.0 *
-* *
-* The MIT License *
-* *
-* Permission is hereby granted, free of charge, to any person obtaining a *
-* copy of this software and associated documentation files (the "Software"), *
-* to deal in the Software without restriction, including without limitation *
-* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
-* and/or sell copies of the Software, and to permit persons to whom the *
-* Software is furnished to do so, subject to the following conditions: *
-* *
-* The above copyright notice and this permission notice shall be included in *
-* all copies or substantial portions of the Software. *
-* *
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
-* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE *
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
-* IN THE SOFTWARE. *
-* *
-* Author(s): *
-* Ryan Capouellez, Denis Zorin, *
-* Courant Institute of Mathematical Sciences, New York University, USA *
-* * *
-*********************************************************************************/
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
#include
#include "util/embedding.h"
-#include "optimization/core/common.h"
-#include "optimization/core/flip_matrix_generator.h"
+#include "metric/common.h"
+#include "metric/flip_matrix_generator.h"
+
+/**
+ * @brief Core representation of a differentiable intrinsic metric on an underlying halfedge mesh, with
+ * support for edge flips and projection to intrinsic metric constraints.
+ *
+ * Also includes the basic differentiable metric coordinates: log length coordinates and Penner coordinates.
+ *
+ */
namespace Penner {
-namespace Optimization {
/// Representation of a differentiable intrinsic metric on a mesh with angle constraints at cones.
///
@@ -60,6 +45,7 @@ namespace Optimization {
/// - Computation of the cone angle constraint error with reduced coordinate Jacobian
/// - Compute a new metric satisfying the constraints
/// - Compute the change of coordinates flip Jacobian
+/// TODO: Check if interface still up to date
///
class DifferentiableConeMetric : public Mesh
{
@@ -358,5 +344,4 @@ class DiscreteMetric : public DifferentiableConeMetric
void expand_metric_coordinates(const VectorX& metric_coords);
};
-} // namespace Optimization
} // namespace Penner
\ No newline at end of file
diff --git a/include/optimization/optimization/core/constraint.h b/include/metric/metric/constraint.h
similarity index 63%
rename from include/optimization/optimization/core/constraint.h
rename to include/metric/metric/constraint.h
index dc710ec..6d02a53 100644
--- a/include/optimization/optimization/core/constraint.h
+++ b/include/metric/metric/constraint.h
@@ -1,40 +1,25 @@
-/*********************************************************************************
-* This file is part of reference implementation of SIGGRAPH Asia 2023 Paper *
-* `Metric Optimization in Penner Coordinates` *
-* v1.0 *
-* *
-* The MIT License *
-* *
-* Permission is hereby granted, free of charge, to any person obtaining a *
-* copy of this software and associated documentation files (the "Software"), *
-* to deal in the Software without restriction, including without limitation *
-* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
-* and/or sell copies of the Software, and to permit persons to whom the *
-* Software is furnished to do so, subject to the following conditions: *
-* *
-* The above copyright notice and this permission notice shall be included in *
-* all copies or substantial portions of the Software. *
-* *
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
-* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE *
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
-* IN THE SOFTWARE. *
-* *
-* Author(s): *
-* Ryan Capouellez, Denis Zorin, *
-* Courant Institute of Mathematical Sciences, New York University, USA *
-* * *
-*********************************************************************************/
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
-#include "optimization/core/common.h"
-#include "optimization/core/cone_metric.h"
+#include "metric/common.h"
+#include "metric/cone_metric.h"
+
+/**
+ * @brief Methods to compute triangle inequality and differentiable cone angle constraints.
+ *
+ * Also includes cone enumeration, and elimination of redundant or other fixed degrees of
+ * freedom in the vertex cone angle constraints.
+ *
+ */
namespace Penner {
-namespace Optimization {
/**
@@ -136,9 +121,16 @@ Scalar compute_max_constraint(const DifferentiableConeMetric& cone_metric);
*/
VectorX compute_cone_angles(const DifferentiableConeMetric& cone_metric);
+/**
+ * @brief Method to compute the angles of a triangle with given lengths
+ *
+ * @param l12: first edge length
+ * @param l23: second edge length
+ * @param l31: third edge length
+ * @return corner angles at v1, v2, v3
+ */
std::array compute_triangle_angles(Scalar l12, Scalar l23, Scalar l31);
/// TODO Optionally add halfedge coordinate Jacobians
-} // namespace Optimization
} // namespace Penner
\ No newline at end of file
diff --git a/include/metric/metric/flip_matrix_generator.h b/include/metric/metric/flip_matrix_generator.h
new file mode 100644
index 0000000..d8e4ab7
--- /dev/null
+++ b/include/metric/metric/flip_matrix_generator.h
@@ -0,0 +1,93 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "metric/common.h"
+
+/**
+ * @brief Data structure to iteratively compute the change of coordinate matrix for intrinsic flips, e.g., in Penner coordinates.
+ *
+ */
+
+namespace Penner {
+
+/// Class for iteratively building the flip change of coordinate matrix
+class FlipMatrixGenerator
+{
+public:
+ /// Initialize an identity matrix
+ ///
+ /// @param[in] size: dimension of the flip matrix
+ FlipMatrixGenerator(int size);
+
+ /// Reset the matrix to the identity
+ void reset();
+
+ /// Multiply the current matrix by a flip matrix Di for a given edge on the left.
+ ///
+ /// The flip matrix is the identity except the row ed, which has the values indicated
+ /// by the (ed, j, v) specified by matrix indices and scalars
+ ///
+ /// @param[in] column_indices: column indices j for row ed of the matrix Di
+ /// @param[in] values: values v for row ed of the matrix Di
+ /// @param[in] ed: edge index for the nontrivial row of the matrix Di
+ void multiply_by_matrix(
+ const std::array& column_indices,
+ const std::array& values,
+ int ed);
+
+ /// Generate a standard sparse representation of the current matrix
+ ///
+ /// @return flip matrix
+ MatrixX build_matrix() const;
+
+private:
+ int m_size;
+ std::vector>> m_list_of_lists;
+};
+
+/// Class for incrementally building the flip change of coordinate matrix using a standard template
+/// library map representation
+///
+/// NOTE: Potential alternative representation of the flip matrix generator.
+class FlipMapMatrixGenerator
+{
+public:
+ /// Initialize an identity matrix
+ ///
+ /// @param[in] size: dimension of the flip matrix
+ FlipMapMatrixGenerator(int size);
+
+ /// Reset the matrix to the identity
+ void reset();
+
+ /// Multiply the current matrix by a flip matrix Di for a given edge on the left.
+ ///
+ /// The flip matrix is the identity except the row ed, which has the values indicated
+ /// by the (ed, j, v) specified by matrix indices and scalars
+ ///
+ /// @param[in] column_indices: column indices j for row ed of the matrix Di
+ /// @param[in] values: values v for row ed of the matrix Di
+ /// @param[in] ed: edge index for the nontrivial row of the matrix Di
+ void multiply_by_matrix(
+ const std::array& column_indices,
+ const std::array& values,
+ int ed);
+
+ /// Generate a standard sparse representation of the current matrix
+ ///
+ /// @return flip matrix
+ MatrixX build_matrix() const;
+
+private:
+ int m_size;
+ std::vector> m_list_of_lists;
+};
+
+} // namespace Penner
\ No newline at end of file
diff --git a/include/metric/metric/globals.h b/include/metric/metric/globals.h
new file mode 100644
index 0000000..71454a8
--- /dev/null
+++ b/include/metric/metric/globals.h
@@ -0,0 +1,34 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "util/common.h"
+
+namespace Penner {
+
+// Parameters to pass to the conformal method for projecting to the constraint.
+// More detail on these parameters can be found in the documentation for that
+// method.
+struct ProjectionParameters
+{
+ int max_itr = 100; // maximum number of iterations
+ Scalar bound_norm_thres = 1e-10; // line search threshold for dropping the gradient norm bound
+#ifdef MULTIPRECISION
+ Scalar error_eps = 1e-24; // minimum error termination condition
+#else
+ Scalar error_eps = 1e-8; // minimum error termination condition
+#endif
+ bool do_reduction =
+ true; // reduce the initial line step if the range of coordinate values is large
+ bool initial_ptolemy = true; // initial_ptolemy: use ptolemy flips for the initial make_delaunay
+ bool use_edge_flips = true; // use intrinsic edge flips
+ std::string output_dir = "";
+};
+
+} // namespace Penner
\ No newline at end of file
diff --git a/include/optimization/optimization/core/projection.h b/include/metric/metric/projection.h
similarity index 59%
rename from include/optimization/optimization/core/projection.h
rename to include/metric/metric/projection.h
index 8c85353..da5415a 100644
--- a/include/optimization/optimization/core/projection.h
+++ b/include/metric/metric/projection.h
@@ -1,40 +1,23 @@
-/*********************************************************************************
-* This file is part of reference implementation of SIGGRAPH Asia 2023 Paper *
-* `Metric Optimization in Penner Coordinates` *
-* v1.0 *
-* *
-* The MIT License *
-* *
-* Permission is hereby granted, free of charge, to any person obtaining a *
-* copy of this software and associated documentation files (the "Software"), *
-* to deal in the Software without restriction, including without limitation *
-* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
-* and/or sell copies of the Software, and to permit persons to whom the *
-* Software is furnished to do so, subject to the following conditions: *
-* *
-* The above copyright notice and this permission notice shall be included in *
-* all copies or substantial portions of the Software. *
-* *
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
-* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE *
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
-* IN THE SOFTWARE. *
-* *
-* Author(s): *
-* Ryan Capouellez, Denis Zorin, *
-* Courant Institute of Mathematical Sciences, New York University, USA *
-* * *
-*********************************************************************************/
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
-#include "optimization/core/common.h"
-#include "optimization/core/cone_metric.h"
+/**
+ * @brief Methods to project a metric conformally to cone constraints, and to project
+ * metric coordinate vectors to the tangent space of the constraint submanifold.
+ *
+ */
+
+#include "metric/common.h"
+#include "metric/cone_metric.h"
namespace Penner {
-namespace Optimization {
/// Create matrix mapping vertex scale factors to their corresponding edges.
///
@@ -118,5 +101,4 @@ VectorX project_descent_direction(
const DifferentiableConeMetric& cone_metric,
const VectorX& descent_direction);
-} // namespace Optimization
} // namespace Penner
\ No newline at end of file
diff --git a/include/metric/metric/reparametrization.h b/include/metric/metric/reparametrization.h
new file mode 100644
index 0000000..31778c5
--- /dev/null
+++ b/include/metric/metric/reparametrization.h
@@ -0,0 +1,51 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "metric/common.h"
+
+/**
+ * @brief Methods for changing edge and interior barycentric coordinates as determined
+ * by hyperbolic edge translations.
+ *
+ * Translations for mapping between surfaces can be computed using methods in translation.h.
+ */
+
+namespace Penner {
+
+/// Reparametrize the barycentric coordinates for the equilateral triangle by
+/// translating a constant hyperbolic distance along each halfedge. If the sum
+/// of translations per triangle is 0, then this corresponds to a projective map
+/// over the triangle.
+///
+/// @param[in, out] m_o: mesh to reparametrize
+/// @param[in] tau: per halfeedge hyperbolic translation distances
+template
+void bc_reparametrize_eq(OverlayMesh& m_o, const VectorX& tau);
+
+/// Reparametrize points contained in equilateral reference triangles by
+/// translating a constant hyperbolic distance along each halfedge. If the sum
+/// of translations per triangle is 0, then this corresponds to a projective map
+/// over the triangle.
+///
+/// @param[in, out] pts: points to reparameterize
+/// @param[in] n: next halfedge array for mesh
+/// @param[in] h: face to halfedge array for mesh
+/// @param[in] tau: per halfeedge hyperbolic translation distances
+template
+void reparametrize_equilateral(
+ std::vector>& pts,
+ const std::vector& n,
+ const std::vector& h,
+ const VectorX& tau);
+
+#ifdef PYBIND
+#endif
+
+} // namespace Penner
\ No newline at end of file
diff --git a/include/optimization/optimization/core/shear.h b/include/metric/metric/shear.h
similarity index 53%
rename from include/optimization/optimization/core/shear.h
rename to include/metric/metric/shear.h
index eb9248d..dfe7882 100644
--- a/include/optimization/optimization/core/shear.h
+++ b/include/metric/metric/shear.h
@@ -1,40 +1,26 @@
-/*********************************************************************************
-* This file is part of reference implementation of SIGGRAPH Asia 2023 Paper *
-* `Metric Optimization in Penner Coordinates` *
-* v1.0 *
-* *
-* The MIT License *
-* *
-* Permission is hereby granted, free of charge, to any person obtaining a *
-* copy of this software and associated documentation files (the "Software"), *
-* to deal in the Software without restriction, including without limitation *
-* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
-* and/or sell copies of the Software, and to permit persons to whom the *
-* Software is furnished to do so, subject to the following conditions: *
-* *
-* The above copyright notice and this permission notice shall be included in *
-* all copies or substantial portions of the Software. *
-* *
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
-* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE *
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
-* IN THE SOFTWARE. *
-* *
-* Author(s): *
-* Ryan Capouellez, Denis Zorin, *
-* Courant Institute of Mathematical Sciences, New York University, USA *
-* * *
-*********************************************************************************/
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
-#include "optimization/core/common.h"
-#include "optimization/core/cone_metric.h"
+#include "metric/common.h"
+#include "metric/cone_metric.h"
+
+/**
+ * @brief Methods to compute the shear coordinates of a metric from Penner coordinates
+ * and shear coordinate bases, linearly independent from the conformal scaling space.
+ *
+ * Also can compute the change in shear coordinates between two non-conformal metrics,
+ * which is necessary for computing continuous mappings between arbitrary surfaces.
+ *
+ */
namespace Penner {
-namespace Optimization {
/// Compute the per halfedge logarithmic shear values for the mesh m with
/// logarithmic lengths lambdas_he
@@ -107,5 +93,4 @@ void compute_shear_basis_coordinates(
VectorX& shear_coords,
VectorX& scale_factors);
-} // namespace Optimization
-} // namespace Penner
+} // namespace Penner
\ No newline at end of file
diff --git a/include/optimization/optimization/core/viewer.h b/include/metric/metric/viewer.h
similarity index 72%
rename from include/optimization/optimization/core/viewer.h
rename to include/metric/metric/viewer.h
index 06bc229..f54b7ce 100644
--- a/include/optimization/optimization/core/viewer.h
+++ b/include/metric/metric/viewer.h
@@ -1,15 +1,37 @@
+// This file is part of penner-optimization, a constrained parametrization library.
+//
+// Copyright (C) 2026 Ryan Capouellez
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
#pragma once
-#include "optimization/core/common.h"
+#include "metric/common.h"
#ifdef ENABLE_VISUALIZATION
#include "polyscope/surface_mesh.h"
#endif
+/**
+ * @brief Assorted viewers.
+ *
+ */
+
namespace Penner {
-namespace Optimization {
+#ifdef ENABLE_VISUALIZATION
+extern glm::vec3 BEIGE;
+extern glm::vec3 BLACK_BROWN;
+extern glm::vec3 TAN;
+extern glm::vec3 MUSTARD;
+extern glm::vec3 FOREST_GREEN;
+extern glm::vec3 TEAL;
+extern glm::vec3 DARK_TEAL;
+#endif
+
// TODO Refactor and add some more convenient viewers
@@ -145,5 +167,35 @@ VectorX compute_corner_angles(
const Eigen::MatrixXi& F
);
-} // namespace Holonomy
+/// View the triangles in the mesh with inverted elements.
+///
+/// @param[in] V: mesh vertices
+/// @param[in] F: mesh faces
+/// @param[in] uv: mesh uv vertices
+/// @param[in] F_uv: mesh uv faces
+void
+view_flipped_triangles(
+ const Eigen::MatrixXd& V,
+ const Eigen::MatrixXi& F,
+ const Eigen::MatrixXd& uv,
+ const Eigen::MatrixXi& F_uv
+);
+
+/// View a layout for a mesh with uv coordinates assigned per halfedge.
+///
+/// @param[in] m: mesh
+/// @param[in] u_vec: per-halfedge u coordinates
+/// @param[in] v_vec: per-halfedge v coordinates
+void
+view_halfedge_mesh_layout(
+ const Mesh& m,
+ const std::vector& u_vec,
+ const std::vector& v_vec
+);
+void view_halfedge_mesh_layout(
+ const std::vector& next,
+ const std::vector& f2h,
+ const std::vector& u_vec,
+ const std::vector& v_vec);
+
} // namespace Penner
\ No newline at end of file
diff --git a/include/optimization/optimization/core/common.h b/include/optimization/optimization/core/common.h
deleted file mode 100644
index 095502e..0000000
--- a/include/optimization/optimization/core/common.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*********************************************************************************
-* This file is part of reference implementation of SIGGRAPH Asia 2023 Paper *
-* `Metric Optimization in Penner Coordinates` *
-* v1.0 *
-* *
-* The MIT License *
-* *
-* Permission is hereby granted, free of charge, to any person obtaining a *
-* copy of this software and associated documentation files (the "Software"), *
-* to deal in the Software without restriction, including without limitation *
-* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
-* and/or sell copies of the Software, and to permit persons to whom the *
-* Software is furnished to do so, subject to the following conditions: *
-* *
-* The above copyright notice and this permission notice shall be included in *
-* all copies or substantial portions of the Software. *
-* *
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
-* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE *
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
-* IN THE SOFTWARE. *
-* *
-* Author(s): *
-* Ryan Capouellez, Denis Zorin, *
-* Courant Institute of Mathematical Sciences, New York University, USA *
-* * *
-*********************************************************************************/
-#pragma once
-
-#include "util/common.h"
-#include "optimization/core/globals.h"
-
-#include