mirror of https://github.com/CGAL/cgal
Merge remote-tracking branch 'cgal/master' into Frechet-dev
This commit is contained in:
commit
859479f681
|
|
@ -0,0 +1,55 @@
|
|||
# Use an official Fedora as a parent image for the build stage
|
||||
FROM fedora:latest AS sources_deps
|
||||
|
||||
# Set environment variables to non-interactive
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Install dependencies
|
||||
RUN dnf update -y && dnf install -y \
|
||||
wget \
|
||||
make \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
patch \
|
||||
cmake \
|
||||
bison \
|
||||
flex \
|
||||
unzip \
|
||||
python3 \
|
||||
&& dnf clean all
|
||||
|
||||
# Copy the patch file to the build context
|
||||
COPY cgal-NO_ADDITIONAL_DETAILS.patch .
|
||||
|
||||
FROM sources_deps AS build
|
||||
|
||||
# Build and install Doxygen from sources
|
||||
ARG DOXYGEN_VERSION=1.9.6
|
||||
ARG MAKEFLAGS=-j$(nproc)
|
||||
RUN if [ -n "$DEBUG"];then set -x && make --version && ls -lZ /tmp && id; fi \
|
||||
&& DOXYGEN_VERSION_UNDERSCORE=$(echo ${DOXYGEN_VERSION} | sed 's/\./_/g') \
|
||||
&& wget https://github.com/doxygen/doxygen/archive/refs/tags/Release_${DOXYGEN_VERSION_UNDERSCORE}.zip \
|
||||
&& unzip Release_${DOXYGEN_VERSION_UNDERSCORE}.zip \
|
||||
&& cd doxygen-Release_${DOXYGEN_VERSION_UNDERSCORE} \
|
||||
&& patch -p1 < ../cgal-NO_ADDITIONAL_DETAILS.patch \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release .. \
|
||||
&& cmake --build . \
|
||||
&& cmake --install . \
|
||||
&& mkdir -p /usr/local/share/doc/doxygen && cp ../LICENSE /usr/local/share/doc/doxygen/LICENSE.TXT \
|
||||
&& cd ../.. \
|
||||
&& rm -rf doxygen-Release_${DOXYGEN_VERSION_UNDERSCORE} Release_${DOXYGEN_VERSION_UNDERSCORE}.zip
|
||||
|
||||
# Use a smaller base image for the final stage
|
||||
FROM fedora:latest
|
||||
|
||||
# Install necessary runtime dependencies
|
||||
RUN set -x \
|
||||
&& dnf update -y && dnf install -y graphviz 'perl(Getopt::Std)' tex-bibtex cmake python3-lxml python3-pyquery \
|
||||
&& dnf clean all
|
||||
|
||||
# Copy Doxygen from the build stage
|
||||
COPY --from=build /usr/local/bin/doxygen /usr/local/bin
|
||||
COPY --from=build /usr/local/share/doc/doxygen/LICENSE.TXT /usr/local/share/doc/doxygen/LICENSE.TXT
|
||||
RUN doxygen --version
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
SHELL := /bin/bash
|
||||
DOXYGEN_VERSIONS := 1.12.0 1.11.0 1.10.0 1.9.8 1.9.7 1.9.6
|
||||
|
||||
.PHONY: all build-% push-% build push
|
||||
|
||||
all: build
|
||||
@echo "Use `$(MAKE) push` to push the images to the registry."
|
||||
|
||||
build-%:
|
||||
@echo "MAKEFLAGS: $(MAKEFLAGS)"
|
||||
@echo "Building Doxygen version $*..."
|
||||
if [ "$$(getenforce || true)" == "Enforcing" ]; then Z=:z; else Z=; fi; \
|
||||
F="$(MAKEFLAGS)"; F=$${F##*fifo:}; F=$${F%% *}; \
|
||||
if [ -p "$$F" ]; then echo "The GNU make FIFO file exists:"; ls -l $$F; VOLUME_ARGS="-v $$F:$$F$$Z"; echo -- $$VOLUME_ARGS; fi; \
|
||||
podman build --build-arg DOXYGEN_VERSION=$* --build-arg "MAKEFLAGS=$(MAKEFLAGS)" $$VOLUME_ARGS -t cgal/doxygen:$* .
|
||||
|
||||
push-%: build-%
|
||||
@echo "Pushing cgal/doxygen:$*..."
|
||||
podman push cgal/doxygen:$*
|
||||
|
||||
build: $(foreach version,$(DOXYGEN_VERSIONS),build-$(version))
|
||||
|
||||
push: $(foreach version,$(DOXYGEN_VERSIONS),push-$(version))
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
diff --git a/src/config.xml b/src/config.xml
|
||||
index 13910958a6..31f1354e44 100644
|
||||
--- a/src/config.xml
|
||||
+++ b/src/config.xml
|
||||
@@ -893,6 +893,18 @@ Go to the <a href="commands.html">next</a> section or return to the
|
||||
\note This will also disable the warnings about undocumented members
|
||||
that are normally produced when \ref cfg_warnings "WARNINGS" is
|
||||
set to \c YES.
|
||||
+]]>
|
||||
+ </docs>
|
||||
+ </option>
|
||||
+ </group>
|
||||
+ <group name='Build' docs='Build related configuration options'>
|
||||
+ <option type='bool' id='NO_ADDITIONAL_DETAILS' defval='0'>
|
||||
+ <docs>
|
||||
+<![CDATA[
|
||||
+ When the \c EXTRACT_ALL tag is set to \c YES and a member or class
|
||||
+ as no documentation, no detailed section will be produced if
|
||||
+ the \c NO_ADDITIONAL_DETAILS tag is set to \c YES.
|
||||
+ This tag has no effect if the \c EXTRACT_ALL tag is set to \c NO.
|
||||
]]>
|
||||
</docs>
|
||||
</option>
|
||||
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
|
||||
index 08d9bf24c5..ab04e994c5 100644
|
||||
--- a/src/memberdef.cpp
|
||||
+++ b/src/memberdef.cpp
|
||||
@@ -2501,6 +2501,7 @@ bool MemberDefImpl::hasDetailedDescription() const
|
||||
if (!m_hasDetailedDescriptionCached)
|
||||
{
|
||||
bool extractAll = Config_getBool(EXTRACT_ALL);
|
||||
+ bool xAllNoDetailedSec = Config_getBool(NO_ADDITIONAL_DETAILS);
|
||||
bool alwaysDetailedSec = Config_getBool(ALWAYS_DETAILED_SEC);
|
||||
bool repeatBrief = Config_getBool(REPEAT_BRIEF);
|
||||
bool briefMemberDesc = Config_getBool(BRIEF_MEMBER_DESC);
|
||||
@@ -2512,7 +2513,7 @@ bool MemberDefImpl::hasDetailedDescription() const
|
||||
// the member has detailed documentation because the user added some comments
|
||||
bool docFilter =
|
||||
// extract all is enabled
|
||||
- extractAll ||
|
||||
+ (extractAll && !xAllNoDetailedSec) ||
|
||||
// has detailed docs
|
||||
!documentation().isEmpty() ||
|
||||
// has inbody docs
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "CGAL Doxygen Dev Container, version 1.12.0, with CGAL patch",
|
||||
"image": "docker.io/cgal/doxygen:1.12.0",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/git:1.3.2": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-vscode.cmake-tools",
|
||||
"bbenoist.Doxygen",
|
||||
"ms-vscode.cpptools"
|
||||
]
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
[distrobox-doxygen-1.12.0]
|
||||
image=cgal/doxygen:1.12.0
|
||||
exported_bins="/usr/local/bin/doxygen /usr/bin/perl /usr/bin/cmake /usr/bin/python3"
|
||||
exported_bins_path=$HOME/.local/bin-doxygen-1.12.0
|
||||
|
||||
[distrobox-doxygen-1.11.0]
|
||||
image=cgal/doxygen:1.11.0
|
||||
exported_bins="/usr/local/bin/doxygen /usr/bin/perl /usr/bin/cmake /usr/bin/python3"
|
||||
exported_bins_path=$HOME/.local/bin-doxygen-1.11.0
|
||||
|
||||
[distrobox-doxygen-1.10.0]
|
||||
image=cgal/doxygen:1.10.0
|
||||
exported_bins="/usr/local/bin/doxygen /usr/bin/perl /usr/bin/cmake /usr/bin/python3"
|
||||
exported_bins_path=$HOME/.local/bin-doxygen-1.10.0
|
||||
|
||||
[distrobox-doxygen-1.9.8]
|
||||
image=cgal/doxygen:1.9.8
|
||||
exported_bins="/usr/local/bin/doxygen /usr/bin/perl /usr/bin/cmake /usr/bin/python3"
|
||||
exported_bins_path=$HOME/.local/bin-doxygen-1.9.8
|
||||
|
||||
[distrobox-doxygen-1.9.7]
|
||||
image=cgal/doxygen:1.9.7
|
||||
exported_bins="/usr/local/bin/doxygen /usr/bin/perl /usr/bin/cmake /usr/bin/python3"
|
||||
exported_bins_path=$HOME/.local/bin-doxygen-1.9.7
|
||||
|
||||
[distrobox-doxygen-1.9.6]
|
||||
image=cgal/doxygen:1.9.6
|
||||
exported_bins="/usr/local/bin/doxygen /usr/bin/perl /usr/bin/cmake /usr/bin/python3"
|
||||
exported_bins_path=$HOME/.local/bin-doxygen-1.9.6
|
||||
|
|
@ -7,9 +7,8 @@ permissions:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
if: github.repository == 'CGAL/cgal' || github.event_name != 'push'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install dependencies
|
||||
|
|
@ -17,7 +16,7 @@ jobs:
|
|||
.github/install.sh
|
||||
set -x
|
||||
sudo apt-get update && sudo apt-get install -y graphviz ssh bibtex2html
|
||||
sudo pip install lxml
|
||||
sudo pip install lxml
|
||||
sudo pip install 'pyquery==1.4.1' # it seems to be the last py2 compatible version
|
||||
wget --no-verbose -O doxygen_exe https://cgal.geometryfactory.com/~cgaltest/doxygen_1_8_13_patched/doxygen
|
||||
sudo mv doxygen_exe /usr/bin/doxygen
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ permissions:
|
|||
|
||||
jobs:
|
||||
cmake-testsuite:
|
||||
|
||||
if: github.repository == 'CGAL/cgal' || github.event_name != 'push'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install dependencies
|
||||
|
|
@ -21,9 +20,8 @@ jobs:
|
|||
ctest -L Installation -j $(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
cmake-testsuite-with-qt:
|
||||
|
||||
if: github.repository == 'CGAL/cgal' || github.event_name != 'push'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: install dependencies
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"default": true,
|
||||
"line-length": false,
|
||||
"no-duplicate-heading": {
|
||||
"siblings_only": true
|
||||
}
|
||||
}
|
||||
|
|
@ -1438,14 +1438,15 @@ vary according to the user choice.} for answering queries:
|
|||
points or choosing points on a grid, are also available; see the
|
||||
Reference Manual for more details.
|
||||
|
||||
The landmark strategy requires that the type of the attached
|
||||
arrangement be an instance of the `Arrangement_2<Traits,Dcel>` class
|
||||
template, where the `Traits` parameter is substituted by a
|
||||
geometry-traits class that models the `ArrangementLandmarkTraits_2`
|
||||
concept, which refines the basic `ArrangementBasicTraits_2` concept;
|
||||
see Section \ref aos_sssec-tr_landmarks_concept for details. Most
|
||||
traits classes included in the \ref PkgArrangementOnSurface2 package
|
||||
are models of this refined concept.
|
||||
The arrangement attached to the landmark strategy must be either (i)
|
||||
an instance of the `Arrangement_2<Geom,Dcel>` class template, where
|
||||
the `Traits` parameter is substituted by a geometry-traits class
|
||||
that models the `ArrangementLandmarkTraits_2` concept, or (ii) an
|
||||
instance of the `Arrangement_on_surface_2<GeomTraits,TopolTraits>`
|
||||
class template, where the `GeomTraits` is similarly substituted;
|
||||
see Section \ref aos_sssec-tr_landmarks_concept for details about
|
||||
this concept. Most traits classes included in the \ref
|
||||
PkgArrangementOnSurface2 package are models of this refined concept.
|
||||
|
||||
<LI>`Arr_trapezoid_ric_point_location<Arrangement>` implements an
|
||||
improved variant of Mulmuley's point-location algorithm
|
||||
|
|
@ -1492,7 +1493,7 @@ educational purposes, and thus we do not elaborate on this strategy.
|
|||
The data structure needed by the landmark and the trapezoidal map RIC
|
||||
strategies can be constructed in \cgalBigO{N \log N} time, where \f$N\f$
|
||||
is the overall number of edges in the arrangement, but the constant
|
||||
hidden in the \cgalBigO{ } notation for the trapezoidal map RIC strategy
|
||||
hidden in the \cgalBigO{~} notation for the trapezoidal map RIC strategy
|
||||
is much larger. Thus, construction needed by the landmark algorithm is
|
||||
in practice significantly faster than the construction needed by the
|
||||
trapezoidal map RIC strategy. In addition, although both resulting
|
||||
|
|
@ -2039,8 +2040,8 @@ so it must be construct from scratch.
|
|||
|
||||
In the first case, we sweep over the input curves, compute their
|
||||
intersection points, and construct the \dcel that represents their
|
||||
arrangement. This process is performed in \cgalBigO{left((n + k)\log
|
||||
n\right} time, where \f$k\f$ is the total number of intersection
|
||||
arrangement. This process is performed in \cgalBigO{(n + k)\log
|
||||
n} time, where \f$k\f$ is the total number of intersection
|
||||
points. The running time is asymptotically better than the time needed
|
||||
for incremental insertion if the arrangement is relatively sparse
|
||||
(when \f$k\f$ is \cgalBigO{\frac{n^2}{\log n}}), but it is recommended
|
||||
|
|
|
|||
|
|
@ -440,13 +440,14 @@ public:
|
|||
Bbox_2 operator()(const X_monotone_curve_2& xcv) const { return bbox(xcv); }
|
||||
};
|
||||
|
||||
/*! \name Auxiliary Functor definitions, used gor, e.g., the landmarks
|
||||
/*! \name Auxiliary Functor definitions, used gor, e.g., the landmarks \
|
||||
* point-location strategy and the drawing function.
|
||||
*/
|
||||
//@{
|
||||
typedef double Approximate_number_type;
|
||||
typedef CGAL::Cartesian<Approximate_number_type> Approximate_kernel;
|
||||
typedef Approximate_kernel::Point_2 Approximate_point_2;
|
||||
//@}
|
||||
|
||||
/*! \class Approximate_2
|
||||
* A functor that approximates a point and an \f$x\f$-monotone curve.
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ public:
|
|||
X_monotone_curve_2(const X_monotone_curve_2& xcv,
|
||||
const Point_2& src, const Point_2& tgt) const;
|
||||
|
||||
//! @}
|
||||
} /* end Arr_segment_traits_2::Trim_2 */
|
||||
|
||||
}; /* end Arr_segment_traits_2 */
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public:
|
|||
|
||||
/// \name Functor Types
|
||||
/// @{
|
||||
/// @}
|
||||
|
||||
/// \name Accessing Functor Objects
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -36,13 +36,6 @@ using Trap_pl = CGAL::Arr_trapezoid_ric_point_location<Gm>;
|
|||
using Geom_traits = Gm::Geometry_traits_2;
|
||||
using Point_2 = Geom_traits::Point_2;
|
||||
|
||||
using Point_location_result = CGAL::Arr_point_location_result<Gm>;
|
||||
using Query_result = std::pair<Point_2, Point_location_result::Type>;
|
||||
|
||||
using Vertex_const_handle = Gm::Vertex_const_handle;
|
||||
using Halfedge_const_handle = Gm::Halfedge_const_handle;
|
||||
using Face_const_handle = Gm::Face_const_handle;
|
||||
|
||||
int main() {
|
||||
Gm_polyhedron p;
|
||||
p.make_tetrahedron(Point_3(1.0, 0.0, 0.0), Point_3(0.0, 1.0, 0.0),
|
||||
|
|
@ -50,7 +43,7 @@ int main() {
|
|||
Gm gm;
|
||||
|
||||
Naive_pl naive_pl(gm);
|
||||
// Landmarks_pl landmarks_pl(gm);
|
||||
Landmarks_pl landmarks_pl(gm);
|
||||
Walk_pl walk_pl(gm);
|
||||
// Trap_pl trap_pl(gm);
|
||||
|
||||
|
|
@ -70,30 +63,17 @@ int main() {
|
|||
locate_point(naive_pl, points[1]);
|
||||
locate_point(naive_pl, points[2]);
|
||||
|
||||
// locate_point(walk_pl, points[0]);
|
||||
// locate_point(walk_pl, points[1]);
|
||||
// locate_point(walk_pl, points[2]);
|
||||
|
||||
locate_point(landmarks_pl, points[0]);
|
||||
locate_point(landmarks_pl, points[1]);
|
||||
locate_point(landmarks_pl, points[2]);
|
||||
|
||||
// locate_point(trap_pl, points[0]);
|
||||
|
||||
////////
|
||||
std::list<Query_result> results;
|
||||
// The following cause an assertion failure.
|
||||
// CGAL::locate(gm, &points[0], &points[3], std::back_inserter(results));
|
||||
|
||||
// Print the results.
|
||||
for (auto it = results.begin(); it != results.end(); ++it) {
|
||||
std::cout << "The point (" << it->first << ") is located ";
|
||||
if (const Face_const_handle* f =
|
||||
std::get_if<Face_const_handle>(&(it->second))) // inside a face
|
||||
std::cout << "inside "
|
||||
<< (((*f)->is_unbounded()) ? "the unbounded" : "a bounded")
|
||||
<< " face.\n";
|
||||
else if (const Halfedge_const_handle* e =
|
||||
std::get_if<Halfedge_const_handle>(&(it->second))) // on an edge
|
||||
std::cout << "on an edge: " << (*e)->curve() << std::endl;
|
||||
else if (const Vertex_const_handle* v =
|
||||
std::get_if<Vertex_const_handle>(&(it->second))) // on a vertex
|
||||
std::cout << "on "
|
||||
<< (((*v)->is_isolated()) ? "an isolated" : "a")
|
||||
<< " vertex: " << (*v)->point() << std::endl;
|
||||
}
|
||||
// locate_point(trap_pl, points[1]);
|
||||
// locate_point(trap_pl, points[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1515,7 +1515,7 @@ public:
|
|||
|
||||
//@}
|
||||
|
||||
/*! \name Auxiliary Functor definitions, used gor, e.g., the landmarks
|
||||
/*! \name Auxiliary Functor definitions, used gor, e.g., the landmarks \
|
||||
* point-location strategy and the drawing function.
|
||||
*/
|
||||
//@{
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Idit Haran <haranidi@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Author(s) : Idit Haran <haranidi@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_ARR_LANDMARKS_POINT_LOCATION_H
|
||||
#define CGAL_ARR_LANDMARKS_POINT_LOCATION_H
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
#include <CGAL/Arr_point_location_result.h>
|
||||
#include <CGAL/Arrangement_2/Arr_traits_adaptor_2.h>
|
||||
#include <CGAL/Arr_point_location/Arr_lm_vertices_generator.h>
|
||||
#include <CGAL/Arr_tags.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
|
|
@ -42,44 +43,54 @@ namespace CGAL {
|
|||
* Generator is a class that generates the set of landmarks.
|
||||
*/
|
||||
|
||||
template <class Arrangement_,
|
||||
class Generator_ = Arr_landmarks_vertices_generator<Arrangement_> >
|
||||
class Arr_landmarks_point_location
|
||||
{
|
||||
template <typename Arrangement_,
|
||||
typename Generator_ = Arr_landmarks_vertices_generator<Arrangement_>>
|
||||
class Arr_landmarks_point_location {
|
||||
public:
|
||||
typedef Arrangement_ Arrangement_2;
|
||||
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
|
||||
typedef Generator_ Generator;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Generator = Generator_;
|
||||
using Geometry_traits_2 = typename Arrangement_2::Geometry_traits_2;
|
||||
|
||||
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||||
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||||
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||||
using Vertex_const_handle = typename Arrangement_2::Vertex_const_handle;
|
||||
using Halfedge_const_handle = typename Arrangement_2::Halfedge_const_handle;
|
||||
using Face_const_handle = typename Arrangement_2::Face_const_handle;
|
||||
|
||||
typedef typename Arrangement_2::Vertex_const_iterator Vertex_const_iterator;
|
||||
typedef typename Arrangement_2::Halfedge_const_iterator
|
||||
Halfedge_const_iterator;
|
||||
typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator
|
||||
Halfedge_around_vertex_const_circulator;
|
||||
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
|
||||
Ccb_halfedge_const_circulator;
|
||||
typedef typename Arrangement_2::Outer_ccb_const_iterator
|
||||
Outer_ccb_const_iterator;
|
||||
typedef typename Arrangement_2::Inner_ccb_const_iterator
|
||||
Inner_ccb_const_iterator;
|
||||
typedef typename Arrangement_2::Isolated_vertex_const_iterator
|
||||
Isolated_vertex_const_iterator;
|
||||
using Vertex_const_iterator = typename Arrangement_2::Vertex_const_iterator;
|
||||
using Halfedge_const_iterator =
|
||||
typename Arrangement_2::Halfedge_const_iterator;
|
||||
|
||||
typedef typename Arrangement_2::Point_2 Point_2;
|
||||
typedef typename Arrangement_2::X_monotone_curve_2 X_monotone_curve_2;
|
||||
using Halfedge_around_vertex_const_circulator =
|
||||
typename Arrangement_2::Halfedge_around_vertex_const_circulator;
|
||||
using Ccb_halfedge_const_circulator =
|
||||
typename Arrangement_2::Ccb_halfedge_const_circulator;
|
||||
using Outer_ccb_const_iterator =
|
||||
typename Arrangement_2::Outer_ccb_const_iterator;
|
||||
using Inner_ccb_const_iterator =
|
||||
typename Arrangement_2::Inner_ccb_const_iterator;
|
||||
using Isolated_vertex_const_iterator =
|
||||
typename Arrangement_2::Isolated_vertex_const_iterator;
|
||||
|
||||
typedef Arr_point_location_result<Arrangement_2> Result;
|
||||
typedef typename Result::Type Result_type;
|
||||
using Point_2 = typename Arrangement_2::Point_2;
|
||||
using X_monotone_curve_2 = typename Arrangement_2::X_monotone_curve_2;
|
||||
|
||||
using Result = Arr_point_location_result<Arrangement_2>;
|
||||
using Result_type = typename Result::Type;
|
||||
|
||||
// Support cpp11::result_of
|
||||
typedef Result_type result_type;
|
||||
using result_type = Result_type;
|
||||
|
||||
private:
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Left_side_category =
|
||||
typename internal::Arr_complete_left_side_category<Gt2>::Category;
|
||||
using Right_side_category =
|
||||
typename internal::Arr_complete_right_side_category<Gt2>::Category;
|
||||
using Left_or_right_sides_category =
|
||||
typename Arr_two_sides_category<Left_side_category,
|
||||
Right_side_category>::result;
|
||||
|
||||
protected:
|
||||
typedef Arr_traits_basic_adaptor_2<Geometry_traits_2> Traits_adaptor_2;
|
||||
using Traits_adaptor_2 = Arr_traits_basic_adaptor_2<Geometry_traits_2>;
|
||||
|
||||
/*! \struct Less_halfedge_handle
|
||||
* Used to sort handles.
|
||||
|
|
@ -92,10 +103,10 @@ protected:
|
|||
typedef std::set<Halfedge_const_handle, Less_halfedge_handle> Halfedge_set;
|
||||
|
||||
// Data members:
|
||||
const Arrangement_2* p_arr; // The associated arrangement.
|
||||
const Arrangement_2* p_arr; // The associated arrangement.
|
||||
const Traits_adaptor_2* m_traits; // Its associated traits object.
|
||||
Generator* lm_gen; // The associated landmark generator.
|
||||
bool own_gen; // Indicates whether the generator
|
||||
Generator* lm_gen; // The associated landmark generator.
|
||||
bool own_gen; // Indicates whether the generator
|
||||
// has been locally allocated.
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -103,7 +114,7 @@ protected:
|
|||
inline Result_type default_result() const { return Result::default_result(); }
|
||||
|
||||
public:
|
||||
/*! Default constructor. */
|
||||
/*! constructs default. */
|
||||
Arr_landmarks_point_location() :
|
||||
p_arr(nullptr),
|
||||
m_traits(nullptr),
|
||||
|
|
@ -111,34 +122,32 @@ public:
|
|||
own_gen(false)
|
||||
{}
|
||||
|
||||
/*! Constructor given an arrangement only. */
|
||||
/*! constructs given an arrangement only. */
|
||||
Arr_landmarks_point_location(const Arrangement_2& arr) :
|
||||
p_arr(&arr),
|
||||
m_traits(static_cast<const Traits_adaptor_2*>(p_arr->geometry_traits())),
|
||||
lm_gen(new Generator(arr)), // allocate the landmarks generator.
|
||||
own_gen(true)
|
||||
{ }
|
||||
{}
|
||||
|
||||
/*! Constructor given an arrangement, and landmarks generator. */
|
||||
/*! constructs given an arrangement, and landmarks generator. */
|
||||
Arr_landmarks_point_location(const Arrangement_2& arr, Generator* gen) :
|
||||
p_arr(&arr),
|
||||
m_traits(static_cast<const Traits_adaptor_2*>(p_arr->geometry_traits())),
|
||||
lm_gen(gen),
|
||||
own_gen(false)
|
||||
{ }
|
||||
{}
|
||||
|
||||
/*! Destructor. */
|
||||
~Arr_landmarks_point_location()
|
||||
{
|
||||
/*! destructs. */
|
||||
~Arr_landmarks_point_location() {
|
||||
if (own_gen) {
|
||||
delete lm_gen;
|
||||
lm_gen = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*! Attach an arrangement object (and a generator, if supplied). */
|
||||
void attach(const Arrangement_2& arr, Generator* gen = nullptr)
|
||||
{
|
||||
/*! attaches an arrangement object (and a generator, if supplied). */
|
||||
void attach(const Arrangement_2& arr, Generator* gen = nullptr) {
|
||||
// Keep a pointer to the associated arrangement.
|
||||
p_arr = &arr;
|
||||
m_traits = static_cast<const Traits_adaptor_2*>(p_arr->geometry_traits());
|
||||
|
|
@ -163,9 +172,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/*! Detach the instance from the arrangement object. */
|
||||
void detach()
|
||||
{
|
||||
/*! detaches the instance from the arrangement object. */
|
||||
void detach() {
|
||||
p_arr = nullptr;
|
||||
m_traits = nullptr;
|
||||
|
||||
|
|
@ -174,8 +182,7 @@ public:
|
|||
lm_gen->detach();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Locate the arrangement feature containing the given point.
|
||||
/*! locates the arrangement feature containing the given point.
|
||||
* \param p The query point.
|
||||
* \return An object representing the arrangement feature containing the
|
||||
* query point. This object is either a Face_const_handle or a
|
||||
|
|
@ -184,7 +191,7 @@ public:
|
|||
result_type locate(const Point_2& p) const;
|
||||
|
||||
protected:
|
||||
/*! Walk from the given vertex to the query point.
|
||||
/*! walks from the given vertex to the query point.
|
||||
* \param vh The given vertex handle.
|
||||
* \param p The query point.
|
||||
* \param crossed_edges In/Out: The set of edges crossed so far.
|
||||
|
|
@ -196,7 +203,7 @@ protected:
|
|||
const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const;
|
||||
|
||||
/*! Locate an edge around a given vertex that is the predecessor of the
|
||||
/*! locates an edge around a given vertex that is the predecessor of the
|
||||
* curve connecting the vertex to the query point in a clockwise order.
|
||||
* \param vh The vertex.
|
||||
* \param p The query point.
|
||||
|
|
@ -207,7 +214,7 @@ protected:
|
|||
const Point_2& p,
|
||||
bool& new_vertex) const;
|
||||
|
||||
/*! Walk from a point on a given halfedge to the query point.
|
||||
/*! walks from a point on a given halfedge to the query point.
|
||||
* \param eh The given halfedge handle.
|
||||
* \param np The point that the walk starts from.
|
||||
* \param p The query point.
|
||||
|
|
@ -220,7 +227,7 @@ protected:
|
|||
const Point_2& np,
|
||||
const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const;
|
||||
/*! In case the arrangement's curve contained in the segment
|
||||
/*! handles the arrangement curve contained in the segment
|
||||
* from the nearest landmark to the query point
|
||||
* \param he The given halfedge handle.
|
||||
* \param p_is_left Is the query point the left endpoint of seg.
|
||||
|
|
@ -236,7 +243,7 @@ protected:
|
|||
const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const;
|
||||
|
||||
/*! Walk from a point in a face to the query point.
|
||||
/*! walks from a point in a face to the query point.
|
||||
* \param fh A halfedge handle that points to the face.
|
||||
* \param np The point that the walk starts from.
|
||||
* \param p The query point.
|
||||
|
|
@ -250,7 +257,7 @@ protected:
|
|||
const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const;
|
||||
|
||||
/*! Find a halfedge on the given CCB that intersects the given x-monotone
|
||||
/*! finds a halfedge on the given CCB that intersects the given x-monotone
|
||||
* curve, connecting the current landmark to the query point.
|
||||
* \param circ The CCB circulator.
|
||||
* \param seg The segment connecting the landmark and the query point.
|
||||
|
|
@ -275,7 +282,7 @@ protected:
|
|||
bool& cv_is_contained_in_seg,
|
||||
Vertex_const_handle& new_vertex) const;
|
||||
|
||||
/*! Return the halfedge that contains the query point.
|
||||
/*! returns the halfedge that contains the query point.
|
||||
* \param he The halfedge handle.
|
||||
* \param crossed_edges In/Out: The set of edges crossed so far.
|
||||
* \param p The query point.
|
||||
|
|
@ -287,7 +294,7 @@ protected:
|
|||
const Point_2& p,
|
||||
bool& is_target) const;
|
||||
|
||||
/*! Check whether the given curve intersects a simple segment, which connects
|
||||
/*! checks whether the given curve intersects a simple segment, which connects
|
||||
* the current landmark to the query point, an odd number of times.
|
||||
* \param cv The curve.
|
||||
* \param seg The segment connecting the landmark and the query point.
|
||||
|
|
@ -303,9 +310,62 @@ protected:
|
|||
bool& p_on_curve,
|
||||
bool& cv_and_seg_overlap,
|
||||
bool& cv_is_contained_in_seg) const;
|
||||
|
||||
//!
|
||||
template <typename T>
|
||||
std::pair<X_monotone_curve_2, Comparison_result>
|
||||
construct_segment(const Point_2& p, const Point_2& q, T const& traits,
|
||||
...) const {
|
||||
X_monotone_curve_2 seg = traits.construct_x_monotone_curve_2_object()(p, q);
|
||||
Comparison_result res = traits.compare_xy_2_object()(p, q);
|
||||
return std::make_pair(seg, res);
|
||||
}
|
||||
|
||||
//*!
|
||||
template <typename T, typename = typename T::Compare_endpoints_xy_2>
|
||||
std::pair<X_monotone_curve_2, Comparison_result>
|
||||
construct_segment(const Point_2& p, const Point_2& q, T const& traits,
|
||||
int) const {
|
||||
X_monotone_curve_2 seg = traits.construct_x_monotone_curve_2_object()(p, q);
|
||||
Comparison_result res = traits.compare_endpoints_xy_2_object()(seg);
|
||||
return std::make_pair(seg, res);
|
||||
}
|
||||
|
||||
/*! Determines whether the $x$-coordinates of two points are equal.
|
||||
*/
|
||||
bool equal_x_2(const Point_2& p, const Point_2& q,
|
||||
Arr_all_sides_oblivious_tag) const
|
||||
{ return (m_traits->compare_x_2_object()(p, q) == EQUAL); }
|
||||
|
||||
/*! Determines whether the $x$-coordinates of two points are equal.
|
||||
*/
|
||||
bool equal_x_2(const Point_2& p, const Point_2& q,
|
||||
Arr_has_identified_side_tag) const {
|
||||
auto is_on_y_identification = m_traits->is_on_y_identification_2_object();
|
||||
if (is_on_y_identification(p)) {
|
||||
return is_on_y_identification(q);
|
||||
}
|
||||
if (is_on_y_identification(q)) return false;
|
||||
return (m_traits->compare_x_2_object()(p, q) == EQUAL);
|
||||
}
|
||||
|
||||
/*! Determines whether the $x$-coordinates of two points are equal.
|
||||
*/
|
||||
bool equal_x_2(const Point_2& p, const Point_2& q,
|
||||
Arr_boundary_cond_tag) const {
|
||||
auto param_space_in_x = m_traits->parameter_space_in_x_2_object();
|
||||
switch (param_space_in_x(p)) {
|
||||
case ARR_LEFT_BOUNDARY: return (param_space_in_x(q) == ARR_LEFT_BOUNDARY);
|
||||
case ARR_RIGHT_BOUNDARY: return (param_space_in_x(q) == ARR_LEFT_BOUNDARY);
|
||||
case ARR_INTERIOR: return (m_traits->compare_x_2_object()(p, q) == EQUAL);
|
||||
default: CGAL_error();
|
||||
}
|
||||
CGAL_error();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
} // namespace CGAL
|
||||
|
||||
// The member-function definitions can be found under:
|
||||
#include <CGAL/Arr_point_location/Arr_landmarks_pl_impl.h>
|
||||
|
|
|
|||
|
|
@ -7,16 +7,15 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Idit Haran <haranidi@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
// Author(s) : Idit Haran <haranidi@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efif@post.tau.ac.il>
|
||||
|
||||
#ifndef CGAL_ARR_LANDMARKS_PL_IMPL_H
|
||||
#define CGAL_ARR_LANDMARKS_PL_IMPL_H
|
||||
|
||||
#include <CGAL/license/Arrangement_on_surface_2.h>
|
||||
|
||||
|
||||
/*! \file
|
||||
* Member-function definitions for the
|
||||
* Arr_landmarks_point_location<Arrangement, Generator> class.
|
||||
|
|
@ -24,60 +23,53 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Locate the arrangement feature containing the given point.
|
||||
//
|
||||
/*! locates the arrangement feature containing the given point.
|
||||
*/
|
||||
template <typename Arr, typename Gen>
|
||||
typename Arr_landmarks_point_location<Arr, Gen>::result_type
|
||||
Arr_landmarks_point_location<Arr, Gen>::locate(const Point_2& p) const
|
||||
{
|
||||
Arr_landmarks_point_location<Arr, Gen>::locate(const Point_2& p) const {
|
||||
// If the arrangement is empty, return its initial (empty and
|
||||
// non-fictitious) face.
|
||||
if (p_arr->number_of_vertices() == 0) {
|
||||
CGAL_assertion(p_arr->number_of_faces() == 1);
|
||||
Face_const_handle fh = p_arr->faces_begin();
|
||||
Face_const_handle fh = p_arr->faces_begin();
|
||||
return make_result(fh);
|
||||
}
|
||||
|
||||
// Use the generator and to find the closest landmark to the query point.
|
||||
result_type lm_location_obj;
|
||||
result_type lm_location_obj;
|
||||
const Point_2& landmark_point = lm_gen->closest_landmark(p, lm_location_obj);
|
||||
|
||||
// If the query point and the landmark point are equal, return the landmark.
|
||||
if (m_traits->equal_2_object()(landmark_point, p))
|
||||
return lm_location_obj;
|
||||
if (m_traits->equal_2_object()(landmark_point, p)) return lm_location_obj;
|
||||
|
||||
// Walk from the nearest_vertex to the point p, using walk algorithm,
|
||||
// and find the location of the query point p. Note that the set of edges
|
||||
// we have crossed so far is initially empty.
|
||||
Halfedge_set crossed_edges;
|
||||
result_type out_obj;
|
||||
Halfedge_set crossed_edges;
|
||||
result_type out_obj;
|
||||
|
||||
// Locate the arrangement feature that contains the landmark.
|
||||
const Vertex_const_handle* vh;
|
||||
const Halfedge_const_handle* hh;
|
||||
const Face_const_handle* fh;
|
||||
if ( ( vh = Result().template assign<Vertex_const_handle>(&lm_location_obj) ) )
|
||||
out_obj = _walk_from_vertex(*vh, p, crossed_edges);
|
||||
else if ( ( hh = Result().template assign<Halfedge_const_handle>(&lm_location_obj) ) )
|
||||
out_obj = _walk_from_edge(*hh, landmark_point, p, crossed_edges);
|
||||
else if ( ( fh = Result().template assign<Face_const_handle>(&lm_location_obj) ) )
|
||||
out_obj = _walk_from_face(*fh, landmark_point, p, crossed_edges);
|
||||
if (const auto* v = std::get_if<Vertex_const_handle>(&lm_location_obj))
|
||||
out_obj = _walk_from_vertex(*v, p, crossed_edges);
|
||||
else if (const auto* e = std::get_if<Halfedge_const_handle>(&lm_location_obj))
|
||||
out_obj = _walk_from_edge(*e, landmark_point, p, crossed_edges);
|
||||
else if (const auto* f = std::get_if<Face_const_handle>(&lm_location_obj))
|
||||
out_obj = _walk_from_face(*f, landmark_point, p, crossed_edges);
|
||||
else CGAL_error_msg("lm_location_obj of an unknown type.");
|
||||
|
||||
if ( ( fh = Result().template assign<Face_const_handle>(&out_obj) ) ) {
|
||||
if (const auto* fp = std::get_if<Face_const_handle>(&out_obj)) {
|
||||
const auto& f = *fp;
|
||||
// If we reached here, we did not locate the query point in any of the
|
||||
// holes inside the current face, so we conclude it is contained in this
|
||||
// face.
|
||||
// However, we first have to check whether the query point coincides with
|
||||
// any of the isolated vertices contained inside this face.
|
||||
Isolated_vertex_const_iterator iso_verts_it;
|
||||
typename Traits_adaptor_2::Equal_2 equal = m_traits->equal_2_object();
|
||||
|
||||
for (iso_verts_it = (*fh)->isolated_vertices_begin();
|
||||
iso_verts_it != (*fh)->isolated_vertices_end(); ++iso_verts_it)
|
||||
{
|
||||
// face. However, we first have to check whether the query point coincides
|
||||
// with any of the isolated vertices contained inside this face.
|
||||
auto equal = m_traits->equal_2_object();
|
||||
// Do not use 'auto' to define the iterator, as MSVC2017 complains.
|
||||
for (Isolated_vertex_const_iterator iso_verts_it = f->isolated_vertices_begin();
|
||||
iso_verts_it != f->isolated_vertices_end(); ++iso_verts_it) {
|
||||
if (equal(p, iso_verts_it->point())) {
|
||||
Vertex_const_handle ivh = iso_verts_it;
|
||||
Vertex_const_handle ivh = iso_verts_it;
|
||||
return make_result(ivh);
|
||||
}
|
||||
}
|
||||
|
|
@ -86,28 +78,24 @@ Arr_landmarks_point_location<Arr, Gen>::locate(const Point_2& p) const
|
|||
return out_obj;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Walk from a given vertex to the query point.
|
||||
//
|
||||
/*! walks from a given vertex to the query point.
|
||||
*/
|
||||
template <typename Arr, typename Gen>
|
||||
typename Arr_landmarks_point_location<Arr, Gen>::result_type
|
||||
Arr_landmarks_point_location<Arr, Gen>::
|
||||
_walk_from_vertex(Vertex_const_handle nearest_vertex,
|
||||
const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const
|
||||
{
|
||||
_walk_from_vertex(Vertex_const_handle nearest_vertex, const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const {
|
||||
Vertex_const_handle vh = nearest_vertex;
|
||||
CGAL_assertion_msg(! vh->is_at_open_boundary(),
|
||||
"_walk_from_vertex() from a vertex at infinity.");
|
||||
|
||||
// Check if the query point p coincides with the vertex.
|
||||
if (m_traits->equal_2_object()(vh->point(), p))
|
||||
return make_result(vh);
|
||||
if (m_traits->equal_2_object()(vh->point(), p)) return make_result(vh);
|
||||
|
||||
// In case of an isolated vertex, walk to from the face that contains
|
||||
// it toward the query point.
|
||||
if (vh->is_isolated()) {
|
||||
Face_const_handle fh = vh->face();
|
||||
Face_const_handle fh = vh->face();
|
||||
return (_walk_from_face(fh, vh->point(), p, crossed_edges));
|
||||
}
|
||||
|
||||
|
|
@ -116,16 +104,15 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex,
|
|||
Halfedge_around_vertex_const_circulator first = vh->incident_halfedges();
|
||||
// Create an x-monotone curve connecting the point associated with the
|
||||
// vertex vp and the query point p.
|
||||
const Point_2& vp = vh->point();
|
||||
X_monotone_curve_2 seg =
|
||||
m_traits->construct_x_monotone_curve_2_object()(vp, p);
|
||||
const bool seg_dir_right =
|
||||
(m_traits->compare_xy_2_object()(vp, p) == SMALLER);
|
||||
const Point_2& vp = vh->point();
|
||||
X_monotone_curve_2 seg;
|
||||
Comparison_result res;
|
||||
std::tie(seg, res) = construct_segment(vp, p, *m_traits, 0);
|
||||
bool seg_dir_right = (res == SMALLER);
|
||||
Halfedge_around_vertex_const_circulator curr_iter = first;
|
||||
Halfedge_around_vertex_const_circulator next_iter = curr_iter;
|
||||
++next_iter;
|
||||
typename Traits_adaptor_2::Is_between_cw_2 is_between_cw =
|
||||
m_traits->is_between_cw_2_object();
|
||||
auto is_between_cw = m_traits->is_between_cw_2_object();
|
||||
// Traverse the halfedges around vp until we find the pair of adjacent
|
||||
// halfedges such as seg is located clockwise in between them.
|
||||
do {
|
||||
|
|
@ -134,12 +121,11 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex,
|
|||
(curr_iter->direction() == ARR_RIGHT_TO_LEFT),
|
||||
next_iter->curve(),
|
||||
(next_iter->direction() == ARR_RIGHT_TO_LEFT),
|
||||
vp, eq_curr_iter, eq_next_iter))
|
||||
{
|
||||
vp, eq_curr_iter, eq_next_iter)) {
|
||||
// the assumption is that each edge is crossed at most twice
|
||||
CGAL_assertion_msg(crossed_edges.count (curr_iter) < 2,
|
||||
CGAL_assertion_msg(crossed_edges.count(curr_iter) < 2,
|
||||
"crossed_edges should contain each halfedge at most twice.");
|
||||
CGAL_assertion_msg(crossed_edges.count (next_iter) < 2,
|
||||
CGAL_assertion_msg(crossed_edges.count(next_iter) < 2,
|
||||
"crossed_edges should contain each halfedge at most twice.");
|
||||
crossed_edges.insert(curr_iter);
|
||||
crossed_edges.insert(curr_iter->twin());
|
||||
|
|
@ -158,8 +144,7 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex,
|
|||
result_type obj = _find_face_around_vertex(vh, p, new_vertex);
|
||||
if (new_vertex) {
|
||||
// We found a vertex closer to p; Continue using this vertex.
|
||||
const Vertex_const_handle* p_vh =
|
||||
Result().template assign<Vertex_const_handle>(&obj);
|
||||
const auto* p_vh = std::get_if<Vertex_const_handle>(&obj);
|
||||
CGAL_assertion(p_vh != nullptr);
|
||||
vh = *p_vh;
|
||||
continue;
|
||||
|
|
@ -167,15 +152,13 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex,
|
|||
|
||||
// If p is located on an edge or on a vertex, return the object
|
||||
// that wraps this arrangement feature.
|
||||
if (Result().template assign<Halfedge_const_handle>(&obj) ||
|
||||
Result().template assign<Vertex_const_handle>(&obj))
|
||||
if (std::get_if<Halfedge_const_handle>(&obj) ||
|
||||
std::get_if<Vertex_const_handle>(&obj))
|
||||
return obj;
|
||||
|
||||
const Face_const_handle* p_fh =
|
||||
Result().template assign<Face_const_handle>(&obj);
|
||||
if (p_fh)
|
||||
// Walk to p from the face we have located:
|
||||
return _walk_from_face(*p_fh, vh->point(), p, crossed_edges);
|
||||
const auto* p_fh = std::get_if<Face_const_handle>(&obj);
|
||||
// Walk to p from the face we have located:
|
||||
if (p_fh) return _walk_from_face(*p_fh, vh->point(), p, crossed_edges);
|
||||
|
||||
CGAL_error_msg("_find_face_around_vertex() returned an unknown object.");
|
||||
}
|
||||
|
|
@ -185,31 +168,27 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex,
|
|||
return default_result();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Locate an edge around a given vertex that is the predecessor of the curve
|
||||
// connecting the vertex to the query point in a clockwise order.
|
||||
//
|
||||
/*! locates an edge around a given vertex that is the predecessor of the curve
|
||||
* connecting the vertex to the query point in a clockwise order.
|
||||
*/
|
||||
template <typename Arr, typename Gen>
|
||||
typename Arr_landmarks_point_location<Arr, Gen>::result_type
|
||||
Arr_landmarks_point_location<Arr, Gen>::
|
||||
_find_face_around_vertex(Vertex_const_handle vh,
|
||||
const Point_2& p,
|
||||
bool& new_vertex) const
|
||||
{
|
||||
_find_face_around_vertex(Vertex_const_handle vh, const Point_2& p,
|
||||
bool& new_vertex) const {
|
||||
new_vertex = false;
|
||||
|
||||
// Create an x-monotone curve connecting the point associated with the
|
||||
// vertex vp and the query point p.
|
||||
const Point_2& vp = vh->point();
|
||||
X_monotone_curve_2 seg =
|
||||
m_traits->construct_x_monotone_curve_2_object()(vp, p);
|
||||
const bool seg_dir_right =
|
||||
(m_traits->compare_xy_2_object()(vp, p) == SMALLER);
|
||||
|
||||
const Point_2& vp = vh->point();
|
||||
X_monotone_curve_2 seg;
|
||||
Comparison_result res;
|
||||
std::tie(seg, res) = construct_segment(vp, p, *m_traits, 0);
|
||||
bool seg_dir_right = (res == SMALLER);
|
||||
// Get the first incident halfedge around v and the next halfedge.
|
||||
Halfedge_around_vertex_const_circulator first = vh->incident_halfedges();
|
||||
Halfedge_around_vertex_const_circulator curr, next;
|
||||
bool equal_curr = false;
|
||||
Halfedge_around_vertex_const_circulator first = vh->incident_halfedges();
|
||||
Halfedge_around_vertex_const_circulator curr, next;
|
||||
bool equal_curr = false;
|
||||
|
||||
next = curr = first;
|
||||
++next;
|
||||
|
|
@ -241,16 +220,14 @@ _find_face_around_vertex(Vertex_const_handle vh,
|
|||
else {
|
||||
// Traverse the halfedges around v until we find the pair of adjacent
|
||||
// halfedges such as seg is located clockwise in between them.
|
||||
typename Traits_adaptor_2::Is_between_cw_2 is_between_cw =
|
||||
m_traits->is_between_cw_2_object();
|
||||
bool eq_curr, eq_next;
|
||||
auto is_between_cw = m_traits->is_between_cw_2_object();
|
||||
bool eq_curr, eq_next;
|
||||
|
||||
while (! is_between_cw(seg, seg_dir_right, curr->curve(),
|
||||
(curr->direction() == ARR_RIGHT_TO_LEFT),
|
||||
next->curve(),
|
||||
(next->direction() == ARR_RIGHT_TO_LEFT),
|
||||
vp, eq_curr, eq_next))
|
||||
{
|
||||
vp, eq_curr, eq_next)) {
|
||||
// Break the loop if seg equals one of the halfedges next to v.
|
||||
if (eq_curr) {
|
||||
equal_curr = true;
|
||||
|
|
@ -291,10 +268,9 @@ _find_face_around_vertex(Vertex_const_handle vh,
|
|||
|
||||
// Check whether p lies on the curve associated with the edge.
|
||||
if (m_traits->is_in_x_range_2_object()(curr->curve(), p) &&
|
||||
m_traits->compare_y_at_x_2_object()(p, curr->curve()) == EQUAL)
|
||||
{
|
||||
m_traits->compare_y_at_x_2_object()(p, curr->curve()) == EQUAL) {
|
||||
// p is located on the interior of the edge.
|
||||
Halfedge_const_handle he = curr;
|
||||
Halfedge_const_handle he = curr;
|
||||
return make_result(he);
|
||||
}
|
||||
|
||||
|
|
@ -304,22 +280,18 @@ _find_face_around_vertex(Vertex_const_handle vh,
|
|||
return make_result(curr->source());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Walk from the edge to the query point.
|
||||
//
|
||||
/*! walks from the edge to the query point.
|
||||
*/
|
||||
template <typename Arr, typename Gen>
|
||||
typename Arr_landmarks_point_location<Arr, Gen>::result_type
|
||||
Arr_landmarks_point_location<Arr, Gen>::
|
||||
_walk_from_edge(Halfedge_const_handle eh,
|
||||
const Point_2& np,
|
||||
const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const
|
||||
{
|
||||
_walk_from_edge(Halfedge_const_handle eh, const Point_2& np, const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const {
|
||||
CGAL_assertion_msg(! eh->is_fictitious(),
|
||||
"_walk_from_edge() from a fictitious edge.");
|
||||
|
||||
const X_monotone_curve_2& cv = eh->curve() ;
|
||||
Comparison_result res;
|
||||
Comparison_result res;
|
||||
|
||||
X_monotone_curve_2 seg =
|
||||
m_traits->construct_x_monotone_curve_2_object()(np, p);
|
||||
|
|
@ -345,8 +317,7 @@ _walk_from_edge(Halfedge_const_handle eh,
|
|||
if (m_traits->is_in_x_range_2_object()(seg, temp_p)) {
|
||||
//we must make sure that eh is not a tip on an "antena"
|
||||
if (m_traits->compare_y_at_x_2_object()(temp_p, seg) == EQUAL &&
|
||||
eh->prev() != eh->twin())
|
||||
{
|
||||
eh->prev() != eh->twin()) {
|
||||
// the assumption is that each edge is crossed at most twice
|
||||
CGAL_assertion_msg(crossed_edges.count(eh->prev()) < 2,
|
||||
"crossed_edges should contain each halfedge at most twice.");
|
||||
|
|
@ -367,8 +338,7 @@ _walk_from_edge(Halfedge_const_handle eh,
|
|||
if (m_traits->is_in_x_range_2_object()(seg, temp_p)) {
|
||||
//we must make sure that eh is not a tip on an "antena"
|
||||
if (m_traits->compare_y_at_x_2_object()(temp_p, seg) == EQUAL &&
|
||||
eh->next() != eh->twin())
|
||||
{
|
||||
eh->next() != eh->twin()) {
|
||||
// the assumption is that each edge is crossed at most twice
|
||||
CGAL_assertion_msg(crossed_edges.count(eh->next()) < 2,
|
||||
"crossed_edges should contain each halfedge at most twice.");
|
||||
|
|
@ -428,89 +398,71 @@ _walk_from_edge(Halfedge_const_handle eh,
|
|||
return (_walk_from_vertex(vh, p, crossed_edges));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// In case the arrangement's curve contained in the segment
|
||||
// from the nearest landmark to the query point
|
||||
//
|
||||
/*! deals with an arrangement curve contained in the segment from the nearest
|
||||
* landmark to the query point
|
||||
*/
|
||||
template <typename Arr, typename Gen>
|
||||
typename Arr_landmarks_point_location<Arr, Gen>::result_type
|
||||
Arr_landmarks_point_location<Arr, Gen>::
|
||||
_deal_with_curve_contained_in_segment(Halfedge_const_handle he,
|
||||
bool p_is_left,
|
||||
_deal_with_curve_contained_in_segment(Halfedge_const_handle he, bool p_is_left,
|
||||
const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const
|
||||
{
|
||||
Halfedge_set& crossed_edges) const {
|
||||
// in this case we want to walk from to the query point from the nearest
|
||||
// vertex either the halfedge's source or target
|
||||
Vertex_const_handle vh;
|
||||
bool target_is_left;
|
||||
if (m_traits->compare_xy_2_object()
|
||||
(he->source()->point(),he->target()->point()) == LARGER)
|
||||
target_is_left = true;
|
||||
else
|
||||
target_is_left = false;
|
||||
auto cmp_xy = m_traits->compare_xy_2_object();
|
||||
bool target_is_left =
|
||||
(cmp_xy(he->source()->point(), he->target()->point()) == LARGER);
|
||||
|
||||
Vertex_const_handle vh;
|
||||
if (p_is_left) {
|
||||
if (target_is_left)
|
||||
vh = he->target();
|
||||
else
|
||||
vh = he->source();
|
||||
if (target_is_left) vh = he->target();
|
||||
else vh = he->source();
|
||||
}
|
||||
else {
|
||||
if (target_is_left)
|
||||
vh = he->source();
|
||||
else
|
||||
vh = he->target();
|
||||
if (target_is_left) vh = he->source();
|
||||
else vh = he->target();
|
||||
}
|
||||
// vh is the closest vertex among the halfedge's end points
|
||||
return (_walk_from_vertex(vh, p, crossed_edges));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Walk from the given face to the query point.
|
||||
//
|
||||
/*! walks from the given face to the query point.
|
||||
*/
|
||||
template <typename Arr, typename Gen>
|
||||
typename Arr_landmarks_point_location<Arr, Gen>::result_type
|
||||
Arr_landmarks_point_location<Arr, Gen>::
|
||||
_walk_from_face(Face_const_handle face,
|
||||
const Point_2& np,
|
||||
const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const
|
||||
{
|
||||
_walk_from_face(Face_const_handle face, const Point_2& np, const Point_2& p,
|
||||
Halfedge_set& crossed_edges) const {
|
||||
// Construct an x-monotone curve connecting the nearest landmark point np
|
||||
// to the query point p and check which CCB intersects this segment.
|
||||
X_monotone_curve_2 seg =
|
||||
m_traits->construct_x_monotone_curve_2_object()(np, p);
|
||||
const bool p_is_left =
|
||||
(m_traits->compare_xy_2_object()(np, p) == LARGER);
|
||||
X_monotone_curve_2 seg;
|
||||
Comparison_result res;
|
||||
std::tie(seg, res) = construct_segment(np, p, *m_traits, 0);
|
||||
const bool p_is_left = (res == LARGER);
|
||||
|
||||
Inner_ccb_const_iterator inner_ccb_iter;
|
||||
Outer_ccb_const_iterator outer_ccb_iter;
|
||||
const Halfedge_const_handle invalid_he;
|
||||
Halfedge_const_handle he;
|
||||
Face_const_handle new_face;
|
||||
bool is_on_edge;
|
||||
bool is_target;
|
||||
bool cv_is_contained_in_seg;
|
||||
Vertex_const_handle new_vertex;
|
||||
const Vertex_const_handle invalid_vertex;
|
||||
const Halfedge_const_handle invalid_he;
|
||||
const Vertex_const_handle invalid_vertex;
|
||||
bool cv_is_contained_in_seg;
|
||||
|
||||
do {
|
||||
// Check whether p lies inside the current face (including its holes):
|
||||
if (p_arr->topology_traits()->is_in_face(&(*face), p, nullptr))
|
||||
{
|
||||
if (p_arr->topology_traits()->is_in_face(&(*face), p, nullptr)) {
|
||||
// We know that p is located inside the current face, and we check
|
||||
// whether it lies inside one of its holes (or on the boundary of
|
||||
// its holes).
|
||||
cv_is_contained_in_seg = false;
|
||||
new_face = face;
|
||||
for (inner_ccb_iter = face->inner_ccbs_begin();
|
||||
inner_ccb_iter != face->inner_ccbs_end(); ++inner_ccb_iter)
|
||||
{
|
||||
he = _intersection_with_ccb(*inner_ccb_iter,seg, p, p_is_left,
|
||||
crossed_edges,is_on_edge, is_target,
|
||||
cv_is_contained_in_seg,new_vertex);
|
||||
if (he == invalid_he && cv_is_contained_in_seg)
|
||||
{
|
||||
auto new_face = face;
|
||||
// Do not use 'auto' to define the iterator, as MSVC2017 complains.
|
||||
for (Inner_ccb_const_iterator inner_ccb_iter = face->inner_ccbs_begin();
|
||||
inner_ccb_iter != face->inner_ccbs_end(); ++inner_ccb_iter) {
|
||||
bool is_on_edge;
|
||||
bool is_target;
|
||||
Vertex_const_handle new_vertex;
|
||||
Halfedge_const_handle he =
|
||||
_intersection_with_ccb(*inner_ccb_iter,seg, p, p_is_left,
|
||||
crossed_edges, is_on_edge, is_target,
|
||||
cv_is_contained_in_seg, new_vertex);
|
||||
if (he == invalid_he && cv_is_contained_in_seg) {
|
||||
return _deal_with_curve_contained_in_segment(*inner_ccb_iter,
|
||||
p_is_left,p,
|
||||
crossed_edges);
|
||||
|
|
@ -535,8 +487,7 @@ _walk_from_face(Face_const_handle face,
|
|||
|
||||
// Check if we found a new face (hole) containing p. If not, the current
|
||||
// face contains p.
|
||||
if (new_face == face)
|
||||
return make_result(face);
|
||||
if (new_face == face) return make_result(face);
|
||||
|
||||
// Continue from the new face (hole).
|
||||
face = new_face;
|
||||
|
|
@ -544,13 +495,17 @@ _walk_from_face(Face_const_handle face,
|
|||
else {
|
||||
// We know that p is not located inside the current face. We therefore
|
||||
// look for an edge on its outer boundary that intersects seg.
|
||||
new_face = face;
|
||||
for (outer_ccb_iter = face->outer_ccbs_begin();
|
||||
outer_ccb_iter != face->outer_ccbs_end(); ++outer_ccb_iter)
|
||||
{
|
||||
he = _intersection_with_ccb(*outer_ccb_iter,seg, p, p_is_left,
|
||||
crossed_edges,is_on_edge, is_target,
|
||||
cv_is_contained_in_seg,new_vertex);
|
||||
auto new_face = face;
|
||||
// Do not use 'auto' to define the iterator, as MSVC2017 complains.
|
||||
for (Inner_ccb_const_iterator outer_ccb_iter = face->outer_ccbs_begin();
|
||||
outer_ccb_iter != face->outer_ccbs_end(); ++outer_ccb_iter) {
|
||||
bool is_on_edge;
|
||||
bool is_target;
|
||||
Vertex_const_handle new_vertex;
|
||||
Halfedge_const_handle he =
|
||||
_intersection_with_ccb(*outer_ccb_iter,seg, p, p_is_left,
|
||||
crossed_edges, is_on_edge, is_target,
|
||||
cv_is_contained_in_seg, new_vertex);
|
||||
if (he == invalid_he && cv_is_contained_in_seg) {
|
||||
return _deal_with_curve_contained_in_segment(*outer_ccb_iter,
|
||||
p_is_left,p,
|
||||
|
|
@ -585,10 +540,9 @@ _walk_from_face(Face_const_handle face,
|
|||
return default_result();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Find a halfedge on the given CCB that intersects the given x-monotone
|
||||
// curve, connecting the current landmark to the query point.
|
||||
//
|
||||
/*! finds a halfedge on the given CCB that intersects the given x-monotone
|
||||
* curve, connecting the current landmark to the query point.
|
||||
*/
|
||||
template <typename Arr, typename Gen>
|
||||
typename Arr_landmarks_point_location<Arr, Gen>::Halfedge_const_handle
|
||||
Arr_landmarks_point_location<Arr, Gen>::
|
||||
|
|
@ -598,17 +552,15 @@ _intersection_with_ccb(Ccb_halfedge_const_circulator circ,
|
|||
Halfedge_set& crossed_edges,
|
||||
bool& is_on_edge, bool& is_target,
|
||||
bool& cv_is_contained_in_seg,
|
||||
Vertex_const_handle & new_vertex) const
|
||||
{
|
||||
Vertex_const_handle& new_vertex) const {
|
||||
is_on_edge = false;
|
||||
is_target = false;
|
||||
|
||||
// Go over the CCB.
|
||||
typename Traits_adaptor_2::Is_in_x_range_2 is_in_x_range =
|
||||
m_traits->is_in_x_range_2_object();
|
||||
Ccb_halfedge_const_circulator curr = circ , temp_circ;
|
||||
const Halfedge_const_handle invalid_he;
|
||||
Halfedge_const_handle he;
|
||||
auto is_in_x_range = m_traits->is_in_x_range_2_object();
|
||||
Ccb_halfedge_const_circulator curr = circ , temp_circ;
|
||||
const Halfedge_const_handle invalid_he;
|
||||
Halfedge_const_handle he;
|
||||
bool cv_and_seg_overlap;
|
||||
do {
|
||||
he = curr;
|
||||
|
|
@ -646,33 +598,28 @@ _intersection_with_ccb(Ccb_halfedge_const_circulator circ,
|
|||
// Check whether the current curve intersects seg an odd number of times.
|
||||
if (_have_odd_intersections(he->curve(), seg, p_is_left,
|
||||
is_on_edge,cv_and_seg_overlap,
|
||||
cv_is_contained_in_seg)
|
||||
&& !(cv_and_seg_overlap || cv_is_contained_in_seg))
|
||||
{
|
||||
cv_is_contained_in_seg) &&
|
||||
! (cv_and_seg_overlap || cv_is_contained_in_seg)) {
|
||||
// Check if the query point lies on the current edge, or whether
|
||||
// it lies in its interior.
|
||||
if (is_on_edge)
|
||||
return _in_case_p_is_on_edge(he,crossed_edges,p,is_target);
|
||||
|
||||
if ((!curr->target()->is_at_open_boundary()) &&
|
||||
is_in_x_range(seg, curr->target()->point()))
|
||||
{
|
||||
is_in_x_range(seg, curr->target()->point())) {
|
||||
// if the target point of curr is located on seg
|
||||
// we should walk from it to the query point
|
||||
if (m_traits->compare_y_at_x_2_object()
|
||||
(curr->target()->point(), seg) == EQUAL)
|
||||
{
|
||||
(curr->target()->point(), seg) == EQUAL) {
|
||||
new_vertex = curr->target();
|
||||
}
|
||||
}
|
||||
else if ((!curr->source()->is_at_open_boundary()) &&
|
||||
is_in_x_range(seg , curr->source()->point() ))
|
||||
{
|
||||
is_in_x_range(seg , curr->source()->point())) {
|
||||
// if the source point of curr is located on seg
|
||||
// we should walk from it to the query point
|
||||
if (m_traits->compare_y_at_x_2_object()
|
||||
(curr->source()->point() , seg) == EQUAL)
|
||||
{
|
||||
(curr->source()->point(), seg) == EQUAL) {
|
||||
new_vertex = curr->source();
|
||||
}
|
||||
}
|
||||
|
|
@ -718,8 +665,7 @@ Arr_landmarks_point_location<Arr, Gen>::
|
|||
_in_case_p_is_on_edge(Halfedge_const_handle he,
|
||||
Halfedge_set& crossed_edges,
|
||||
const Point_2 & p,
|
||||
bool & is_target) const
|
||||
{
|
||||
bool & is_target) const {
|
||||
// cv and seg overlap, obviously we crossed it
|
||||
// the assumption is that each edge is crossed at most twice
|
||||
CGAL_assertion_msg(crossed_edges.count(he) < 2,
|
||||
|
|
@ -728,14 +674,12 @@ _in_case_p_is_on_edge(Halfedge_const_handle he,
|
|||
crossed_edges.insert(he->twin());
|
||||
// Check if p equals one of the edge end-vertices.
|
||||
if (! he->target()->is_at_open_boundary() &&
|
||||
m_traits->compare_xy_2_object()(he->target()->point(), p) == EQUAL)
|
||||
{
|
||||
m_traits->equal_2_object()(he->target()->point(), p)) {
|
||||
// p is the target of the current halfedge.
|
||||
is_target = true;
|
||||
}
|
||||
else if (! he->source()->is_at_open_boundary() &&
|
||||
m_traits->compare_xy_2_object()(he->source()->point(), p) == EQUAL)
|
||||
{
|
||||
m_traits->equal_2_object()(he->source()->point(), p)) {
|
||||
// Take the twin halfedge, so p equals its target.
|
||||
he = he->twin();
|
||||
is_target = true;
|
||||
|
|
@ -744,21 +688,17 @@ _in_case_p_is_on_edge(Halfedge_const_handle he,
|
|||
return he;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Check whether the given curve intersects a simple segment, which connects
|
||||
// the current landmark to the query point, an odd number of times.
|
||||
//
|
||||
/*! checks whether the given curve intersects a simple segment, which connects
|
||||
* the current landmark to the query point, an odd number of times.
|
||||
*/
|
||||
template <typename Arr, typename Gen>
|
||||
bool Arr_landmarks_point_location<Arr, Gen>::
|
||||
_have_odd_intersections(const X_monotone_curve_2& cv,
|
||||
const X_monotone_curve_2& seg,
|
||||
bool p_is_left,
|
||||
bool& p_on_curve,
|
||||
bool p_is_left, bool& p_on_curve,
|
||||
bool& cv_and_seg_overlap,
|
||||
bool& cv_is_contained_in_seg) const
|
||||
{
|
||||
typename Traits_adaptor_2::Is_in_x_range_2 is_in_x_range =
|
||||
m_traits->is_in_x_range_2_object();
|
||||
bool& cv_is_contained_in_seg) const {
|
||||
auto is_in_x_range = m_traits->is_in_x_range_2_object();
|
||||
p_on_curve = false;
|
||||
cv_and_seg_overlap = false;
|
||||
cv_is_contained_in_seg = false;
|
||||
|
|
@ -776,9 +716,9 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
cv_right = m_traits->construct_max_vertex_2_object()(cv);
|
||||
if (cv_left_is_closed && cv_right_is_closed) {
|
||||
if (is_in_x_range(seg,cv_left) && is_in_x_range(seg,cv_right)) {
|
||||
if ((m_traits->compare_y_at_x_2_object()(cv_left, seg) == EQUAL) &&
|
||||
(m_traits->compare_y_at_x_2_object()(cv_right, seg) == EQUAL))
|
||||
{
|
||||
auto cmp_y_at_x = m_traits->compare_y_at_x_2_object();
|
||||
if ((cmp_y_at_x(cv_left, seg) == EQUAL) &&
|
||||
(cmp_y_at_x(cv_right, seg) == EQUAL)) {
|
||||
// cv is contained in seg non of the answer true or false is correct
|
||||
// we must set a special flag to distinguish this case
|
||||
cv_is_contained_in_seg = true;
|
||||
|
|
@ -791,22 +731,17 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
if (cv_left_is_closed) {
|
||||
// Check if the left endpoint of cv has the same x-coordinate as the
|
||||
// right endpoint of seg.
|
||||
if (m_traits->compare_x_2_object()
|
||||
(m_traits->construct_min_vertex_2_object()(cv), seg_right) == EQUAL)
|
||||
{
|
||||
if (! p_is_left &&
|
||||
m_traits->compare_xy_2_object()
|
||||
(m_traits->construct_min_vertex_2_object()(cv), seg_right) == EQUAL)
|
||||
{
|
||||
auto min_p = m_traits->construct_min_vertex_2_object()(cv);
|
||||
if (equal_x_2(min_p, seg_right, Left_or_right_sides_category())) {
|
||||
if (! p_is_left && m_traits->equal_2_object()(min_p, seg_right)) {
|
||||
p_on_curve = true;
|
||||
return true;
|
||||
}
|
||||
else if (m_traits->is_vertical_2_object()(seg)) {
|
||||
auto cmp_y_at_x = m_traits->compare_y_at_x_2_object();
|
||||
// Special treatment for vertical segments.
|
||||
Comparison_result res_l =
|
||||
m_traits->compare_y_at_x_2_object()(seg_left, cv);
|
||||
Comparison_result res_r =
|
||||
m_traits->compare_y_at_x_2_object()(seg_right, cv);
|
||||
Comparison_result res_l = cmp_y_at_x(seg_left, cv);
|
||||
Comparison_result res_r = cmp_y_at_x(seg_right, cv);
|
||||
if ((p_is_left && res_l == EQUAL) || (! p_is_left && res_r == EQUAL)) {
|
||||
p_on_curve = true;
|
||||
return true;
|
||||
|
|
@ -819,23 +754,17 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
if (cv_right_is_closed) {
|
||||
// Check if the right endpoint of cv has the same x-coordinate as the
|
||||
// left endpoint of seg.
|
||||
if (m_traits->compare_x_2_object()
|
||||
(m_traits->construct_max_vertex_2_object()(cv), seg_left) == EQUAL)
|
||||
{
|
||||
if (p_is_left &&
|
||||
m_traits->compare_xy_2_object()
|
||||
(m_traits->construct_max_vertex_2_object()(cv), seg_left) == EQUAL)
|
||||
{
|
||||
auto max_p = m_traits->construct_max_vertex_2_object()(cv);
|
||||
if (equal_x_2(max_p, seg_left, Left_or_right_sides_category())) {
|
||||
if (p_is_left && m_traits->equal_2_object()(max_p, seg_left)) {
|
||||
p_on_curve = true;
|
||||
return true;
|
||||
}
|
||||
else if (m_traits->is_vertical_2_object()(seg)) {
|
||||
// Special treatment for vertical segments.
|
||||
Comparison_result res_l =
|
||||
m_traits->compare_y_at_x_2_object()(seg_left, cv);
|
||||
Comparison_result res_r =
|
||||
m_traits->compare_y_at_x_2_object()(seg_right, cv);
|
||||
|
||||
auto cmp_y_at_x = m_traits->compare_y_at_x_2_object();
|
||||
Comparison_result res_l = cmp_y_at_x(seg_left, cv);
|
||||
Comparison_result res_r = cmp_y_at_x(seg_right, cv);
|
||||
if ((p_is_left && res_l == EQUAL) || (! p_is_left && res_r == EQUAL)) {
|
||||
p_on_curve = true;
|
||||
return true;
|
||||
|
|
@ -846,8 +775,8 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
}
|
||||
}
|
||||
// Compare the two left ends of cv and seg.
|
||||
Comparison_result left_res;
|
||||
const Arr_parameter_space bx_l =
|
||||
Comparison_result left_res;
|
||||
const Arr_parameter_space bx_l =
|
||||
m_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END);
|
||||
if (bx_l == ARR_LEFT_BOUNDARY) {
|
||||
// The left end of cv lies to the left of seg_left:
|
||||
|
|
@ -858,11 +787,11 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
// The left end of cv lies to the right of seg_left.
|
||||
// Compare the left endpoint of cv to seg.
|
||||
left_res = m_traits->compare_y_at_x_2_object()
|
||||
(m_traits->construct_min_vertex_2_object()(cv), seg);
|
||||
(m_traits->construct_min_vertex_2_object()(cv), seg);
|
||||
left_res = CGAL::opposite(left_res);
|
||||
}
|
||||
else {
|
||||
const Arr_parameter_space by_l =
|
||||
const Arr_parameter_space by_l =
|
||||
m_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END);
|
||||
if (by_l == ARR_BOTTOM_BOUNDARY)
|
||||
// The left end of cv is at y = -oo, so cv obviously lies above it.
|
||||
|
|
@ -876,8 +805,7 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
Comparison_result res = m_traits->compare_xy_2_object()(cv_left, seg_left);
|
||||
if (res != LARGER) {
|
||||
left_res = m_traits->compare_y_at_x_2_object()(seg_left, cv);
|
||||
if (p_is_left && left_res == EQUAL)
|
||||
{
|
||||
if (p_is_left && left_res == EQUAL) {
|
||||
// In this case the query point p, which is the left endpoint of seg,
|
||||
// lies on cv.
|
||||
p_on_curve = true;
|
||||
|
|
@ -904,8 +832,7 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
// we must set a special flag to distinguish this case
|
||||
if (is_in_x_range(cv,( p_is_left ? seg_left : seg_right)))
|
||||
if (m_traits->compare_y_at_x_2_object()
|
||||
((p_is_left ? seg_left : seg_right), cv) == EQUAL)
|
||||
{
|
||||
((p_is_left ? seg_left : seg_right), cv) == EQUAL) {
|
||||
p_on_curve = true;
|
||||
}
|
||||
cv_and_seg_overlap = true;
|
||||
|
|
@ -913,8 +840,8 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
}
|
||||
}
|
||||
// Compare the two right ends of cv and seg.
|
||||
Comparison_result right_res;
|
||||
const Arr_parameter_space bx_r =
|
||||
Comparison_result right_res;
|
||||
const Arr_parameter_space bx_r =
|
||||
m_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END);
|
||||
if (bx_r == ARR_RIGHT_BOUNDARY) {
|
||||
// The right end of cv lies to the right of seg_right:
|
||||
|
|
@ -925,11 +852,11 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
// The right end of cv lies to the left of seg_right.
|
||||
// Compare the right endpoint of cv to seg.
|
||||
right_res = m_traits->compare_y_at_x_2_object()
|
||||
(m_traits->construct_max_vertex_2_object()(cv), seg);
|
||||
(m_traits->construct_max_vertex_2_object()(cv), seg);
|
||||
right_res = CGAL::opposite(right_res);
|
||||
}
|
||||
else {
|
||||
const Arr_parameter_space by_r =
|
||||
const Arr_parameter_space by_r =
|
||||
m_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END);
|
||||
if (by_r == ARR_BOTTOM_BOUNDARY)
|
||||
// The right end of cv is at y = -oo, so cv obviously lies above it.
|
||||
|
|
@ -972,8 +899,7 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
// we must set a special flag to distinguish this case
|
||||
if (is_in_x_range(cv, (p_is_left ? seg_left : seg_right)))
|
||||
if (m_traits->compare_y_at_x_2_object()
|
||||
((p_is_left ? seg_left : seg_right), cv) == EQUAL)
|
||||
{
|
||||
((p_is_left ? seg_left : seg_right), cv) == EQUAL) {
|
||||
p_on_curve = true;
|
||||
}
|
||||
cv_and_seg_overlap = true;
|
||||
|
|
@ -986,6 +912,6 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
|
|||
return (left_res != right_res);
|
||||
}
|
||||
|
||||
} //namespace CGAL
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -76,9 +76,9 @@ public:
|
|||
NUMBER_OF_OPERATIONS
|
||||
};
|
||||
|
||||
private:
|
||||
using Base = BaseTraits;
|
||||
|
||||
private:
|
||||
//! A set of bits that indicate whether operations should be traced.
|
||||
unsigned long long m_flags;
|
||||
|
||||
|
|
@ -212,6 +212,7 @@ public:
|
|||
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||
using Curve_2 = typename Base::Curve_2;
|
||||
using Multiplicity = typename Base::Multiplicity;
|
||||
//@}
|
||||
|
||||
/*! A functor that compares the \f$x\f$-coordinates of two points. */
|
||||
class Compare_x_2 {
|
||||
|
|
@ -832,9 +833,16 @@ public:
|
|||
std::cout << "approximate_2" << std::endl
|
||||
<< " xcv: " << xcv << ", error: " << error
|
||||
<< ", l2r: " << l2r << std::endl;
|
||||
auto res = m_object(xcv, error, oi, l2r);
|
||||
std::cout << " result: " << res << std::endl;
|
||||
return res;
|
||||
std::list<Approximate_point_2> container;
|
||||
m_object(xcv, error, std::back_inserter(container), l2r);
|
||||
if (container.empty()) return oi;
|
||||
|
||||
std::size_t i = 0;
|
||||
for (const auto& point : container) {
|
||||
std::cout << " result[" << i++ << "]: " << point << std::endl;
|
||||
*oi++ = point;
|
||||
}
|
||||
return oi;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ void copy_face_graph_impl(const SourceMesh& sm, TargetMesh& tm,
|
|||
}
|
||||
|
||||
// detect if there are some non-manifold umbrellas and fix missing halfedge target pointers
|
||||
std::map<sm_vertex_descriptor, std::vector<tm_halfedge_descriptor>> nm_umbrella_map;
|
||||
typedef typename std::vector<tm_edge_descriptor>::iterator edge_iterator;
|
||||
for (edge_iterator it=new_edges.begin(); it!=new_edges.end(); ++it)
|
||||
{
|
||||
|
|
@ -199,10 +200,19 @@ void copy_face_graph_impl(const SourceMesh& sm, TargetMesh& tm,
|
|||
// we recover tm_v using the halfedge associated to the target vertex of
|
||||
// the halfedge in sm corresponding to nh_t. This is working because we
|
||||
// set the vertex halfedge pointer to the "same" halfedges.
|
||||
tm_vertex_descriptor tm_v =
|
||||
target( get(hs_to_ht, halfedge(target(get(ht_to_hs, nh_t), sm), sm)), tm);
|
||||
for(tm_halfedge_descriptor ht : halfedges_around_target(nh_t, tm))
|
||||
set_target(ht, tm_v, tm);
|
||||
|
||||
sm_vertex_descriptor vs = target(get(ht_to_hs, nh_t), sm);
|
||||
sm_halfedge_descriptor hs = halfedge(vs, sm);
|
||||
if (hs == boost::graph_traits<SourceMesh>::null_halfedge())
|
||||
{ // special case for Face_filtered_graph with a non-manifold input with not all umbrellas selected
|
||||
nm_umbrella_map[vs].push_back(nh_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
tm_vertex_descriptor tm_v = target( get(hs_to_ht, hs), tm);
|
||||
for(tm_halfedge_descriptor ht : halfedges_around_target(nh_t, tm))
|
||||
set_target(ht, tm_v, tm);
|
||||
}
|
||||
}
|
||||
nh_t = opposite(nh_t, tm);
|
||||
}
|
||||
|
|
@ -210,6 +220,18 @@ void copy_face_graph_impl(const SourceMesh& sm, TargetMesh& tm,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& vs_and_hts : nm_umbrella_map)
|
||||
{
|
||||
sm_vertex_descriptor v_sm = vs_and_hts.first;
|
||||
tm_vertex_descriptor v_tm = add_vertex(tm);
|
||||
*v2v++=std::make_pair(v_sm, v_tm);
|
||||
set_halfedge(v_tm, vs_and_hts.second.front(), tm);
|
||||
put(tm_vpm, v_tm, conv(get(sm_vpm, v_sm)));
|
||||
|
||||
for (tm_halfedge_descriptor h_tm : vs_and_hts.second)
|
||||
set_target(h_tm, v_tm, tm);
|
||||
}
|
||||
}
|
||||
|
||||
} // end of namespace internal
|
||||
|
|
|
|||
|
|
@ -579,6 +579,102 @@ void test_Polyhedron_tetrahedron()
|
|||
test_mesh<Polyhedron, FCMap, Poly_Adapter>(poly_adapter);
|
||||
}
|
||||
|
||||
void non_manifoldness_test1()
|
||||
{
|
||||
// works out-of-the-box because Face_filtered_graph handles already non-manifold cycles
|
||||
SM mesh;
|
||||
SM::Vertex_index v0=add_vertex(mesh);
|
||||
SM::Vertex_index v1=add_vertex(mesh);
|
||||
SM::Vertex_index v2=add_vertex(mesh);
|
||||
SM::Vertex_index v3=add_vertex(mesh);
|
||||
SM::Vertex_index v4=add_vertex(mesh);
|
||||
SM::Vertex_index v5=add_vertex(mesh);
|
||||
SM::Vertex_index v6=add_vertex(mesh);
|
||||
|
||||
SM::Face_index f0=mesh.add_face(v0,v1,v2);
|
||||
SM::Face_index f1=mesh.add_face(v0,v3,v4);
|
||||
SM::Face_index f2=mesh.add_face(v0,v5,v6);
|
||||
SM::Halfedge_index h = halfedge(f0,mesh);
|
||||
while(target(h, mesh)!=v0)
|
||||
h=next(h,mesh);
|
||||
set_halfedge(v0, h, mesh);
|
||||
|
||||
std::vector<SM::Face_index> selection = {f1, f2};
|
||||
CGAL::Face_filtered_graph<SM> ffg(mesh, selection);
|
||||
|
||||
SM out;
|
||||
CGAL::copy_face_graph(ffg, out);
|
||||
|
||||
assert(vertices(out).size()==5);
|
||||
assert(faces(out).size()==2);
|
||||
}
|
||||
|
||||
void non_manifoldness_test2()
|
||||
{
|
||||
SM mesh;
|
||||
SM::Vertex_index v0=add_vertex(mesh);
|
||||
SM::Vertex_index v0b=add_vertex(mesh);
|
||||
SM::Vertex_index v0t=add_vertex(mesh);
|
||||
|
||||
SM::Vertex_index v1=add_vertex(mesh);
|
||||
SM::Vertex_index v2=add_vertex(mesh);
|
||||
SM::Vertex_index v3=add_vertex(mesh);
|
||||
|
||||
SM::Vertex_index v4=add_vertex(mesh);
|
||||
SM::Vertex_index v5=add_vertex(mesh);
|
||||
SM::Vertex_index v6=add_vertex(mesh);
|
||||
|
||||
SM::Vertex_index v7=add_vertex(mesh);
|
||||
SM::Vertex_index v8=add_vertex(mesh);
|
||||
SM::Vertex_index v9=add_vertex(mesh);
|
||||
|
||||
SM::Face_index f00=mesh.add_face(v1,v2,v0);
|
||||
SM::Face_index f01=mesh.add_face(v2,v3,v0);
|
||||
SM::Face_index f02=mesh.add_face(v3,v1,v0);
|
||||
|
||||
SM::Face_index f10=mesh.add_face(v4,v5,v0b);
|
||||
SM::Face_index f11=mesh.add_face(v5,v6,v0b);
|
||||
SM::Face_index f12=mesh.add_face(v6,v4,v0b);
|
||||
|
||||
SM::Face_index f20=mesh.add_face(v7,v8,v0t);
|
||||
SM::Face_index f21=mesh.add_face(v8,v9,v0t);
|
||||
SM::Face_index f22=mesh.add_face(v9,v7,v0t);
|
||||
|
||||
assert(f00!=SM::Face_index());
|
||||
assert(f01!=SM::Face_index());
|
||||
assert(f02!=SM::Face_index());
|
||||
assert(f10!=SM::Face_index());
|
||||
assert(f11!=SM::Face_index());
|
||||
assert(f12!=SM::Face_index());
|
||||
assert(f20!=SM::Face_index());
|
||||
assert(f21!=SM::Face_index());
|
||||
assert(f22!=SM::Face_index());
|
||||
|
||||
#define UPDATE_V(fX, vX) \
|
||||
{ SM::Halfedge_index h = halfedge(fX,mesh);\
|
||||
while(target(h, mesh)!=vX) h=next(h,mesh);\
|
||||
set_target(h, v0, mesh); }
|
||||
|
||||
UPDATE_V(f10, v0b)
|
||||
UPDATE_V(f11, v0b)
|
||||
UPDATE_V(f12, v0b)
|
||||
UPDATE_V(f20, v0t)
|
||||
UPDATE_V(f21, v0t)
|
||||
UPDATE_V(f22, v0t)
|
||||
|
||||
remove_vertex(v0b, mesh);
|
||||
remove_vertex(v0t, mesh);
|
||||
|
||||
std::vector<SM::Face_index> selection = {f10, f11, f12, f20, f21, f22};
|
||||
CGAL::Face_filtered_graph<SM> ffg(mesh, selection);
|
||||
|
||||
SM out;
|
||||
CGAL::copy_face_graph(ffg, out);
|
||||
|
||||
assert(vertices(out).size()==7);
|
||||
assert(faces(out).size()==6);
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_graph_range(poly_data());
|
||||
|
|
@ -590,6 +686,8 @@ int main(int, char**)
|
|||
#endif
|
||||
|
||||
test_invalid_selections();
|
||||
non_manifoldness_test1();
|
||||
non_manifoldness_test2();
|
||||
|
||||
test_SM_tetrahedron();
|
||||
test_Polyhedron_tetrahedron();
|
||||
|
|
|
|||
|
|
@ -600,6 +600,7 @@ inline long longValue(const BigFloat& bf)
|
|||
{
|
||||
return bf.longValue();
|
||||
}
|
||||
//@}
|
||||
|
||||
} //namespace CORE
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ else()
|
|||
set(CGAL_ROOT "${CMAKE_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
cmake_minimum_required(VERSION 3.18..3.29) # for list(SORT ... COMPARE NATURAL)
|
||||
|
||||
find_package(Doxygen REQUIRED)
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||
|
||||
|
|
@ -32,7 +34,7 @@ if (NOT Python3_EXECUTABLE)
|
|||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS ${Python3_EXECUTABLE})
|
||||
message(VERBOSE "Using Python version ${Python3_VERSION}: ${Python3_EXECUTABLE}")
|
||||
|
||||
if(NOT DOXYGEN_FOUND)
|
||||
message(WARNING "Cannot build the documentation without Doxygen!")
|
||||
|
|
@ -275,7 +277,7 @@ set(CGAL_DOC_DXY_DIR "${CMAKE_BINARY_DIR}/doc_dxy")
|
|||
file(MAKE_DIRECTORY "${CGAL_DOC_DXY_DIR}")
|
||||
|
||||
#Setting the resource directory depending on the version of doxygen
|
||||
set(CGAL_DOC_RESOURCE_DIR_DEFAULT "${CMAKE_CURRENT_LIST_DIR}/resources/1.10.0")
|
||||
set(CGAL_DOC_RESOURCE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/resources")
|
||||
|
||||
# first look if resources for the specific doxygen version is available, fallback
|
||||
# on the default otherwise
|
||||
|
|
@ -283,12 +285,46 @@ set(CGAL_DOC_RESOURCE_DIR_DEFAULT "${CMAKE_CURRENT_LIST_DIR}/resources/1.10.0")
|
|||
#select only the version number (not the commit hash)
|
||||
string(REPLACE " " ";" DOXYGEN_VERSION ${DOXYGEN_VERSION})
|
||||
list(GET DOXYGEN_VERSION 0 DOXYGEN_VERSION)
|
||||
message(VERBOSE "Doxygen version ${DOXYGEN_VERSION}: ${DOXYGEN_EXECUTABLE}")
|
||||
|
||||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/resources/${DOXYGEN_VERSION}")
|
||||
set(CGAL_DOC_RESOURCE_DIR
|
||||
"${CMAKE_CURRENT_LIST_DIR}/resources/${DOXYGEN_VERSION}")
|
||||
# The Doxygen version is search in that sorted list (to find the index for which the version is less or equal)
|
||||
set(CGAL_DOXYGEN_RESOURCES_VERSIONS 1.8.13 1.9.6 1.10.0)
|
||||
list(SORT CGAL_DOXYGEN_RESOURCES_VERSIONS COMPARE NATURAL)
|
||||
|
||||
# The GLOB is here to check that the list in CGAL_DOXYGEN_RESOURCES_VERSIONS is correct.
|
||||
# CGAL_DOXYGEN_RESOURCES_DIRS is also used below.
|
||||
file(GLOB CGAL_DOXYGEN_RESOURCES_DIRS
|
||||
RELATIVE "${CGAL_DOC_RESOURCE_PREFIX_DIR}"
|
||||
"${CGAL_DOC_RESOURCE_PREFIX_DIR}/*")
|
||||
list(SORT CGAL_DOXYGEN_RESOURCES_DIRS COMPARE NATURAL)
|
||||
|
||||
if(NOT CGAL_DOXYGEN_RESOURCES_DIRS STREQUAL CGAL_DOXYGEN_RESOURCES_VERSIONS)
|
||||
message(FATAL "The directories in ${CGAL_DOC_RESOURCE_PREFIX_DIR} do not match the
|
||||
expected versions: [${CGAL_DOXYGEN_RESOURCES_VERSIONS}] vs [${CGAL_DOXYGEN_RESOURCES_DIRS}]")
|
||||
endif()
|
||||
|
||||
function(CGAL_insert_in_sorted_list list_name value)
|
||||
set(list ${${list_name}})
|
||||
if(NOT value IN_LIST list)
|
||||
list(APPEND list "${value}")
|
||||
list(SORT list COMPARE NATURAL)
|
||||
endif()
|
||||
set(${list_name} ${list} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(DOXYGEN_VERSION IN_LIST CGAL_DOXYGEN_RESOURCES_VERSIONS)
|
||||
list(FIND CGAL_DOXYGEN_RESOURCES_VERSIONS "${DOXYGEN_VERSION}" DOXYGEN_VERSION_INDEX)
|
||||
else()
|
||||
set(CGAL_DOC_RESOURCE_DIR "${CGAL_DOC_RESOURCE_DIR_DEFAULT}")
|
||||
CGAL_insert_in_sorted_list(CGAL_DOXYGEN_RESOURCES_VERSIONS ${DOXYGEN_VERSION})
|
||||
list(FIND CGAL_DOXYGEN_RESOURCES_VERSIONS ${DOXYGEN_VERSION} DOXYGEN_VERSION_INDEX)
|
||||
math(EXPR DOXYGEN_VERSION_INDEX "${DOXYGEN_VERSION_INDEX} - 1")
|
||||
endif()
|
||||
list(GET CGAL_DOXYGEN_RESOURCES_DIRS "${DOXYGEN_VERSION_INDEX}" CGAL_DOC_RESOURCE_DIR)
|
||||
set(CGAL_DOC_RESOURCE_DIR "${CGAL_DOC_RESOURCE_PREFIX_DIR}/${CGAL_DOC_RESOURCE_DIR}")
|
||||
if(NOT EXISTS "${CGAL_DOC_RESOURCE_DIR}")
|
||||
message(FATAL_ERROR "Doxygen resources for version ${DOXYGEN_VERSION} not found")
|
||||
else()
|
||||
message(VERBOSE "Using Doxygen resources from ${CGAL_DOC_RESOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
set(CGAL_DOC_BIBLIO_DIR "${CMAKE_CURRENT_LIST_DIR}/biblio")
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ complexity are known. Also, the theoretic interest in efficiency for
|
|||
realistic inputs, as opposed to worst-case situations, is
|
||||
growing \cgalCite{v-ffrim-97}.
|
||||
For practical purposes, insight into the constant factors hidden in the
|
||||
\cgalBigO{ }-notation is necessary, especially if there are several competing
|
||||
\cgalBigO{~}-notation is necessary, especially if there are several competing
|
||||
algorithms.
|
||||
|
||||
Therefore, different implementations should be supplied if there is
|
||||
|
|
|
|||
|
|
@ -35,6 +35,6 @@ These options should suffice to create a `CMakeLists.txt` script
|
|||
for most directories containing programs. However, in some special
|
||||
cases, it might still be required to create the script manually, for
|
||||
instance, if some source files/executables need a different linking than
|
||||
other source files. The Section \subpage devman_create_and_use_a_cmakelist provides more details.
|
||||
other source files. The Section \ref devman_create_and_use_a_cmakelist provides more details.
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -23,4 +23,5 @@ The developer manual is primarily aimed at \cgal developers, but may also be int
|
|||
- \subpage devman_info
|
||||
- \subpage devman_create_cgal_CMakeLists
|
||||
- \subpage deprecated
|
||||
- \subpage Doxygen_for_CGAL
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ FILTER_PATTERNS = *.txt=${CMAKE_BINARY_DIR}/pkglist_filter
|
|||
|
||||
HTML_EXTRA_FILES += ${CGAL_DOC_RESOURCE_DIR}/hacks.js \
|
||||
${CGAL_DOC_RESOURCE_DIR}/menu_version.js \
|
||||
${CGAL_DOC_RESOURCE_DIR}/cgal_stylesheet.css \
|
||||
${CMAKE_BINARY_DIR}/how_to_cite_cgal.bib \
|
||||
${CMAKE_BINARY_DIR}/how_to_cite.html \
|
||||
${CGAL_PACKAGE_DOC_DIR}/fig/g-196x196-doc.png
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Doxygen for CGAL #
|
||||
\page Doxygen_for_CGAL Doxygen for CGAL
|
||||
|
||||
This is the documentation of doxygen hacks that are applied to make
|
||||
the output of Doxygen more suitable to CGAL. It explains the general
|
||||
|
|
@ -14,17 +14,17 @@ hacks that create what you see.
|
|||
### Package Overview ###
|
||||
|
||||
The package overview is build by having a special command that is
|
||||
filtered by the python script pkglist_filter.py.
|
||||
filtered by the python script `pkglist_filter.py`.
|
||||
|
||||
A command has to be of the form \package_listing{PKG_NAME}, where
|
||||
PKG_NAME cannot contain a closing }.
|
||||
A command has to be of the form `\package_listing{PKG_NAME}`, where
|
||||
`PKG_NAME` cannot contain a closing `}`.
|
||||
|
||||
The command is replaced by the text between the two delimiters
|
||||
PkgDescBegin and PkgDescEnd in the file ../PKG_NAME/doc/PKG_NAME/PackageDescription.txt
|
||||
`cgalPkgDescriptionBegin` and `cgalPkgDescriptionEnd` in the file `../PKG_NAME/doc/PKG_NAME/PackageDescription.txt`
|
||||
|
||||
If PKG_NAME is of the form A/B the selected file is
|
||||
../A/doc/B/PackageDescription.txt. This is to support packages like
|
||||
TDS_2, which don't reside in their own packages in the SCM.
|
||||
If `PKG_NAME` is of the form `A/B` the selected file is
|
||||
`../A/doc/B/PackageDescription.txt`. This is to support packages like
|
||||
`TDS_2`, which don't reside in their own packages in the SCM.
|
||||
|
||||
### Footnotes ###
|
||||
|
||||
|
|
@ -50,13 +50,13 @@ LaTex.
|
|||
This hack fiddles with the internal structures and functions of the
|
||||
treeview to remove the unnecessary intermediate top-level module part.
|
||||
|
||||
It assigns the first element of the module array (found in module.js)
|
||||
It assigns the first element of the module array (found in `module.js`)
|
||||
to the Reference Manual entry. This makes the tree view link go to
|
||||
that group directly instead of the intermediate link. It also removes
|
||||
one level of nesting.
|
||||
|
||||
Unfortunately this changes the overall tree structure. To adjust for
|
||||
that we hijack the gotoNode function of navtree.js and *augment* it
|
||||
that we hijack the `gotoNode` function of `navtree.js` and *augment* it
|
||||
with an additional check for the specific tree level we borked and
|
||||
redirect it.
|
||||
|
||||
|
|
@ -2512,7 +2512,7 @@ cell neighborhood in $O(m)$ time."
|
|||
booktitle = {Handbook of Computational Geometry},
|
||||
publisher = {Elsevier Science Publishers B.V. North-Holland},
|
||||
address = {Amsterdam},
|
||||
year = {2000}
|
||||
year = {2000},
|
||||
pages = {49--119},
|
||||
update = {00.03 bibrelex, 99.03 bibrelex, 98.11 bibrelex, 98.07 mitchell},
|
||||
annote = {Chapter 2 of su-hcg-00}
|
||||
|
|
@ -152057,12 +152057,13 @@ keywords = {polygonal surface mesh, Surface reconstruction, kinetic framework, s
|
|||
|
||||
@article{cvl-ew-12,
|
||||
Author = {Cabello, Sergio and de Verdière, {\'E}ric Colin and Lazarus, Francis},
|
||||
Title = {Algorithms for the edge-width of an embedded graph},
|
||||
Journal = {Computational Geometry},
|
||||
Volume = {45},
|
||||
Pages = {215--224},
|
||||
Year = {2012},
|
||||
Url = {https://monge.univ-mlv.fr/~colinde/pub/09edgewidth.pdf}
|
||||
Title = {Algorithms for the edge-width of an embedded graph},
|
||||
Journal = {Computational Geometry},
|
||||
Volume = {45},
|
||||
Pages = {215--224},
|
||||
Year = {2012},
|
||||
Url = {https://monge.univ-mlv.fr/~colinde/pub/09edgewidth.pdf}
|
||||
}
|
||||
|
||||
@inproceedings{tang2009interactive,
|
||||
title={Interactive Hausdorff distance computation for general polygonal models},
|
||||
|
|
|
|||
|
|
@ -486,24 +486,6 @@ HTML_HEADER = ${CGAL_DOC_HEADER_PACKAGE}
|
|||
|
||||
HTML_FOOTER = ${CGAL_DOC_RESOURCE_DIR}/footer.html
|
||||
|
||||
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
|
||||
# cascading style sheets that are included after the standard style sheets
|
||||
# created by doxygen. Using this option one can overrule certain style aspects.
|
||||
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
||||
# standard style sheet and is therefore more robust against future updates.
|
||||
# Doxygen will copy the style sheet files to the output directory.
|
||||
# Note: The order of the extra style sheet files is of importance (e.g. the last
|
||||
# style sheet in the list overrules the setting of the previous ones in the
|
||||
# list).
|
||||
# Note: Since the styling of scrollbars can currently not be overruled in
|
||||
# Webkit/Chromium, the styling will be left out of the default doxygen.css if
|
||||
# one or more extra stylesheets have been specified. So if scrollbar
|
||||
# customization is desired it has to be added explicitly. For an example see the
|
||||
# documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_STYLESHEET = ${CGAL_DOC_RESOURCE_DIR}/cgal_stylesheet.css
|
||||
|
||||
# Doxygen stores a couple of settings persistently in the browser (via e.g.
|
||||
# cookies). By default these settings apply to all HTML pages generated by
|
||||
# doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store
|
||||
|
|
@ -541,6 +523,18 @@ DISABLE_INDEX = YES
|
|||
|
||||
GENERATE_TREEVIEW = YES
|
||||
|
||||
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
|
||||
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
|
||||
# area (value NO) or if it should extend to the full height of the window (value
|
||||
# YES). Setting this to YES gives a layout similar to
|
||||
# https://docs.readthedocs.io with more room for contents, but less room for the
|
||||
# project logo, title, and description. If either GENERATE_TREEVIEW or
|
||||
# DISABLE_INDEX is set to NO, this option has no effect.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
FULL_SIDEBAR = NO
|
||||
|
||||
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
|
||||
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
|
||||
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
|
||||
|
|
|
|||
|
|
@ -32,4 +32,14 @@ MathJax.Hub.Config(
|
|||
}
|
||||
}
|
||||
);
|
||||
MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
|
||||
var PARSE = MathJax.InputJax.TeX.Parse,
|
||||
TEXT = PARSE.prototype.InternalText;
|
||||
PARSE.Augment({
|
||||
InternalText: function (text,def) {
|
||||
text = text.replace(/\\/g,"");
|
||||
return TEXT.call(this,text,def);
|
||||
}
|
||||
});
|
||||
});
|
||||
//]]>
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ $search
|
|||
$mathjax
|
||||
$darkmode
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
<link href="$relpath$../Manual/cgal_stylesheet.css" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
<script type="text/javascript" src="../Manual/search/search.js"></script>
|
||||
<!-- Manually done below. -->
|
||||
<link href="$relpath^../Manual/$stylesheet" rel="stylesheet" type="text/css" />
|
||||
<link href="$relpath$../Manual/cgal_stylesheet.css" rel="stylesheet" type="text/css" />
|
||||
$mathjax
|
||||
$darkmode
|
||||
<script src="$relpath^topics.js" type="text/javascript"></script>
|
||||
|
|
|
|||
|
|
@ -477,24 +477,6 @@ HTML_HEADER = ${CGAL_DOC_HEADER_PACKAGE}
|
|||
|
||||
HTML_FOOTER = ${CGAL_DOC_RESOURCE_DIR}/footer.html
|
||||
|
||||
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
|
||||
# cascading style sheets that are included after the standard style sheets
|
||||
# created by doxygen. Using this option one can overrule certain style aspects.
|
||||
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
||||
# standard style sheet and is therefore more robust against future updates.
|
||||
# Doxygen will copy the style sheet files to the output directory.
|
||||
# Note: The order of the extra style sheet files is of importance (e.g. the last
|
||||
# style sheet in the list overrules the setting of the previous ones in the
|
||||
# list).
|
||||
# Note: Since the styling of scrollbars can currently not be overruled in
|
||||
# Webkit/Chromium, the styling will be left out of the default doxygen.css if
|
||||
# one or more extra stylesheets have been specified. So if scrollbar
|
||||
# customization is desired it has to be added explicitly. For an example see the
|
||||
# documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_STYLESHEET = ${CGAL_DOC_RESOURCE_DIR}/cgal_stylesheet.css
|
||||
|
||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
||||
# page will contain the date and time when the page was generated. Setting this
|
||||
# to YES can help to show when doxygen was last run and thus if the
|
||||
|
|
|
|||
|
|
@ -31,4 +31,14 @@ MathJax.Hub.Config(
|
|||
}
|
||||
}
|
||||
);
|
||||
MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
|
||||
var PARSE = MathJax.InputJax.TeX.Parse,
|
||||
TEXT = PARSE.prototype.InternalText;
|
||||
PARSE.Augment({
|
||||
InternalText: function (text,def) {
|
||||
text = text.replace(/\\/g,"");
|
||||
return TEXT.call(this,text,def);
|
||||
}
|
||||
});
|
||||
});
|
||||
//]]>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ $treeview
|
|||
$search
|
||||
$mathjax
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
<!-- This should probably be an extrastylesheet instead of hardcoded. -->
|
||||
<link href="$relpath$../Manual/cgal_stylesheet.css" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
<script type="text/javascript" src="../Manual/search/search.js"></script>
|
||||
<!-- Manually done below. -->
|
||||
<link href="$relpath^../Manual/$stylesheet" rel="stylesheet" type="text/css" />
|
||||
<!-- This should probably be an extrastylesheet instead of hardcoded. -->
|
||||
<link href="$relpath$../Manual/cgal_stylesheet.css" rel="stylesheet" type="text/css" />
|
||||
<script type="text/x-mathjax-config">
|
||||
MathJax.Hub.Config({
|
||||
|
|
|
|||
|
|
@ -486,24 +486,6 @@ HTML_HEADER = ${CGAL_DOC_HEADER_PACKAGE}
|
|||
|
||||
HTML_FOOTER = ${CGAL_DOC_RESOURCE_DIR}/footer.html
|
||||
|
||||
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
|
||||
# cascading style sheets that are included after the standard style sheets
|
||||
# created by doxygen. Using this option one can overrule certain style aspects.
|
||||
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
||||
# standard style sheet and is therefore more robust against future updates.
|
||||
# Doxygen will copy the style sheet files to the output directory.
|
||||
# Note: The order of the extra style sheet files is of importance (e.g. the last
|
||||
# style sheet in the list overrules the setting of the previous ones in the
|
||||
# list).
|
||||
# Note: Since the styling of scrollbars can currently not be overruled in
|
||||
# Webkit/Chromium, the styling will be left out of the default doxygen.css if
|
||||
# one or more extra stylesheets have been specified. So if scrollbar
|
||||
# customization is desired it has to be added explicitly. For an example see the
|
||||
# documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_STYLESHEET = ${CGAL_DOC_RESOURCE_DIR}/cgal_stylesheet.css
|
||||
|
||||
# If you want full control over the layout of the generated HTML pages it might
|
||||
# be necessary to disable the index and replace it with your own. The
|
||||
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
|
||||
|
|
|
|||
|
|
@ -32,4 +32,14 @@ MathJax.Hub.Config(
|
|||
}
|
||||
}
|
||||
);
|
||||
MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
|
||||
var PARSE = MathJax.InputJax.TeX.Parse,
|
||||
TEXT = PARSE.prototype.InternalText;
|
||||
PARSE.Augment({
|
||||
InternalText: function (text,def) {
|
||||
text = text.replace(/\\/g,"");
|
||||
return TEXT.call(this,text,def);
|
||||
}
|
||||
});
|
||||
});
|
||||
//]]>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ $search
|
|||
$mathjax
|
||||
$darkmode
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
<!-- This should probably be an extrastylesheet instead of hardcoded. -->
|
||||
<link href="$relpath$../Manual/cgal_stylesheet.css" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
<script type="text/javascript" src="../Manual/search/search.js"></script>
|
||||
<!-- Manually done below. -->
|
||||
<link href="$relpath^../Manual/$stylesheet" rel="stylesheet" type="text/css" />
|
||||
<!-- This should probably be an extrastylesheet instead of hardcoded. -->
|
||||
<link href="$relpath$../Manual/cgal_stylesheet.css" rel="stylesheet" type="text/css" />
|
||||
$mathjax
|
||||
$darkmode
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import codecs
|
||||
import re
|
||||
|
|
@ -28,16 +28,10 @@ def main(argv):
|
|||
for l in pkgdesc:
|
||||
do_print = do_print or re.match(".*cgalPkgDescriptionBegin.*", l)
|
||||
if(do_print):
|
||||
if hasattr(sys.stdout, 'buffer'):
|
||||
sys.stdout.buffer.write(l.encode('utf-8')) #python3
|
||||
else:
|
||||
sys.stdout.write(l.encode('utf-8')) #python2
|
||||
sys.stdout.buffer.write(l.encode('utf-8'))
|
||||
do_print = do_print and (not re.match(".*cgalPkgDescriptionEnd.*", l))
|
||||
else:
|
||||
if hasattr(sys.stdout, 'buffer'):
|
||||
sys.stdout.buffer.write(line.encode('utf-8')) #python3
|
||||
else:
|
||||
sys.stdout.write(line.encode('utf-8')) #python2
|
||||
sys.stdout.buffer.write(line.encode('utf-8'))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
### [2D Arrangements](https://doc.cgal.org/6.1/Manual/packages.html#PkgArrangementOnSurface2)
|
||||
|
||||
- Introduces two traits decorators, namely `Arr_tracing_traits_2` and `Arr_counting_traits_2`, which can be used to extract debugging and informative metadata about the traits in use while a program is being executed.
|
||||
- Fixed the Landmark point-location strategy so that it can be applied to arrangements on a sphere.
|
||||
|
||||
## [Release 6.0.1](https://github.com/CGAL/cgal/releases/tag/v6.0.1)
|
||||
|
||||
|
|
|
|||
|
|
@ -8124,6 +8124,12 @@ public:
|
|||
bool operator()(const Kernel::Iso_cuboid_3&c,
|
||||
const Kernel::Point_3&p);
|
||||
|
||||
/*!
|
||||
returns true iff `p` lies on the bounded side of `c`.
|
||||
*/
|
||||
bool operator()(const Kernel::Circle_3& c,
|
||||
const Kernel::Point_3& p);
|
||||
|
||||
/*!
|
||||
returns true iff the line segment `ab` is inside the union of the
|
||||
bounded sides of `s1` and `s2`.
|
||||
|
|
@ -8386,6 +8392,11 @@ public:
|
|||
bool operator()(const Kernel::Iso_cuboid_3&c,
|
||||
const Kernel::Point_3&p);
|
||||
|
||||
/*!
|
||||
returns true iff `p` lies on the unbounded side of `c`.
|
||||
*/
|
||||
bool operator()(const Kernel::Circle_3&c,
|
||||
const Kernel::Point_3&p);
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ public:
|
|||
\sa `Kernel::ConstructPlane_3`
|
||||
\sa `Kernel::Equal_3`
|
||||
\sa `Kernel::HasOn_3`
|
||||
\sa `Kernel::HasOnBoundedSide_3`
|
||||
\sa `Kernel::HasOnUnboundedSide_3`
|
||||
\sa `Kernel::IsDegenerate_3`
|
||||
|
||||
*/
|
||||
|
|
@ -81,6 +83,7 @@ public:
|
|||
\sa `Kernel::ConstructDirection_2`
|
||||
\sa `Kernel::ConstructOppositeDirection_2`
|
||||
\sa `Kernel::ConstructPerpendicularDirection_2`
|
||||
\sa `Kernel::ConstructRay_2`
|
||||
\sa `Kernel::CounterclockwiseInBetween_2`
|
||||
\sa `Kernel::Equal_2`
|
||||
|
||||
|
|
@ -101,9 +104,12 @@ public:
|
|||
\cgalHasModels{CGAL::Direction_3<Kernel>}
|
||||
\cgalHasModelsEnd
|
||||
|
||||
\sa `Kernel::ConstructCircle_3`
|
||||
\sa `Kernel::ConstructDirection_3`
|
||||
\sa `Kernel::ConstructOppositeDirection_3`
|
||||
\sa `Kernel::Equal_2`
|
||||
\sa `Kernel::ConstructPlane_3`
|
||||
\sa `Kernel::ConstructRay_3`
|
||||
\sa `Kernel::Equal_3`
|
||||
|
||||
*/
|
||||
class Direction_3 {
|
||||
|
|
@ -125,9 +131,17 @@ A type representing isocuboids in three dimensions.
|
|||
|
||||
\sa `Kernel::BoundedSide_3`
|
||||
\sa `Kernel::ComputeVolume_3`
|
||||
\sa `Kernel::ComputeXmax_3`
|
||||
\sa `Kernel::ComputeXmin_3`
|
||||
\sa `Kernel::ComputeYmax_3`
|
||||
\sa `Kernel::ComputeYmin_3`
|
||||
\sa `Kernel::ComputeZmax_3`
|
||||
\sa `Kernel::ComputeZmin_3`
|
||||
\sa `Kernel::ConstructIsoCuboid_3`
|
||||
\sa `Kernel::ConstructMaxVertex_3`
|
||||
\sa `Kernel::ConstructMinVertex_3`
|
||||
\sa `Kernel::ConstructVertex_3`
|
||||
\sa `Kernel::Equal_2`
|
||||
\sa `Kernel::Equal_3`
|
||||
\sa `Kernel::HasOnBoundary_3`
|
||||
\sa `Kernel::HasOnBoundedSide_3`
|
||||
\sa `Kernel::HasOnUnboundedSide_3`
|
||||
|
|
@ -151,13 +165,15 @@ public:
|
|||
\cgalHasModelsEnd
|
||||
|
||||
\sa `Kernel::ConstructIsoRectangle_2`
|
||||
\sa `Kernel::ComputeXmin_2`
|
||||
\sa `Kernel::ComputeXmax_2`
|
||||
\sa `Kernel::ComputeYmin_2`
|
||||
\sa `Kernel::ComputeXmin_2`
|
||||
\sa `Kernel::ComputeYmax_2`
|
||||
\sa `Kernel::ComputeYmin_2`
|
||||
\sa `Kernel::BoundedSide_2`
|
||||
\sa `Kernel::ComputeArea_2`
|
||||
\sa `Kernel::ConstructIsoRectangle_2`
|
||||
\sa `Kernel::ConstructMaxVertex_2`
|
||||
\sa `Kernel::ConstructMinVertex_2`
|
||||
\sa `Kernel::ConstructVertex_2`
|
||||
\sa `Kernel::DoIntersect_2`
|
||||
\sa `Kernel::Equal_2`
|
||||
|
|
@ -185,8 +201,11 @@ public:
|
|||
\cgalHasModelsEnd
|
||||
|
||||
\sa `Kernel::CompareXAtY_2`
|
||||
\sa `Kernel::ComputeSquaredDistance_2`
|
||||
\sa `Kernel::CompareYAtX_2`
|
||||
\sa `Kernel::ComputeA_2`
|
||||
\sa `Kernel::ComputeB_2`
|
||||
\sa `Kernel::ComputeC_2`
|
||||
\sa `Kernel::ComputeSquaredDistance_2`
|
||||
\sa `Kernel::ConstructBisector_2`
|
||||
\sa `Kernel::ConstructDirection_2`
|
||||
\sa `Kernel::ConstructLine_2`
|
||||
|
|
@ -194,6 +213,7 @@ public:
|
|||
\sa `Kernel::ConstructPerpendicularLine_2`
|
||||
\sa `Kernel::ConstructPointOn_2`
|
||||
\sa `Kernel::ConstructProjectedPoint_2`
|
||||
\sa `Kernel::ConstructRay_2`
|
||||
\sa `Kernel::DoIntersect_2`
|
||||
\sa `Kernel::Equal_2`
|
||||
\sa `Kernel::HasOnNegativeSide_2`
|
||||
|
|
@ -222,6 +242,7 @@ public:
|
|||
\cgalHasModels{CGAL::Line_3<Kernel>}
|
||||
\cgalHasModelsEnd
|
||||
|
||||
\sa `Kernel::AreParallel_3`
|
||||
\sa `Kernel::ComputeSquaredDistance_3`
|
||||
\sa `Kernel::ConstructDirection_3`
|
||||
\sa `Kernel::ConstructLine_3`
|
||||
|
|
@ -230,6 +251,7 @@ public:
|
|||
\sa `Kernel::ConstructPlane_3`
|
||||
\sa `Kernel::ConstructPointOn_3`
|
||||
\sa `Kernel::ConstructProjectedPoint_3`
|
||||
\sa `Kernel::ConstructRay_3`
|
||||
\sa `Kernel::DoIntersect_3`
|
||||
\sa `Kernel::Equal_3`
|
||||
\sa `Kernel::HasOn_3`
|
||||
|
|
@ -299,18 +321,23 @@ public:
|
|||
\cgalHasModels{CGAL::Plane_3<Kernel>}
|
||||
\cgalHasModelsEnd
|
||||
|
||||
\sa `Kernel::AreParallel_3`
|
||||
\sa `Kernel::ComputeSquaredDistance_3`
|
||||
\sa `Kernel::ConstructBaseVector_3`
|
||||
\sa `Kernel::ConstructBisector_3`
|
||||
\sa `Kernel::ConstructCircle_3`
|
||||
\sa `Kernel::ConstructLiftedPoint_3`
|
||||
\sa `Kernel::ConstructOppositePlane_3`
|
||||
\sa `Kernel::ConstructOrthogonalVector_3`
|
||||
\sa `Kernel::ConstructProjectedXYPoint_2`
|
||||
\sa `Kernel::ConstructPerpendicularLine_3`
|
||||
\sa `Kernel::ConstructPerpendicularPlane_3`
|
||||
\sa `Kernel::ConstructPlane_3`
|
||||
\sa `Kernel::ConstructPointOn_3`
|
||||
\sa `Kernel::ConstructProjectedPoint_3`
|
||||
\sa `Kernel::ConstructProjectedXYPoint_2`
|
||||
\sa `Kernel::ConstructRadicalPlane_3`
|
||||
\sa `Kernel::ConstructSupportingPlane_3`
|
||||
\sa `Kernel::DoIntersect_3`
|
||||
\sa `Kernel::Equal_3`
|
||||
\sa `Kernel::HasOnNegativeSide_3`
|
||||
|
|
@ -365,6 +392,7 @@ public:
|
|||
\sa `Kernel::ConstructPoint_2`
|
||||
\sa `Kernel::ConstructProjectedPoint_2`
|
||||
\sa `Kernel::ConstructProjectedXYPoint_2`
|
||||
\sa `Kernel::ConstructRay_2`
|
||||
\sa `Kernel::ConstructTranslatedPoint_2`
|
||||
\sa `Kernel::DoIntersect_2`
|
||||
\sa `Kernel::Equal_2`
|
||||
|
|
@ -425,6 +453,7 @@ public:
|
|||
\sa `Kernel::ConstructPointOn_3`
|
||||
\sa `Kernel::ConstructPoint_3`
|
||||
\sa `Kernel::ConstructProjectedPoint_3`
|
||||
\sa `Kernel::ConstructRay_3`
|
||||
\sa `Kernel::ConstructTranslatedPoint_3`
|
||||
\sa `Kernel::CoplanarOrientation_3`
|
||||
\sa `Kernel::CoplanarSideOfBoundedCircle_3`
|
||||
|
|
@ -496,6 +525,7 @@ public:
|
|||
\cgalHasModels{CGAL::Ray_3<Kernel>}
|
||||
\cgalHasModelsEnd
|
||||
|
||||
\sa `Kernel::AreParallel_3`
|
||||
\sa `Kernel::ComputeSquaredDistance_3`
|
||||
\sa `Kernel::ConstructDirection_3`
|
||||
\sa `Kernel::ConstructLine_3`
|
||||
|
|
@ -562,6 +592,7 @@ public:
|
|||
\cgalHasModels{CGAL::Segment_3<Kernel>}
|
||||
\cgalHasModelsEnd
|
||||
|
||||
\sa `Kernel::AreParallel_3`
|
||||
\sa `Kernel::ComputeSquaredDistance_3`
|
||||
\sa `Kernel::ComputeSquaredLength_3`
|
||||
\sa `Kernel::ConstructDirection_3`
|
||||
|
|
@ -600,7 +631,7 @@ public:
|
|||
\sa `Kernel::ConstructOppositeSphere_3`
|
||||
\sa `Kernel::ConstructRadicalPlane_3`
|
||||
\sa `Kernel::ConstructSphere_3`
|
||||
\sa `Kernel::Equal_2`
|
||||
\sa `Kernel::Equal_3`
|
||||
\sa `Kernel::HasOnBoundary_3`
|
||||
\sa `Kernel::HasOnBoundedSide_3`
|
||||
\sa `Kernel::HasOnNegativeSide_3`
|
||||
|
|
@ -631,7 +662,7 @@ public:
|
|||
\sa `Kernel::ConstructCentroid_3`
|
||||
\sa `Kernel::ConstructTetrahedron_3`
|
||||
\sa `Kernel::ConstructVertex_3`
|
||||
\sa `Kernel::Equal_2`
|
||||
\sa `Kernel::Equal_3`
|
||||
\sa `Kernel::HasOnBoundary_3`
|
||||
\sa `Kernel::HasOnBoundedSide_3`
|
||||
\sa `Kernel::HasOnNegativeSide_3`
|
||||
|
|
@ -735,6 +766,7 @@ public:
|
|||
\sa `Kernel::ConstructDividedVector_2`
|
||||
\sa `Kernel::ConstructSumOfVectors_2`
|
||||
\sa `Kernel::ConstructDifferenceOfVectors_2`
|
||||
\sa `Kernel::ConstructRay_2`
|
||||
\sa `Kernel::ConstructVector_2`
|
||||
\sa `Kernel::Equal_2`
|
||||
\sa `Kernel::Orientation_2`
|
||||
|
|
@ -764,13 +796,14 @@ A type representing vectors in three dimensions.
|
|||
\sa `Kernel::ComputeY_3`
|
||||
\sa `Kernel::ComputeZ_3`
|
||||
\sa `Kernel::ConstructCrossProductVector_3`
|
||||
\sa `Kernel::ConstructDifferenceOfVectors_3`
|
||||
\sa `Kernel::ConstructDirection_3`
|
||||
\sa `Kernel::ConstructDividedVector_3`
|
||||
\sa `Kernel::ConstructOppositeVector_3`
|
||||
\sa `Kernel::ConstructOrthogonalVector_3`
|
||||
\sa `Kernel::ConstructRay_3`
|
||||
\sa `Kernel::ConstructScaledVector_3`
|
||||
\sa `Kernel::ConstructDividedVector_3`
|
||||
\sa `Kernel::ConstructSumOfVectors_3`
|
||||
\sa `Kernel::ConstructDifferenceOfVectors_3`
|
||||
\sa `Kernel::ConstructVector_3`
|
||||
\sa `Kernel::Equal_3`
|
||||
\sa `Kernel::Orientation_3`
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ get_idx_color(std::size_t idx) {
|
|||
static_cast<unsigned char>(rand.get_int(32, 192)));
|
||||
}
|
||||
|
||||
CGAL::IO::Color get_color(std::size_t idx) {
|
||||
CGAL::Random rand(static_cast<unsigned int>(idx));
|
||||
return CGAL::IO::Color(rand.get_int(32, 192), rand.get_int(32, 192), rand.get_int(32, 192));
|
||||
}
|
||||
|
||||
template<typename DS>
|
||||
void dump_intersection_edges(const DS& data, const std::string tag = std::string()) {
|
||||
|
||||
|
|
@ -110,12 +115,12 @@ void dump_2d_surface_mesh(
|
|||
using Mesh = CGAL::Surface_mesh<Point_3>;
|
||||
using Face_index = typename Mesh::Face_index;
|
||||
using Vertex_index = typename Mesh::Vertex_index;
|
||||
using Int_map = typename Mesh::template Property_map<Face_index, int>;
|
||||
using Int_map = typename Mesh::template Property_map<Face_index, unsigned char>;
|
||||
|
||||
Mesh mesh;
|
||||
Int_map red = mesh.template add_property_map<Face_index, int>("red", 0).first;
|
||||
Int_map green = mesh.template add_property_map<Face_index, int>("green", 0).first;
|
||||
Int_map blue = mesh.template add_property_map<Face_index, int>("blue", 0).first;
|
||||
Int_map red = mesh.template add_property_map<Face_index, unsigned char>("red", 0).first;
|
||||
Int_map green = mesh.template add_property_map<Face_index, unsigned char>("green", 0).first;
|
||||
Int_map blue = mesh.template add_property_map<Face_index, unsigned char>("blue", 0).first;
|
||||
|
||||
std::vector<Vertex_index> vertices;
|
||||
std::vector<Vertex_index> map_vertices;
|
||||
|
|
@ -332,7 +337,7 @@ public:
|
|||
{ }
|
||||
|
||||
void initialize(std::stringstream& stream) const {
|
||||
stream.precision(20);
|
||||
stream.precision(17);
|
||||
}
|
||||
|
||||
void export_points_2(
|
||||
|
|
@ -495,7 +500,8 @@ public:
|
|||
stream << polygon.size() << " ";
|
||||
for (std::size_t j = 0; j < polygon.size(); ++j)
|
||||
stream << i++ << " ";
|
||||
stream << get_idx_color(polygon_id) << std::endl;
|
||||
auto col = get_idx_color(polygon_id);
|
||||
stream << int(col.r()) << " " << int(col.g()) << " " << int(col.b()) << std::endl;
|
||||
++polygon_id;
|
||||
}
|
||||
save(stream, file_name + ".ply");
|
||||
|
|
@ -528,7 +534,8 @@ public:
|
|||
stream << polygon.size() << " ";
|
||||
for (std::size_t j = 0; j < polygon.size(); ++j)
|
||||
stream << i++ << " ";
|
||||
stream << get_idx_color(region_id) << std::endl;
|
||||
auto col = get_idx_color(region_id);
|
||||
stream << int(col.r()) << " " << int(col.g()) << " " << int(col.b()) << std::endl;
|
||||
}
|
||||
++region_id;
|
||||
}
|
||||
|
|
@ -700,17 +707,16 @@ private:
|
|||
const std::size_t size) const {
|
||||
|
||||
stream <<
|
||||
"ply" + std::string(_NL_) + "" <<
|
||||
"format ascii 1.0" + std::string(_NL_) + "" <<
|
||||
"element vertex " << size << "" + std::string(_NL_) + "" <<
|
||||
"property double x" + std::string(_NL_) + "" <<
|
||||
"property double y" + std::string(_NL_) + "" <<
|
||||
"property double z" + std::string(_NL_) + "" <<
|
||||
"property uchar red" + std::string(_NL_) + "" <<
|
||||
"property uchar green" + std::string(_NL_) + "" <<
|
||||
"property uchar blue" + std::string(_NL_) + "" <<
|
||||
"property uchar alpha" + std::string(_NL_) + "" <<
|
||||
"end_header" + std::string(_NL_) + "";
|
||||
"ply" << std::endl <<
|
||||
"format ascii 1.0" << std::endl <<
|
||||
"element vertex " << size << std::endl <<
|
||||
"property double x" << std::endl <<
|
||||
"property double y" << std::endl <<
|
||||
"property double z" << std::endl <<
|
||||
"property uchar red" << std::endl <<
|
||||
"property uchar green" << std::endl <<
|
||||
"property uchar blue" << std::endl <<
|
||||
"end_header" << std::endl;
|
||||
}
|
||||
|
||||
void add_ply_header_normals(
|
||||
|
|
@ -718,16 +724,16 @@ private:
|
|||
const std::size_t size) const {
|
||||
|
||||
stream <<
|
||||
"ply" + std::string(_NL_) + "" <<
|
||||
"format ascii 1.0" + std::string(_NL_) + "" <<
|
||||
"element vertex " << size << "" + std::string(_NL_) + "" <<
|
||||
"property double x" + std::string(_NL_) + "" <<
|
||||
"property double y" + std::string(_NL_) + "" <<
|
||||
"property double z" + std::string(_NL_) + "" <<
|
||||
"property double nx" + std::string(_NL_) + "" <<
|
||||
"property double ny" + std::string(_NL_) + "" <<
|
||||
"property double nz" + std::string(_NL_) + "" <<
|
||||
"end_header" + std::string(_NL_) + "";
|
||||
"ply" << std::endl <<
|
||||
"format ascii 1.0" << std::endl <<
|
||||
"element vertex " << size << std::endl <<
|
||||
"property double x" << std::endl <<
|
||||
"property double y" << std::endl <<
|
||||
"property double z" << std::endl <<
|
||||
"property double nx" << std::endl <<
|
||||
"property double ny" << std::endl <<
|
||||
"property double nz" << std::endl <<
|
||||
"end_header" << std::endl;
|
||||
}
|
||||
|
||||
void add_ply_header_normals_colors(
|
||||
|
|
@ -735,20 +741,19 @@ private:
|
|||
const std::size_t size) const {
|
||||
|
||||
stream <<
|
||||
"ply" + std::string(_NL_) + "" <<
|
||||
"format ascii 1.0" + std::string(_NL_) + "" <<
|
||||
"element vertex " << size << "" + std::string(_NL_) + "" <<
|
||||
"property double x" + std::string(_NL_) + "" <<
|
||||
"property double y" + std::string(_NL_) + "" <<
|
||||
"property double z" + std::string(_NL_) + "" <<
|
||||
"property double nx" + std::string(_NL_) + "" <<
|
||||
"property double ny" + std::string(_NL_) + "" <<
|
||||
"property double nz" + std::string(_NL_) + "" <<
|
||||
"property uchar red" + std::string(_NL_) + "" <<
|
||||
"property uchar green" + std::string(_NL_) + "" <<
|
||||
"property uchar blue" + std::string(_NL_) + "" <<
|
||||
"property uchar alpha" + std::string(_NL_) + "" <<
|
||||
"end_header" + std::string(_NL_) + "";
|
||||
"ply" << std::endl <<
|
||||
"format ascii 1.0" << std::endl <<
|
||||
"element vertex " << size << std::endl <<
|
||||
"property double x" << std::endl <<
|
||||
"property double y" << std::endl <<
|
||||
"property double z" << std::endl <<
|
||||
"property double nx" << std::endl <<
|
||||
"property double ny" << std::endl <<
|
||||
"property double nz" << std::endl <<
|
||||
"property uchar red" << std::endl <<
|
||||
"property uchar green" << std::endl <<
|
||||
"property uchar blue" << std::endl <<
|
||||
"end_header" << std::endl;
|
||||
}
|
||||
|
||||
void add_ply_header_regions(
|
||||
|
|
@ -775,19 +780,19 @@ private:
|
|||
const std::size_t num_faces) const {
|
||||
|
||||
stream <<
|
||||
"ply" + std::string(_NL_) + "" <<
|
||||
"format ascii 1.0" + std::string(_NL_) + "" <<
|
||||
"element vertex " << num_vertices << "" + std::string(_NL_) + "" <<
|
||||
"property double x" + std::string(_NL_) + "" <<
|
||||
"property double y" + std::string(_NL_) + "" <<
|
||||
"property double z" + std::string(_NL_) + "" <<
|
||||
"element face " << num_faces << "" + std::string(_NL_) + "" <<
|
||||
"property list uchar int vertex_indices" + std::string(_NL_) + "" <<
|
||||
"property uchar red" + std::string(_NL_) + "" <<
|
||||
"property uchar green" + std::string(_NL_) + "" <<
|
||||
"property uchar blue" + std::string(_NL_) + "" <<
|
||||
"property uchar alpha" + std::string(_NL_) + "" <<
|
||||
"end_header" + std::string(_NL_) + "";
|
||||
"ply" << std::endl <<
|
||||
"format ascii 1.0" << std::endl <<
|
||||
"element vertex " << num_vertices << std::endl <<
|
||||
"property double x" << std::endl <<
|
||||
"property double y" << std::endl <<
|
||||
"property double z" << std::endl <<
|
||||
"element face " << num_faces << std::endl <<
|
||||
"property list uchar int vertex_indices" << std::endl <<
|
||||
"property uchar red" << std::endl <<
|
||||
"property uchar green" << std::endl <<
|
||||
"property uchar blue" << std::endl <<
|
||||
"property uchar alpha" << std::endl <<
|
||||
"end_header" << std::endl;
|
||||
}
|
||||
|
||||
void add_ply_header_mesh_no_color(
|
||||
|
|
@ -796,15 +801,15 @@ private:
|
|||
const std::size_t num_faces) const {
|
||||
|
||||
stream <<
|
||||
"ply" + std::string(_NL_) + "" <<
|
||||
"format ascii 1.0" + std::string(_NL_) + "" <<
|
||||
"element vertex " << num_vertices << "" + std::string(_NL_) + "" <<
|
||||
"property double x" + std::string(_NL_) + "" <<
|
||||
"property double y" + std::string(_NL_) + "" <<
|
||||
"property double z" + std::string(_NL_) + "" <<
|
||||
"element face " << num_faces << "" + std::string(_NL_) + "" <<
|
||||
"property list ushort int vertex_indices" + std::string(_NL_) + "" <<
|
||||
"end_header" + std::string(_NL_) + "";
|
||||
"ply" << std::endl <<
|
||||
"format ascii 1.0" << std::endl <<
|
||||
"element vertex " << num_vertices << std::endl <<
|
||||
"property double x" << std::endl <<
|
||||
"property double y" << std::endl <<
|
||||
"property double z" << std::endl <<
|
||||
"element face " << num_faces << std::endl <<
|
||||
"property list ushort int vertex_indices" << std::endl <<
|
||||
"end_header" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1015,14 +1020,22 @@ void dump_points(const std::vector<CGAL::Epick::Point_3>& pts, const std::vector
|
|||
|
||||
template<typename DS>
|
||||
void dump_ifaces(const DS& data, const std::string tag = std::string()) {
|
||||
|
||||
using From_exact = CGAL::Cartesian_converter<typename DS::Intersection_kernel, typename DS::Kernel>;
|
||||
From_exact from_exact;
|
||||
// write all polygons into a separate ply with support plane index and iface index
|
||||
for (std::size_t sp_idx = data.number_of_support_planes(); sp_idx++;) {
|
||||
for (std::size_t sp_idx = 0; sp_idx < data.number_of_support_planes(); sp_idx++) {
|
||||
for (typename DS::IFace f : data.support_plane(sp_idx).ifaces()) {
|
||||
Saver<typename DS::Kernel> saver;
|
||||
std::vector<std::vector<typename DS::Kernel::Point_3> > pts(1);
|
||||
for (auto v : data.igraph().face(f).vertices)
|
||||
pts.back().push_back(data.igraph().point_3(v));
|
||||
saver.export_polygon_soup_3(pts, tag + "-" + std::to_string(sp_idx) + "-" + std::to_string(f));
|
||||
std::vector<CGAL::IO::Color> cols;
|
||||
cols.push_back(get_color(std::size_t(f)));
|
||||
Saver<typename DS::Kernel> saver;
|
||||
for (auto v : data.igraph().face(f).vertices) {
|
||||
typename DS::IkPoint_3 ip = data.igraph().point_3(v);
|
||||
Point_3 p = from_exact(ip);
|
||||
pts.back().push_back(p);
|
||||
}
|
||||
saver.export_polygon_soup_3(pts, cols, tag + "-" + std::to_string(sp_idx) + "-" + std::to_string(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -409,11 +409,11 @@ public:
|
|||
else
|
||||
event.face = faces.first;
|
||||
|
||||
for (std::size_t i = 0; i < sp.data().original_directions.size(); i++) {
|
||||
if (source_idx == uninitialized && sp.data().original_directions[i] > to_source)
|
||||
for (std::size_t i = 0; i < sp.data().exact_directions.size(); i++) {
|
||||
if (source_idx == uninitialized && sp.data().exact_directions[i] > to_source2)
|
||||
source_idx = i;
|
||||
|
||||
if (target_idx == uninitialized && sp.data().original_directions[i] > to_target)
|
||||
if (target_idx == uninitialized && sp.data().exact_directions[i] > to_target2)
|
||||
target_idx = i;
|
||||
}
|
||||
|
||||
|
|
@ -452,7 +452,7 @@ public:
|
|||
|
||||
// Shooting rays to find intersection with line of IEdge
|
||||
typename Intersection_kernel::Line_3 l3 = m_intersection_graph.line_3(edge);
|
||||
const typename Intersection_kernel::Line_2 l = sp.to_2d(l3);
|
||||
const typename Intersection_kernel::Line_2 l = typename Intersection_kernel::Line_2(s2, t2);
|
||||
for (std::size_t i = 0; i < num; i++) {
|
||||
std::size_t idx = (i + source_idx) % sp.data().original_directions.size();
|
||||
const auto result = CGAL::intersection(l, sp.data().original_rays[idx]);
|
||||
|
|
@ -465,8 +465,6 @@ public:
|
|||
if (CGAL::assign(p, result)) {
|
||||
IkFT l = CGAL::approximate_sqrt(sp.data().original_vectors[idx].squared_length());
|
||||
|
||||
IkFT l2 = from_exact(CGAL::approximate_sqrt((p - sp.data().original_rays[idx].point(0)).squared_length()));
|
||||
|
||||
IkFT l3 = (p - sp.data().original_rays[idx].point(0)) * sp.data().original_rays[idx].to_vector();
|
||||
time[i] = l3;
|
||||
CGAL_assertion(0 <= time[i]);
|
||||
|
|
@ -483,39 +481,39 @@ public:
|
|||
|
||||
// Source edge time
|
||||
std::size_t adjacent = (source_idx + sp.data().original_vertices.size() - 1) % sp.data().original_vertices.size();
|
||||
Vector_2 dir = sp.data().original_vertices[source_idx] - sp.data().original_vertices[adjacent];
|
||||
IkVector_2 dir = sp.data().exact_vertices[source_idx] - sp.data().exact_vertices[adjacent];
|
||||
dir = dir / CGAL::approximate_sqrt(dir * dir);
|
||||
|
||||
// Orthogonal direction matching the direction of the adjacent vertices
|
||||
dir = Vector_2(dir.y(), -dir.x());
|
||||
dir = IkVector_2(dir.y(), -dir.x());
|
||||
|
||||
// Moving speed matches the speed of adjacent vertices
|
||||
FT speed = (dir * sp.data().original_vectors[source_idx]);
|
||||
IkFT speed = (dir * sp.data().original_rays[source_idx].to_vector());
|
||||
|
||||
if (speed < 0)
|
||||
speed = -speed;
|
||||
|
||||
// Distance from edge to endpoint of iedge
|
||||
FT dist = (s - sp.data().original_vertices[source_idx]) * dir;
|
||||
IkFT dist = (s2 - sp.data().exact_vertices[source_idx]) * dir;
|
||||
|
||||
edge_time[0] = dist / speed;
|
||||
|
||||
// Target edge time
|
||||
adjacent = (target_idx + sp.data().original_vertices.size() - 1) % sp.data().original_vertices.size();
|
||||
dir = sp.data().original_vertices[target_idx] - sp.data().original_vertices[adjacent];
|
||||
adjacent = (target_idx + sp.data().exact_vertices.size() - 1) % sp.data().exact_vertices.size();
|
||||
dir = sp.data().exact_vertices[target_idx] - sp.data().exact_vertices[adjacent];
|
||||
dir = dir / CGAL::approximate_sqrt(dir * dir);
|
||||
|
||||
// Orthogonal direction matching the direction of the adjacent vertices
|
||||
dir = Vector_2(dir.y(), -dir.x());
|
||||
dir = IkVector_2(dir.y(), -dir.x());
|
||||
|
||||
// Moving speed matches the speed of adjacent vertices
|
||||
speed = (dir * sp.data().original_vectors[target_idx]);
|
||||
speed = (dir * sp.data().original_rays[target_idx].to_vector());
|
||||
|
||||
if (speed < 0)
|
||||
speed = -speed;
|
||||
|
||||
// Distance from edge to endpoint of iedge
|
||||
dist = (t - sp.data().original_vertices[target_idx]) * dir;
|
||||
dist = (t2 - sp.data().exact_vertices[target_idx]) * dir;
|
||||
|
||||
edge_time[1] = dist / speed;
|
||||
|
||||
|
|
@ -565,6 +563,7 @@ public:
|
|||
for (IEdge edge : border) {
|
||||
Face_event fe;
|
||||
IkFT t = calculate_edge_intersection_time(sp_idx, edge, fe);
|
||||
|
||||
if (t > 0) {
|
||||
queue.push(fe);
|
||||
}
|
||||
|
|
@ -912,8 +911,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void add_input_polygon( const std::size_t support_plane_idx, const std::vector<std::size_t>& input_indices, const std::vector<Point_2>& polygon) {
|
||||
std::vector< std::pair<Point_2, bool> > points;
|
||||
void add_input_polygon( const std::size_t support_plane_idx, const std::vector<std::size_t>& input_indices, const std::vector<typename Intersection_kernel::Point_2>& polygon) {
|
||||
std::vector< std::pair<typename Intersection_kernel::Point_2, bool> > points;
|
||||
points.reserve(polygon.size());
|
||||
for (const auto& point : polygon) {
|
||||
points.push_back(std::make_pair(point, true));
|
||||
|
|
@ -921,9 +920,10 @@ public:
|
|||
CGAL_assertion(points.size() == polygon.size());
|
||||
|
||||
preprocess(points);
|
||||
|
||||
sort_points_by_direction(points);
|
||||
support_plane(support_plane_idx).
|
||||
add_input_polygon(points, input_indices);
|
||||
add_input_polygon(points, input_indices);
|
||||
for (const std::size_t input_index : input_indices) {
|
||||
m_input_polygon_map[input_index] = support_plane_idx;
|
||||
m_sp2input_polygon[support_plane_idx].insert(input_index);
|
||||
|
|
@ -976,14 +976,17 @@ public:
|
|||
const auto& q = points[i].first;
|
||||
const auto& r = points[ip].first;
|
||||
|
||||
Vector_2 vec1(q, r);
|
||||
Vector_2 vec2(q, p);
|
||||
using Vector = typename CGAL::Kernel_traits<typename Pair::first_type>::type::Vector_2;
|
||||
using Direction = typename CGAL::Kernel_traits<typename Pair::first_type>::type::Direction_2;
|
||||
|
||||
Vector vec1(q, r);
|
||||
Vector vec2(q, p);
|
||||
vec1 = KSP::internal::normalize(vec1);
|
||||
vec2 = KSP::internal::normalize(vec2);
|
||||
|
||||
const Direction_2 dir1(vec1);
|
||||
const Direction_2 dir2(vec2);
|
||||
const FT angle = KSP::internal::angle_2(dir1, dir2);
|
||||
const Direction dir1(vec1);
|
||||
const Direction dir2(vec2);
|
||||
const auto angle = KSP::internal::angle_2(dir1, dir2);
|
||||
|
||||
if (angle > min_angle) polygon.push_back(points[i]);
|
||||
}
|
||||
|
|
@ -993,9 +996,10 @@ public:
|
|||
|
||||
template<typename Pair>
|
||||
void sort_points_by_direction(std::vector<Pair>& points) const {
|
||||
From_exact from_exact;
|
||||
FT x = FT(0), y = FT(0); FT num = 0;
|
||||
for (const auto& pair : points) {
|
||||
const auto& point = pair.first;
|
||||
const auto& point = from_exact(pair.first);
|
||||
x += point.x();
|
||||
y += point.y();
|
||||
num += 1;
|
||||
|
|
@ -1006,8 +1010,8 @@ public:
|
|||
|
||||
std::sort(points.begin(), points.end(),
|
||||
[&](const Pair& a, const Pair& b) -> bool {
|
||||
const Segment_2 sega(mid, a.first);
|
||||
const Segment_2 segb(mid, b.first);
|
||||
const Segment_2 sega(mid, from_exact(a.first));
|
||||
const Segment_2 segb(mid, from_exact(b.first));
|
||||
return ( Direction_2(sega) < Direction_2(segb) );
|
||||
});
|
||||
}
|
||||
|
|
@ -1395,10 +1399,9 @@ public:
|
|||
return support_plane(support_plane_idx).to_2d(point_3);
|
||||
}
|
||||
|
||||
/*
|
||||
IkPoint_2 to_2d(const std::size_t support_plane_idx, const IkPoint_3& point_3) const {
|
||||
return support_plane(support_plane_idx).to_2d(point_3);
|
||||
}*/
|
||||
}
|
||||
|
||||
Point_2 point_2(const PVertex& pvertex) const {
|
||||
return support_plane(pvertex).point_2(pvertex.second);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,13 @@ public:
|
|||
|
||||
merge_facets_connected_components();
|
||||
|
||||
/*
|
||||
if (m_parameters.debug) {
|
||||
for (std::size_t sp = 0; sp < m_data.number_of_support_planes(); sp++) {
|
||||
dump_2d_surface_mesh(m_data, sp, m_data.prefix() + "after-merge-sp" + std::to_string(sp));
|
||||
}
|
||||
}*/
|
||||
|
||||
create_volumes();
|
||||
|
||||
if (m_parameters.debug) {
|
||||
|
|
@ -336,13 +343,10 @@ private:
|
|||
}
|
||||
|
||||
// Propagate both queues if volumes on either side of the pface are not segmented.
|
||||
for (std::size_t i = 0; i < 2; i++) {
|
||||
if (volume_indices[i] != uninitialized) {
|
||||
while (!queue[i].empty()) {
|
||||
for (std::size_t i = 0; i < 2; i++)
|
||||
if (volume_indices[i] != uninitialized)
|
||||
while (!queue[i].empty())
|
||||
propagate_volume(queue[i], volume_indices[i], volumes, map_volumes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void propagate_volume(std::queue<std::pair<PFace, Oriented_side> >& queue, std::size_t volume_index, std::vector<Volume_cell>& volumes, std::map<PFace, std::pair<int, int> >& map_volumes) {
|
||||
|
|
|
|||
|
|
@ -402,7 +402,6 @@ private:
|
|||
typename Intersection_kernel::Point_2 a(sp.to_2d(m_data.point_3(m_data.source(pair.second[0]))));
|
||||
typename Intersection_kernel::Point_2 b(sp.to_2d(m_data.point_3(m_data.target(pair.second[0]))));
|
||||
typename Intersection_kernel::Line_2 exact_line(a, b);
|
||||
Line_2 l = from_exact(exact_line);
|
||||
|
||||
typename Intersection_kernel::Vector_2 ldir = exact_line.to_vector();
|
||||
ldir = (typename Intersection_kernel::FT(1.0) / CGAL::approximate_sqrt(ldir * ldir)) * ldir;
|
||||
|
|
@ -413,43 +412,38 @@ private:
|
|||
typename Intersection_kernel::FT emin = (std::numeric_limits<double>::max)();
|
||||
typename Intersection_kernel::FT emax = -(std::numeric_limits<double>::max)();
|
||||
FT min_speed = (std::numeric_limits<double>::max)(), max_speed = -(std::numeric_limits<double>::max)();
|
||||
|
||||
CGAL::Oriented_side last_side = l.oriented_side(sp.data().original_vertices.back());
|
||||
CGAL::Oriented_side last_side = exact_line.oriented_side(sp.data().exact_vertices.back());
|
||||
Point_2 minp, maxp;
|
||||
typename Intersection_kernel::Point_2 eminp, emaxp;
|
||||
|
||||
// Map polygon to line and get min&max projection
|
||||
for (std::size_t v = 0; v < sp.data().original_vertices.size(); v++) {
|
||||
const Point_2& p = sp.data().original_vertices[v];
|
||||
|
||||
CGAL::Oriented_side s = l.oriented_side(p);
|
||||
CGAL::Oriented_side s = exact_line.oriented_side(sp.data().exact_vertices[v]);
|
||||
if (last_side != s) {
|
||||
// Fetch former point to add segment.
|
||||
const Point_2& prev = sp.data().original_vertices[(v + sp.data().original_vertices.size() - 1) % sp.data().original_vertices.size()];
|
||||
auto eprev = sp.data().exact_vertices[(v + sp.data().exact_vertices.size() - 1) % sp.data().exact_vertices.size()];
|
||||
const Vector_2 edge_dir = sp.original_edge_direction((v + sp.data().original_vertices.size() - 1) % sp.data().original_vertices.size(), v);
|
||||
typename Intersection_kernel::Segment_2 seg(to_exact(prev), to_exact(p));
|
||||
|
||||
typename Intersection_kernel::Segment_2 seg(eprev, sp.data().exact_vertices[v]);
|
||||
const auto result = CGAL::intersection(seg, exact_line);
|
||||
|
||||
typename Intersection_kernel::Point_2 intersection;
|
||||
|
||||
if (result && CGAL::assign(intersection, result)) {
|
||||
typename Intersection_kernel::FT eproj = (intersection - exact_line.point()) * ldir;
|
||||
//FT proj = to_inexact(eproj);
|
||||
|
||||
if (eproj < emin) {
|
||||
eminp = intersection;
|
||||
emin = eproj;
|
||||
minp = from_exact(intersection);
|
||||
//min = proj;
|
||||
typename Intersection_kernel::FT p = dir * edge_dir;
|
||||
CGAL_assertion(p != 0);
|
||||
min_speed = CGAL::approximate_sqrt(edge_dir * edge_dir) / from_exact(p);
|
||||
FT p = dir * edge_dir;
|
||||
min_speed = CGAL::approximate_sqrt(edge_dir * edge_dir) / p;
|
||||
}
|
||||
if (emax < eproj) {
|
||||
emaxp = intersection;
|
||||
emax = eproj;
|
||||
maxp = from_exact(intersection);
|
||||
//max = proj;
|
||||
typename Intersection_kernel::FT p = dir * edge_dir;
|
||||
CGAL_assertion(p != 0);
|
||||
max_speed = CGAL::approximate_sqrt(edge_dir * edge_dir) / from_exact(p);
|
||||
}
|
||||
}
|
||||
|
|
@ -499,7 +493,7 @@ private:
|
|||
|
||||
typename Intersection_graph::Kinetic_interval& kinetic_interval = m_data.igraph().kinetic_interval(e, sp_idx);
|
||||
crossing_iedges.push_back(e);
|
||||
if (emin > s) {
|
||||
if (emin > s || std::isinf(min_speed)) {
|
||||
typename Intersection_kernel::FT bary_edge_exact = (emin - s) / (t - s);
|
||||
FT bary_edge = from_exact((emin - s) / (t - s));
|
||||
CGAL_assertion(bary_edge_exact >= 0);
|
||||
|
|
@ -511,7 +505,7 @@ private:
|
|||
kinetic_interval.push_back(std::pair<FT, FT>(0, 0));
|
||||
}
|
||||
|
||||
if (t > emax) {
|
||||
if (t > emax || std::isinf(max_speed)) {
|
||||
typename Intersection_kernel::FT bary_edge_exact = (emax - s) / (t - s);
|
||||
FT bary_edge = from_exact((emax - s) / (t - s));
|
||||
CGAL_assertion(0 <= bary_edge_exact && bary_edge_exact <= 1);
|
||||
|
|
@ -665,7 +659,7 @@ private:
|
|||
}
|
||||
|
||||
void add_input_polygons() {
|
||||
using Polygon_2 = std::vector<Point_2>;
|
||||
using Polygon_2 = std::vector<typename Intersection_kernel::Point_2>;
|
||||
using Indices = std::vector<std::size_t>;
|
||||
|
||||
std::map< std::size_t, std::pair<Polygon_2, Indices> > polygons;
|
||||
|
|
@ -689,20 +683,19 @@ private:
|
|||
}
|
||||
|
||||
template<typename PointRange>
|
||||
void convert_polygon(const std::size_t support_plane_idx, const PointRange& polygon_3, std::vector<Point_2>& polygon_2) {
|
||||
void convert_polygon(const std::size_t support_plane_idx, const PointRange& polygon_3, std::vector<typename Intersection_kernel::Point_2>& polygon_2) {
|
||||
polygon_2.clear();
|
||||
polygon_2.reserve(polygon_3.size());
|
||||
To_exact to_exact;
|
||||
for (const auto& point : polygon_3) {
|
||||
const Point_3 converted(static_cast<FT>(point.x()), static_cast<FT>(point.y()), static_cast<FT>(point.z()));
|
||||
|
||||
polygon_2.push_back(m_data.support_plane(support_plane_idx).to_2d(converted));
|
||||
polygon_2.push_back(m_data.support_plane(support_plane_idx).to_2d(to_exact(point)));
|
||||
}
|
||||
CGAL_assertion(polygon_2.size() == polygon_3.size());
|
||||
}
|
||||
|
||||
void preprocess_polygons(std::map< std::size_t, std::pair<std::vector<Point_2>, std::vector<std::size_t> > >& polygons) {
|
||||
void preprocess_polygons(std::map< std::size_t, std::pair<std::vector<typename Intersection_kernel::Point_2>, std::vector<std::size_t> > >& polygons) {
|
||||
std::size_t input_index = 0;
|
||||
std::vector<Point_2> polygon_2;
|
||||
std::vector<typename Intersection_kernel::Point_2> polygon_2;
|
||||
std::vector<std::size_t> input_indices;
|
||||
for (std::size_t i = 0; i < m_input_polygons.size(); i++) {
|
||||
bool is_added = true;
|
||||
|
|
@ -729,8 +722,8 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void merge_polygons(const std::size_t support_plane_idx, const std::vector<Point_2>& polygon_a, std::vector<Point_2>& polygon_b) {
|
||||
const bool is_debug = false;
|
||||
void merge_polygons(const std::size_t support_plane_idx, const std::vector<typename Intersection_kernel::Point_2>& polygon_a, std::vector<typename Intersection_kernel::Point_2>& polygon_b) {
|
||||
const bool is_debug = true;
|
||||
CGAL_assertion(support_plane_idx >= 6);
|
||||
if (is_debug) {
|
||||
std::cout << std::endl << "support plane idx: " << support_plane_idx << std::endl;
|
||||
|
|
@ -743,18 +736,19 @@ private:
|
|||
}
|
||||
|
||||
// Create the merged polygon.
|
||||
std::vector<Point_2> merged;
|
||||
std::vector<typename Intersection_kernel::Point_2> merged;
|
||||
create_merged_polygon(points, merged);
|
||||
|
||||
if (is_debug) {
|
||||
std::cout << "merged polygon: " << std::endl;
|
||||
From_exact from_exact;
|
||||
for (std::size_t i = 0; i < merged.size(); ++i) {
|
||||
const std::size_t ip = (i + 1) % merged.size();
|
||||
const auto& p = merged[i];
|
||||
const auto& q = merged[ip];
|
||||
std::cout << "2 " <<
|
||||
m_data.to_3d(support_plane_idx, p) << " " <<
|
||||
m_data.to_3d(support_plane_idx, q) << std::endl;
|
||||
m_data.to_3d(support_plane_idx, from_exact(p)) << " " <<
|
||||
m_data.to_3d(support_plane_idx, from_exact(q)) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -762,7 +756,7 @@ private:
|
|||
polygon_b = merged;
|
||||
}
|
||||
|
||||
void create_merged_polygon(const std::vector<Point_2>& points, std::vector<Point_2>& merged) const {
|
||||
void create_merged_polygon(const std::vector<typename Intersection_kernel::Point_2>& points, std::vector<typename Intersection_kernel::Point_2>& merged) const {
|
||||
merged.clear();
|
||||
|
||||
CGAL::convex_hull_2(points.begin(), points.end(), std::back_inserter(merged));
|
||||
|
|
|
|||
|
|
@ -119,8 +119,10 @@ public:
|
|||
|
||||
std::vector<IEdge> iedges;
|
||||
std::vector<Point_2> original_vertices;
|
||||
std::vector<typename Intersection_kernel::Point_2> exact_vertices;
|
||||
std::vector<Vector_2> original_vectors;
|
||||
std::vector<Direction_2> original_directions;
|
||||
std::vector<typename Intersection_kernel::Direction_2> exact_directions;
|
||||
std::vector<typename Intersection_kernel::Ray_2> original_rays;
|
||||
|
||||
FT distance_tolerance;
|
||||
|
|
@ -345,11 +347,12 @@ public:
|
|||
CGAL_assertion(is_valid_polygon(points));
|
||||
|
||||
To_exact to_exact;
|
||||
From_exact from_exact;
|
||||
|
||||
CGAL_assertion(points.size() >= 3);
|
||||
std::vector<Triangle_2> tris(points.size() - 2);
|
||||
for (std::size_t i = 2; i < points.size(); i++)
|
||||
tris[i - 2] = Triangle_2(points[0].first, points[i - 1].first, points[i].first);
|
||||
tris[i - 2] = Triangle_2(from_exact(points[0].first), from_exact(points[i - 1].first), from_exact(points[i].first));
|
||||
|
||||
m_data->centroid = CGAL::centroid(tris.begin(), tris.end(), CGAL::Dimension_tag<2>());
|
||||
|
||||
|
|
@ -358,22 +361,23 @@ public:
|
|||
CGAL_assertion(n >= 3);
|
||||
vertices.reserve(n);
|
||||
m_data->original_vertices.resize(n);
|
||||
m_data->exact_vertices.resize(n);
|
||||
m_data->original_vectors.resize(n);
|
||||
m_data->original_directions.resize(n);
|
||||
m_data->exact_directions.resize(n);
|
||||
m_data->original_rays.resize(n);
|
||||
|
||||
FT sum_length = FT(0);
|
||||
std::vector<Vector_2> directions;
|
||||
std::vector<typename Intersection_kernel::Vector_2> directions;
|
||||
directions.reserve(n);
|
||||
|
||||
std::vector<std::pair<std::size_t, Direction_2> > dir_vec;
|
||||
std::vector<std::pair<std::size_t, typename Intersection_kernel::Direction_2> > dir_vec;
|
||||
|
||||
FT num = 0;
|
||||
for (const auto& pair : points) {
|
||||
const auto& point = pair.first;
|
||||
directions.push_back(Vector_2(m_data->centroid, point));
|
||||
const FT length = static_cast<FT>(
|
||||
CGAL::approximate_sqrt(CGAL::abs(directions.back() * directions.back())));
|
||||
directions.push_back(typename Intersection_kernel::Vector_2(to_exact(m_data->centroid), point));
|
||||
const FT length = CGAL::sqrt(CGAL::abs(from_exact(directions.back() * directions.back())));
|
||||
sum_length += length;
|
||||
num += 1;
|
||||
}
|
||||
|
|
@ -382,21 +386,23 @@ public:
|
|||
|
||||
dir_vec.reserve(n);
|
||||
for (std::size_t i = 0; i < n; i++)
|
||||
dir_vec.push_back(std::pair<std::size_t, Direction_2>(i, directions[i]));
|
||||
dir_vec.push_back(std::pair<std::size_t, typename Intersection_kernel::Direction_2>(i, directions[i]));
|
||||
|
||||
std::sort(dir_vec.begin(), dir_vec.end(),
|
||||
[&](const std::pair<std::size_t, Direction_2>& a,
|
||||
const std::pair<std::size_t, Direction_2>& b) -> bool {
|
||||
[&](const std::pair<std::size_t, typename Intersection_kernel::Direction_2>& a,
|
||||
const std::pair<std::size_t, typename Intersection_kernel::Direction_2>& b) -> bool {
|
||||
return a.second < b.second;
|
||||
});
|
||||
|
||||
for (std::size_t i = 0; i < n; ++i) {
|
||||
const auto& point = points[dir_vec[i].first].first;
|
||||
const auto vi = m_data->mesh.add_vertex(point);
|
||||
m_data->original_vertices[i] = point;
|
||||
m_data->original_vectors[i] = directions[dir_vec[i].first] / sum_length;
|
||||
m_data->original_directions[i] = Direction_2(directions[dir_vec[i].first]);
|
||||
m_data->original_rays[i] = typename Intersection_kernel::Ray_2(to_exact(point), to_exact(m_data->original_vectors[i]));
|
||||
const auto vi = m_data->mesh.add_vertex(from_exact(point));
|
||||
m_data->original_vertices[i] = from_exact(point);
|
||||
m_data->exact_vertices[i] = point;
|
||||
m_data->original_vectors[i] = from_exact(directions[dir_vec[i].first]) / sum_length;
|
||||
m_data->original_directions[i] = Direction_2(from_exact(directions[dir_vec[i].first]));
|
||||
m_data->exact_directions[i] = dir_vec[i].second;
|
||||
m_data->original_rays[i] = typename Intersection_kernel::Ray_2(point, directions[dir_vec[i].first] / sum_length);
|
||||
m_data->v_original_map[vi] = true;
|
||||
vertices.push_back(vi);
|
||||
}
|
||||
|
|
@ -448,20 +454,22 @@ public:
|
|||
|
||||
template<typename Pair>
|
||||
bool is_simple_polygon(const std::vector<Pair>& points) const {
|
||||
From_exact from_exact;
|
||||
std::vector<Point_2> polygon;
|
||||
polygon.reserve(points.size());
|
||||
for (const auto& pair : points)
|
||||
polygon.push_back(pair.first);
|
||||
polygon.push_back(from_exact(pair.first));
|
||||
CGAL_assertion(polygon.size() == points.size());
|
||||
return CGAL::is_simple_2(polygon.begin(), polygon.end());
|
||||
}
|
||||
|
||||
template<typename Pair>
|
||||
bool is_convex_polygon(const std::vector<Pair>& points) const {
|
||||
From_exact from_exact;
|
||||
std::vector<Point_2> polygon;
|
||||
polygon.reserve(points.size());
|
||||
for (const auto& pair : points)
|
||||
polygon.push_back(pair.first);
|
||||
polygon.push_back(from_exact(pair.first));
|
||||
CGAL_assertion(polygon.size() == points.size());
|
||||
return CGAL::is_convex_2(polygon.begin(), polygon.end());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ public:
|
|||
m_input2regularized.push_back(m_input_planes.size());
|
||||
m_regularized2input.push_back(std::vector<std::size_t>());
|
||||
m_regularized2input.back().push_back(p);
|
||||
m_input_planes.push_back(to_exact(pl));
|
||||
m_input_planes.push_back(exact_pl);
|
||||
m_input_centroids.push_back(c);
|
||||
m_input_polygons.push_back(std::vector<Point_3>(ch.size()));
|
||||
|
||||
|
|
@ -491,7 +491,7 @@ public:
|
|||
m_parameters.max_octree_node_size = parameters::choose_parameter(
|
||||
parameters::get_parameter(np, internal_np::max_octree_node_size), 40);
|
||||
|
||||
std::cout.precision(20);
|
||||
std::cout.precision(17);
|
||||
if (m_input_polygons.size() == 0) {
|
||||
std::cout << "Warning: Your input is empty!";
|
||||
return;
|
||||
|
|
@ -581,12 +581,6 @@ public:
|
|||
finalization_time = 0;
|
||||
conformal_time = 0;
|
||||
|
||||
/*
|
||||
if (m_parameters.debug)
|
||||
if (boost::filesystem::is_directory("volumes/"))
|
||||
for (boost::filesystem::directory_iterator end_dir_it, it("volumes/"); it != end_dir_it; ++it)
|
||||
boost::filesystem::remove_all(it->path());*/
|
||||
|
||||
for (std::size_t idx : m_partitions) {
|
||||
Sub_partition& partition = m_partition_nodes[idx];
|
||||
timer.reset();
|
||||
|
|
@ -612,13 +606,12 @@ public:
|
|||
|
||||
// Propagation.
|
||||
Propagation propagation(*partition.m_data, m_parameters);
|
||||
std::size_t m_num_events = propagation.propagate(k);
|
||||
propagation.propagate(k);
|
||||
|
||||
partition_time += timer.time();
|
||||
|
||||
if (m_parameters.verbose) {
|
||||
std::cout << "* propagation finished" << std::endl;
|
||||
std::cout << "* number of events handled: " << m_num_events << std::endl;
|
||||
}
|
||||
|
||||
if (m_parameters.verbose) {
|
||||
|
|
@ -1274,12 +1267,12 @@ private:
|
|||
|
||||
if (pos && neg) {
|
||||
std::cout << "face is not convex" << std::endl;
|
||||
exit(1);
|
||||
CGAL_assertion(false);
|
||||
}
|
||||
|
||||
if (!pos && !neg) {
|
||||
std::cout << "face is degenerated" << std::endl;
|
||||
exit(1);
|
||||
CGAL_assertion(false);
|
||||
}
|
||||
|
||||
if (neg) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ if(Boost_FOUND)
|
|||
message(STATUS "Found Eigen")
|
||||
include(CGAL_Eigen3_support)
|
||||
|
||||
set(targets kinetic_3d_test_all)
|
||||
set(targets kinetic_3d_test_all issue_8624)
|
||||
|
||||
set(project_linked_libraries)
|
||||
set(project_compilation_definitions)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,777 @@
|
|||
OFF
|
||||
620 155 0
|
||||
868.585 442.974 10
|
||||
871.72 445.821 10
|
||||
871.72 445.821 -10
|
||||
868.585 442.974 -10
|
||||
871.138 444.964 10
|
||||
879.142 451.345 10
|
||||
879.142 451.345 -10
|
||||
871.138 444.964 -10
|
||||
878.286 450.795 10
|
||||
881.048 454.343 10
|
||||
881.048 454.343 -10
|
||||
878.286 450.795 -10
|
||||
880.519 454.396 10
|
||||
882.228 450.947 10
|
||||
882.228 450.947 -10
|
||||
880.519 454.396 -10
|
||||
886.03 449.396 10
|
||||
890.121 458.086 10
|
||||
890.121 458.086 -10
|
||||
886.03 449.396 -10
|
||||
887.322 458.699 10
|
||||
881.556 460.73 10
|
||||
881.556 460.73 -10
|
||||
887.322 458.699 -10
|
||||
882.339 460.955 10
|
||||
878.71 456.409 10
|
||||
878.71 456.409 -10
|
||||
882.339 460.955 -10
|
||||
879.495 456.639 10
|
||||
873.633 458.623 10
|
||||
873.633 458.623 -10
|
||||
879.495 456.639 -10
|
||||
872.369 457.733 10
|
||||
873.136 456.477 10
|
||||
873.136 456.477 -10
|
||||
872.369 457.733 -10
|
||||
873.329 457.114 10
|
||||
869.874 455.517 10
|
||||
869.874 455.517 -10
|
||||
873.329 457.114 -10
|
||||
867.498 452.88 10
|
||||
864.051 451.791 10
|
||||
864.051 451.791 -10
|
||||
867.498 452.88 -10
|
||||
864.938 452.277 10
|
||||
861.298 450.817 10
|
||||
861.298 450.817 -10
|
||||
864.938 452.277 -10
|
||||
852.179 454.854 10
|
||||
851.232 458.959 10
|
||||
851.232 458.959 -10
|
||||
852.179 454.854 -10
|
||||
851.176 463.954 10
|
||||
841.842 461.31 10
|
||||
841.842 461.31 -10
|
||||
851.176 463.954 -10
|
||||
842.736 456.409 10
|
||||
844.684 455.598 10
|
||||
844.684 455.598 -10
|
||||
842.736 456.409 -10
|
||||
844.552 456.166 10
|
||||
841.806 453.036 10
|
||||
841.806 453.036 -10
|
||||
844.552 456.166 -10
|
||||
840.485 445.346 10
|
||||
842.819 442.364 10
|
||||
842.819 442.364 -10
|
||||
840.485 445.346 -10
|
||||
846.529 445.694 10
|
||||
847.927 447.809 10
|
||||
847.927 447.809 -10
|
||||
846.529 445.694 -10
|
||||
847.187 447.578 10
|
||||
861.395 441.911 10
|
||||
861.395 441.911 -10
|
||||
847.187 447.578 -10
|
||||
861.718 435.388 10
|
||||
862.046 431.559 10
|
||||
862.046 431.559 -10
|
||||
861.718 435.388 -10
|
||||
861.51 431.979 10
|
||||
872.554 433.721 10
|
||||
872.554 433.721 -10
|
||||
861.51 431.979 -10
|
||||
872.226 433.171 10
|
||||
870.515 438.04 10
|
||||
870.515 438.04 -10
|
||||
872.226 433.171 -10
|
||||
871.166 437.689 10
|
||||
869.365 437.241 10
|
||||
869.365 437.241 -10
|
||||
871.166 437.689 -10
|
||||
869.925 436.867 10
|
||||
868.881 443.805 10
|
||||
868.881 443.805 -10
|
||||
869.925 436.867 -10
|
||||
897.095 457.032 10
|
||||
897.879 452.662 10
|
||||
897.879 452.662 -10
|
||||
897.095 457.032 -10
|
||||
897.997 453.609 10
|
||||
897.26 451.982 10
|
||||
897.26 451.982 -10
|
||||
897.997 453.609 -10
|
||||
897.829 452.782 10
|
||||
893.076 448.257 10
|
||||
893.076 448.257 -10
|
||||
897.829 452.782 -10
|
||||
893.505 449.097 10
|
||||
892.824 444.106 10
|
||||
892.824 444.106 -10
|
||||
893.505 449.097 -10
|
||||
892.549 444.966 10
|
||||
893.782 443.654 10
|
||||
893.782 443.654 -10
|
||||
892.549 444.966 -10
|
||||
893.088 443.663 10
|
||||
896.956 447.574 10
|
||||
896.956 447.574 -10
|
||||
893.088 443.663 -10
|
||||
896.113 447.126 10
|
||||
898.564 447.591 10
|
||||
898.564 447.591 -10
|
||||
896.113 447.126 -10
|
||||
897.956 447.984 10
|
||||
898.281 446.621 10
|
||||
898.281 446.621 -10
|
||||
897.956 447.984 -10
|
||||
897.685 446.969 10
|
||||
901.213 447.988 10
|
||||
901.213 447.988 -10
|
||||
897.685 446.969 -10
|
||||
900.108 448.061 10
|
||||
904.091 450.431 10
|
||||
904.091 450.431 -10
|
||||
900.108 448.061 -10
|
||||
874.111 467.179 10
|
||||
873.942 457.959 10
|
||||
873.942 457.959 -10
|
||||
874.111 467.179 -10
|
||||
873.484 458.637 10
|
||||
880.013 456.15 10
|
||||
880.013 456.15 -10
|
||||
873.484 458.637 -10
|
||||
879.279 455.905 10
|
||||
882.992 461.795 10
|
||||
882.992 461.795 -10
|
||||
879.279 455.905 -10
|
||||
882.783 460.876 10
|
||||
881.895 468.477 10
|
||||
881.895 468.477 -10
|
||||
882.783 460.876 -10
|
||||
882.446 468.062 10
|
||||
873.609 466.597 10
|
||||
873.609 466.597 -10
|
||||
882.446 468.062 -10
|
||||
902.925 438.952 10
|
||||
901.118 449.001 10
|
||||
901.118 449.001 -10
|
||||
902.925 438.952 -10
|
||||
901.699 448.6 10
|
||||
892.423 446.892 10
|
||||
892.423 446.892 -10
|
||||
901.699 448.6 -10
|
||||
894.032 443.388 10
|
||||
892.896 443.195 10
|
||||
892.896 443.195 -10
|
||||
894.032 443.388 -10
|
||||
893.305 443.772 10
|
||||
894.364 437.533 10
|
||||
894.364 437.533 -10
|
||||
893.305 443.772 -10
|
||||
887.964 452.307 10
|
||||
886.501 450.39 10
|
||||
886.501 450.39 -10
|
||||
887.964 452.307 -10
|
||||
886.372 451.038 10
|
||||
889.325 449.332 10
|
||||
889.325 449.332 -10
|
||||
886.372 451.038 -10
|
||||
888.416 449.736 10
|
||||
893.486 448.093 10
|
||||
893.486 448.093 -10
|
||||
888.416 449.736 -10
|
||||
892.565 448.021 10
|
||||
895.803 449.666 10
|
||||
895.803 449.666 -10
|
||||
892.565 448.021 -10
|
||||
895.528 448.97 10
|
||||
895.012 450.389 10
|
||||
895.012 450.389 -10
|
||||
895.528 448.97 -10
|
||||
894.696 449.806 10
|
||||
898.725 450.742 10
|
||||
898.725 450.742 -10
|
||||
894.696 449.806 -10
|
||||
898.318 450.135 10
|
||||
897.114 457.602 10
|
||||
897.114 457.602 -10
|
||||
898.318 450.135 -10
|
||||
897.676 457.242 10
|
||||
893.714 456.145 10
|
||||
893.714 456.145 -10
|
||||
897.676 457.242 -10
|
||||
889.625 458.651 10
|
||||
887.521 451.429 10
|
||||
887.521 451.429 -10
|
||||
889.625 458.651 -10
|
||||
842.941 456.869 10
|
||||
840.675 453.689 10
|
||||
840.675 453.689 -10
|
||||
842.941 456.869 -10
|
||||
840.505 454.293 10
|
||||
848.102 451.048 10
|
||||
848.102 451.048 -10
|
||||
840.505 454.293 -10
|
||||
847.483 450.77 10
|
||||
848.797 454.684 10
|
||||
848.797 454.684 -10
|
||||
847.483 450.77 -10
|
||||
849.106 454.034 10
|
||||
842.183 456.638 10
|
||||
842.183 456.638 -10
|
||||
849.106 454.034 -10
|
||||
880.808 468.873 10
|
||||
882.269 462.532 10
|
||||
882.269 462.532 -10
|
||||
880.808 468.873 -10
|
||||
891.45 449.017 10
|
||||
886.364 450.967 10
|
||||
886.364 450.967 -10
|
||||
891.45 449.017 -10
|
||||
845.731 452.492 10
|
||||
846.332 455.986 10
|
||||
846.332 455.986 -10
|
||||
845.731 452.492 -10
|
||||
846.745 455.535 10
|
||||
843.652 455.275 10
|
||||
843.652 455.275 -10
|
||||
846.745 455.535 -10
|
||||
844.311 455.79 10
|
||||
843.256 452.688 10
|
||||
843.256 452.688 -10
|
||||
844.311 455.79 -10
|
||||
842.919 453.198 10
|
||||
846.314 452.948 10
|
||||
846.314 452.948 -10
|
||||
842.919 453.198 -10
|
||||
901.523 459.934 10
|
||||
906.476 453.647 10
|
||||
906.476 453.647 -10
|
||||
901.523 459.934 -10
|
||||
869.438 440.281 10
|
||||
870.133 435.658 10
|
||||
870.133 435.658 -10
|
||||
869.438 440.281 -10
|
||||
870.133 435.658 10
|
||||
871.019 435.806 10
|
||||
871.019 435.806 -10
|
||||
870.133 435.658 -10
|
||||
871.019 435.806 10
|
||||
871.265 433.517 10
|
||||
871.265 433.517 -10
|
||||
871.019 435.806 -10
|
||||
871.265 433.517 10
|
||||
862.057 432.051 10
|
||||
862.057 432.051 -10
|
||||
871.265 433.517 -10
|
||||
862.057 432.051 10
|
||||
861.741 434.244 10
|
||||
861.741 434.244 -10
|
||||
862.057 432.051 -10
|
||||
861.741 434.244 10
|
||||
862.598 434.384 10
|
||||
862.598 434.384 -10
|
||||
861.741 434.244 -10
|
||||
862.598 434.384 10
|
||||
861.231 443.29 10
|
||||
861.231 443.29 -10
|
||||
862.598 434.384 -10
|
||||
861.231 443.29 10
|
||||
858.98 444.392 10
|
||||
858.98 444.392 -10
|
||||
861.231 443.29 -10
|
||||
858.98 444.392 10
|
||||
858.507 443.132 10
|
||||
858.507 443.132 -10
|
||||
858.98 444.392 -10
|
||||
858.507 443.132 10
|
||||
854.315 444.757 10
|
||||
854.315 444.757 -10
|
||||
858.507 443.132 -10
|
||||
854.315 444.757 10
|
||||
854.713 445.837 10
|
||||
854.713 445.837 -10
|
||||
854.315 444.757 -10
|
||||
854.713 445.837 10
|
||||
854.289 446.01 10
|
||||
854.289 446.01 -10
|
||||
854.713 445.837 -10
|
||||
854.289 446.01 10
|
||||
853.889 444.922 10
|
||||
853.889 444.922 -10
|
||||
854.289 446.01 -10
|
||||
853.889 444.922 10
|
||||
849.736 446.532 10
|
||||
849.736 446.532 -10
|
||||
853.889 444.922 -10
|
||||
849.736 446.532 10
|
||||
850.139 447.714 10
|
||||
850.139 447.714 -10
|
||||
849.736 446.532 -10
|
||||
850.139 447.714 10
|
||||
847.908 448.63 10
|
||||
847.908 448.63 -10
|
||||
850.139 447.714 -10
|
||||
847.908 448.63 10
|
||||
845.946 447.151 10
|
||||
845.946 447.151 -10
|
||||
847.908 448.63 -10
|
||||
845.946 447.151 10
|
||||
846.766 446.064 10
|
||||
846.766 446.064 -10
|
||||
845.946 447.151 -10
|
||||
846.766 446.064 10
|
||||
842.506 442.73 10
|
||||
842.506 442.73 -10
|
||||
846.766 446.064 -10
|
||||
842.506 442.73 10
|
||||
841.171 444.471 10
|
||||
841.171 444.471 -10
|
||||
842.506 442.73 -10
|
||||
841.171 444.471 10
|
||||
841.864 444.992 10
|
||||
841.864 444.992 -10
|
||||
841.171 444.471 -10
|
||||
841.864 444.992 10
|
||||
837.66 450.279 10
|
||||
837.66 450.279 -10
|
||||
841.864 444.992 -10
|
||||
837.66 450.279 10
|
||||
841.787 453.697 10
|
||||
841.787 453.697 -10
|
||||
837.66 450.279 -10
|
||||
841.787 453.697 10
|
||||
842.252 455.222 10
|
||||
842.252 455.222 -10
|
||||
841.787 453.697 -10
|
||||
842.252 455.222 10
|
||||
842.038 455.287 10
|
||||
842.038 455.287 -10
|
||||
842.252 455.222 -10
|
||||
842.038 455.287 10
|
||||
842.378 456.299 10
|
||||
842.378 456.299 -10
|
||||
842.038 455.287 -10
|
||||
842.378 456.299 10
|
||||
842.853 456.136 10
|
||||
842.853 456.136 -10
|
||||
842.378 456.299 -10
|
||||
842.853 456.136 10
|
||||
842.071 461.494 10
|
||||
842.071 461.494 -10
|
||||
842.853 456.136 -10
|
||||
842.071 461.494 10
|
||||
848.285 462.661 10
|
||||
848.285 462.661 -10
|
||||
842.071 461.494 -10
|
||||
848.285 462.661 10
|
||||
848.196 463.135 10
|
||||
848.196 463.135 -10
|
||||
848.285 462.661 -10
|
||||
848.196 463.135 10
|
||||
850.743 463.613 10
|
||||
850.743 463.613 -10
|
||||
848.196 463.135 -10
|
||||
850.743 463.613 10
|
||||
851.562 458.36 10
|
||||
851.562 458.36 -10
|
||||
850.743 463.613 -10
|
||||
851.562 458.36 10
|
||||
850.212 458.143 10
|
||||
850.212 458.143 -10
|
||||
851.562 458.36 -10
|
||||
850.212 458.143 10
|
||||
850.628 455.916 10
|
||||
850.628 455.916 -10
|
||||
850.212 458.143 -10
|
||||
850.628 455.916 10
|
||||
862.426 451.139 10
|
||||
862.426 451.139 -10
|
||||
850.628 455.916 -10
|
||||
862.426 451.139 10
|
||||
862.436 451.286 10
|
||||
862.436 451.286 -10
|
||||
862.426 451.139 -10
|
||||
862.436 451.286 10
|
||||
864.092 451.433 10
|
||||
864.092 451.433 -10
|
||||
862.436 451.286 -10
|
||||
864.092 451.433 10
|
||||
864.001 452.143 10
|
||||
864.001 452.143 -10
|
||||
864.092 451.433 -10
|
||||
864.001 452.143 10
|
||||
865.049 452.275 10
|
||||
865.049 452.275 -10
|
||||
864.001 452.143 -10
|
||||
865.049 452.275 10
|
||||
865.148 451.49 10
|
||||
865.148 451.49 -10
|
||||
865.049 452.275 -10
|
||||
865.148 451.49 10
|
||||
871.873 457.056 10
|
||||
871.873 457.056 -10
|
||||
865.148 451.49 -10
|
||||
871.873 457.056 10
|
||||
873.835 458.548 10
|
||||
873.835 458.548 -10
|
||||
871.873 457.056 -10
|
||||
873.835 458.548 10
|
||||
874.247 460.088 10
|
||||
874.247 460.088 -10
|
||||
873.835 458.548 -10
|
||||
874.247 460.088 10
|
||||
873.75 460.267 10
|
||||
873.75 460.267 -10
|
||||
874.247 460.088 -10
|
||||
873.75 460.267 10
|
||||
874.083 461.293 10
|
||||
874.083 461.293 -10
|
||||
873.75 460.267 -10
|
||||
874.083 461.293 10
|
||||
874.475 461.16 10
|
||||
874.475 461.16 -10
|
||||
874.083 461.293 -10
|
||||
874.475 461.16 10
|
||||
874.191 466.565 10
|
||||
874.191 466.565 -10
|
||||
874.475 461.16 -10
|
||||
874.191 466.565 10
|
||||
880.947 467.519 10
|
||||
880.947 467.519 -10
|
||||
874.191 466.565 -10
|
||||
880.947 467.519 10
|
||||
880.801 468.386 10
|
||||
880.801 468.386 -10
|
||||
880.947 467.519 -10
|
||||
880.801 468.386 10
|
||||
882.894 468.654 10
|
||||
882.894 468.654 -10
|
||||
880.801 468.386 -10
|
||||
882.894 468.654 10
|
||||
883.766 463.197 10
|
||||
883.766 463.197 -10
|
||||
882.894 468.654 -10
|
||||
883.766 463.197 10
|
||||
882.319 462.953 10
|
||||
882.319 462.953 -10
|
||||
883.766 463.197 -10
|
||||
882.319 462.953 10
|
||||
882.725 460.694 10
|
||||
882.725 460.694 -10
|
||||
882.319 462.953 -10
|
||||
882.725 460.694 10
|
||||
894.534 456.209 10
|
||||
894.534 456.209 -10
|
||||
882.725 460.694 -10
|
||||
894.534 456.209 10
|
||||
894.525 456.384 10
|
||||
894.525 456.384 -10
|
||||
894.534 456.209 -10
|
||||
894.525 456.384 10
|
||||
896.128 456.578 10
|
||||
896.128 456.578 -10
|
||||
894.525 456.384 -10
|
||||
896.128 456.578 10
|
||||
896.091 456.885 10
|
||||
896.091 456.885 -10
|
||||
896.128 456.578 -10
|
||||
896.091 456.885 10
|
||||
897.169 457.035 10
|
||||
897.169 457.035 -10
|
||||
896.091 456.885 -10
|
||||
897.169 457.035 10
|
||||
897.241 456.619 10
|
||||
897.241 456.619 -10
|
||||
897.169 457.035 -10
|
||||
897.241 456.619 10
|
||||
901.566 459.979 10
|
||||
901.566 459.979 -10
|
||||
897.241 456.619 -10
|
||||
901.566 459.979 10
|
||||
905.82 454.744 10
|
||||
905.82 454.744 -10
|
||||
901.566 459.979 -10
|
||||
905.82 454.744 10
|
||||
906.374 455.235 10
|
||||
906.374 455.235 -10
|
||||
905.82 454.744 -10
|
||||
906.374 455.235 10
|
||||
907.888 453.524 10
|
||||
907.888 453.524 -10
|
||||
906.374 455.235 -10
|
||||
907.888 453.524 10
|
||||
903.631 450.089 10
|
||||
903.631 450.089 -10
|
||||
907.888 453.524 -10
|
||||
903.631 450.089 10
|
||||
902.81 451.122 10
|
||||
902.81 451.122 -10
|
||||
903.631 450.089 -10
|
||||
902.81 451.122 10
|
||||
900.909 449.502 10
|
||||
900.909 449.502 -10
|
||||
902.81 451.122 -10
|
||||
900.909 449.502 10
|
||||
902.231 440.596 10
|
||||
902.231 440.596 -10
|
||||
900.909 449.502 -10
|
||||
902.231 440.596 10
|
||||
903.107 440.726 10
|
||||
903.107 440.726 -10
|
||||
902.231 440.596 -10
|
||||
903.107 440.726 10
|
||||
903.439 438.561 10
|
||||
903.439 438.561 -10
|
||||
903.107 440.726 -10
|
||||
903.439 438.561 10
|
||||
894.229 437.091 10
|
||||
894.229 437.091 -10
|
||||
903.439 438.561 -10
|
||||
894.229 437.091 10
|
||||
893.897 439.256 10
|
||||
893.897 439.256 -10
|
||||
894.229 437.091 -10
|
||||
893.897 439.256 10
|
||||
894.766 439.395 10
|
||||
894.766 439.395 -10
|
||||
893.897 439.256 -10
|
||||
894.766 439.395 10
|
||||
893.095 448.477 10
|
||||
893.095 448.477 -10
|
||||
894.766 439.395 -10
|
||||
893.095 448.477 10
|
||||
891.024 449.302 10
|
||||
891.024 449.302 -10
|
||||
893.095 448.477 -10
|
||||
891.024 449.302 10
|
||||
890.547 448.022 10
|
||||
890.547 448.022 -10
|
||||
891.024 449.302 -10
|
||||
890.547 448.022 10
|
||||
886.357 449.641 10
|
||||
886.357 449.641 -10
|
||||
890.547 448.022 -10
|
||||
886.357 449.641 10
|
||||
886.919 451.003 10
|
||||
886.919 451.003 -10
|
||||
886.357 449.641 -10
|
||||
886.919 451.003 10
|
||||
886.529 451.164 10
|
||||
886.529 451.164 -10
|
||||
886.919 451.003 -10
|
||||
886.529 451.164 10
|
||||
886.017 449.926 10
|
||||
886.017 449.926 -10
|
||||
886.529 451.164 -10
|
||||
886.017 449.926 10
|
||||
881.895 451.431 10
|
||||
881.895 451.431 -10
|
||||
886.017 449.926 -10
|
||||
881.895 451.431 10
|
||||
882.338 452.688 10
|
||||
882.338 452.688 -10
|
||||
881.895 451.431 -10
|
||||
882.338 452.688 10
|
||||
879.892 453.549 10
|
||||
879.892 453.549 -10
|
||||
882.338 452.688 -10
|
||||
879.892 453.549 10
|
||||
877.953 452.092 10
|
||||
877.953 452.092 -10
|
||||
879.892 453.549 -10
|
||||
877.953 452.092 10
|
||||
878.727 451.063 10
|
||||
878.727 451.063 -10
|
||||
877.953 452.092 -10
|
||||
878.727 451.063 10
|
||||
875.334 448.269 10
|
||||
875.334 448.269 -10
|
||||
878.727 451.063 -10
|
||||
875.334 448.269 10
|
||||
874.474 449.339 10
|
||||
874.474 449.339 -10
|
||||
875.334 448.269 -10
|
||||
874.474 449.339 10
|
||||
874.085 449.038 10
|
||||
874.085 449.038 -10
|
||||
874.474 449.339 -10
|
||||
874.085 449.038 10
|
||||
874.945 447.968 10
|
||||
874.945 447.968 -10
|
||||
874.085 449.038 -10
|
||||
874.945 447.968 10
|
||||
871.482 445.258 10
|
||||
871.482 445.258 -10
|
||||
874.945 447.968 -10
|
||||
871.482 445.258 10
|
||||
870.634 446.255 10
|
||||
870.634 446.255 -10
|
||||
871.482 445.258 -10
|
||||
870.634 446.255 10
|
||||
868.777 444.675 10
|
||||
868.777 444.675 -10
|
||||
870.634 446.255 -10
|
||||
868.777 444.675 10
|
||||
869.438 440.281 10
|
||||
869.438 440.281 -10
|
||||
868.777 444.675 -10
|
||||
4 0 1 2 3
|
||||
4 4 5 6 7
|
||||
4 8 9 10 11
|
||||
4 12 13 14 15
|
||||
4 16 17 18 19
|
||||
4 20 21 22 23
|
||||
4 24 25 26 27
|
||||
4 28 29 30 31
|
||||
4 32 33 34 35
|
||||
4 36 37 38 39
|
||||
4 40 41 42 43
|
||||
4 44 45 46 47
|
||||
4 48 49 50 51
|
||||
4 52 53 54 55
|
||||
4 56 57 58 59
|
||||
4 60 61 62 63
|
||||
4 64 65 66 67
|
||||
4 68 69 70 71
|
||||
4 72 73 74 75
|
||||
4 76 77 78 79
|
||||
4 80 81 82 83
|
||||
4 84 85 86 87
|
||||
4 88 89 90 91
|
||||
4 92 93 94 95
|
||||
4 96 97 98 99
|
||||
4 100 101 102 103
|
||||
4 104 105 106 107
|
||||
4 108 109 110 111
|
||||
4 112 113 114 115
|
||||
4 116 117 118 119
|
||||
4 120 121 122 123
|
||||
4 124 125 126 127
|
||||
4 128 129 130 131
|
||||
4 132 133 134 135
|
||||
4 136 137 138 139
|
||||
4 140 141 142 143
|
||||
4 144 145 146 147
|
||||
4 148 149 150 151
|
||||
4 152 153 154 155
|
||||
4 156 157 158 159
|
||||
4 160 161 162 163
|
||||
4 164 165 166 167
|
||||
4 168 169 170 171
|
||||
4 172 173 174 175
|
||||
4 176 177 178 179
|
||||
4 180 181 182 183
|
||||
4 184 185 186 187
|
||||
4 188 189 190 191
|
||||
4 192 193 194 195
|
||||
4 196 197 198 199
|
||||
4 200 201 202 203
|
||||
4 204 205 206 207
|
||||
4 208 209 210 211
|
||||
4 212 213 214 215
|
||||
4 216 217 218 219
|
||||
4 220 221 222 223
|
||||
4 224 225 226 227
|
||||
4 228 229 230 231
|
||||
4 232 233 234 235
|
||||
4 236 237 238 239
|
||||
4 240 241 242 243
|
||||
4 244 245 246 247
|
||||
4 248 249 250 251
|
||||
4 252 253 254 255
|
||||
4 256 257 258 259
|
||||
4 260 261 262 263
|
||||
4 264 265 266 267
|
||||
4 268 269 270 271
|
||||
4 272 273 274 275
|
||||
4 276 277 278 279
|
||||
4 280 281 282 283
|
||||
4 284 285 286 287
|
||||
4 288 289 290 291
|
||||
4 292 293 294 295
|
||||
4 296 297 298 299
|
||||
4 300 301 302 303
|
||||
4 304 305 306 307
|
||||
4 308 309 310 311
|
||||
4 312 313 314 315
|
||||
4 316 317 318 319
|
||||
4 320 321 322 323
|
||||
4 324 325 326 327
|
||||
4 328 329 330 331
|
||||
4 332 333 334 335
|
||||
4 336 337 338 339
|
||||
4 340 341 342 343
|
||||
4 344 345 346 347
|
||||
4 348 349 350 351
|
||||
4 352 353 354 355
|
||||
4 356 357 358 359
|
||||
4 360 361 362 363
|
||||
4 364 365 366 367
|
||||
4 368 369 370 371
|
||||
4 372 373 374 375
|
||||
4 376 377 378 379
|
||||
4 380 381 382 383
|
||||
4 384 385 386 387
|
||||
4 388 389 390 391
|
||||
4 392 393 394 395
|
||||
4 396 397 398 399
|
||||
4 400 401 402 403
|
||||
4 404 405 406 407
|
||||
4 408 409 410 411
|
||||
4 412 413 414 415
|
||||
4 416 417 418 419
|
||||
4 420 421 422 423
|
||||
4 424 425 426 427
|
||||
4 428 429 430 431
|
||||
4 432 433 434 435
|
||||
4 436 437 438 439
|
||||
4 440 441 442 443
|
||||
4 444 445 446 447
|
||||
4 448 449 450 451
|
||||
4 452 453 454 455
|
||||
4 456 457 458 459
|
||||
4 460 461 462 463
|
||||
4 464 465 466 467
|
||||
4 468 469 470 471
|
||||
4 472 473 474 475
|
||||
4 476 477 478 479
|
||||
4 480 481 482 483
|
||||
4 484 485 486 487
|
||||
4 488 489 490 491
|
||||
4 492 493 494 495
|
||||
4 496 497 498 499
|
||||
4 500 501 502 503
|
||||
4 504 505 506 507
|
||||
4 508 509 510 511
|
||||
4 512 513 514 515
|
||||
4 516 517 518 519
|
||||
4 520 521 522 523
|
||||
4 524 525 526 527
|
||||
4 528 529 530 531
|
||||
4 532 533 534 535
|
||||
4 536 537 538 539
|
||||
4 540 541 542 543
|
||||
4 544 545 546 547
|
||||
4 548 549 550 551
|
||||
4 552 553 554 555
|
||||
4 556 557 558 559
|
||||
4 560 561 562 563
|
||||
4 564 565 566 567
|
||||
4 568 569 570 571
|
||||
4 572 573 574 575
|
||||
4 576 577 578 579
|
||||
4 580 581 582 583
|
||||
4 584 585 586 587
|
||||
4 588 589 590 591
|
||||
4 592 593 594 595
|
||||
4 596 597 598 599
|
||||
4 600 601 602 603
|
||||
4 604 605 606 607
|
||||
4 608 609 610 611
|
||||
4 612 613 614 615
|
||||
4 616 617 618 619
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Kinetic_space_partition_3.h>
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/IO/polygon_soup_io.h>
|
||||
|
||||
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
|
||||
|
||||
using Kernel = EPICK;
|
||||
using FT = typename Kernel::FT;
|
||||
using Point_3 = typename Kernel::Point_3;
|
||||
|
||||
using Surface_mesh = CGAL::Surface_mesh<Point_3>;
|
||||
using KSP = CGAL::Kinetic_space_partition_3<EPICK>;
|
||||
using Timer = CGAL::Real_timer;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Reading polygons from file
|
||||
std::string input_filename = (argc > 1 ? argv[1] : "data/issue_8624.off");
|
||||
std::ifstream input_file(input_filename);
|
||||
|
||||
std::vector<Point_3> input_vertices;
|
||||
std::vector<std::vector<std::size_t> > input_faces;
|
||||
|
||||
if (CGAL::IO::read_polygon_soup(input_filename, input_vertices, input_faces)) {
|
||||
std::cout << "* reading the file: " << input_filename << "!" << std::endl;
|
||||
input_file.close();
|
||||
} else {
|
||||
std::cerr << "ERROR: can't read the file " << input_filename << "!" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::cout << "--- INPUT STATS: \n* number of polygons: " << input_faces.size() << std::endl;
|
||||
|
||||
// Parameters.
|
||||
const unsigned int k = (argc > 2 ? std::atoi(argv[2]) : 1);
|
||||
|
||||
// Initialization of Kinetic_space_partition_3 object.
|
||||
// 'debug' set to true exports intermediate results into files in the working directory.
|
||||
// The resulting volumes are exported into a volumes folder, if the folder already exists.
|
||||
KSP ksp(CGAL::parameters::verbose(true).debug(false));
|
||||
|
||||
// Providing input polygons.
|
||||
ksp.insert(input_vertices, input_faces);
|
||||
|
||||
Timer timer;
|
||||
timer.start();
|
||||
|
||||
// 'initialize' creates the intersection graph that is used for the partition.
|
||||
ksp.initialize(CGAL::parameters::bbox_dilation_ratio(1.1).reorient_bbox(false));
|
||||
|
||||
// Creating the partition with allowing up to 'k' intersections for each kinetic polygon.
|
||||
ksp.partition(k);
|
||||
|
||||
timer.stop();
|
||||
const FT time = static_cast<FT>(timer.time());
|
||||
|
||||
// Access the kinetic partition via linear cell complex.
|
||||
typedef CGAL::Linear_cell_complex_traits<3, EPECK> LCC_Traits;
|
||||
CGAL::Linear_cell_complex_for_combinatorial_map<3, 3, LCC_Traits, typename KSP::Linear_cell_complex_min_items> lcc;
|
||||
ksp.get_linear_cell_complex(lcc);
|
||||
|
||||
std::vector<unsigned int> cells = { 0, 2, 3 }, count;
|
||||
count = lcc.count_cells(cells);
|
||||
|
||||
assert(count[0] != 0);
|
||||
assert(count[2] != 0);
|
||||
assert(count[3] != 0);
|
||||
|
||||
if (count[0] == 0 || count[2] == 0 || count[3] == 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
std::cout << "For k = " << k << ":\n" << " vertices: " << count[0] << "\n faces: " << count[2] << "\n volumes: " << count[3] << std::endl;
|
||||
|
||||
std::cout << "\n3D kinetic partition created in " << time << " seconds!" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ The reconstruction is posed as an energy minimization labeling the convex volume
|
|||
<center>
|
||||
<table class="center-table" border="0">
|
||||
<tr><td>
|
||||
\f$\DeclareMathOperator*{\argmin}{arg\,min} \argmin\limits_{l \in {\{0, 1\}}^n} E(l) = (1 - \lambda) D(l) + \lambda U(l)\f$
|
||||
\f$\operatorname*{arg\,min}\limits_{l \in {\{0, 1\}}^n} E(l) = (1 - \lambda) D(l) + \lambda U(l)\f$
|
||||
|
||||
\f$D(l) = \sum\limits_{i \in C}\sum\limits_{p \in I_i}d_i(p, l_i)\f$
|
||||
|
||||
|
|
@ -156,11 +156,11 @@ Foam_box
|
|||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
444
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
6,5
|
||||
6.4
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
3,3
|
||||
3.4
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
9,8
|
||||
9.9
|
||||
<TR>
|
||||
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -172,17 +172,17 @@ Lans
|
|||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
169
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
3.334
|
||||
3.338
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
330
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
1.175
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
26,3
|
||||
27,2
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
9,4
|
||||
11,1
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
35,7
|
||||
38,4
|
||||
<TR>
|
||||
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -194,17 +194,17 @@ Meeting Room
|
|||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
777
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
29.605
|
||||
29.737
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
2.867
|
||||
2.876
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
11.819
|
||||
11.839
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
37,1
|
||||
41,4
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
93,4
|
||||
100,7
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
131,1
|
||||
142,1
|
||||
<TR>
|
||||
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -216,17 +216,17 @@ Full Thing
|
|||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
1.790
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
21.804
|
||||
21.845
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
2.655
|
||||
2.656
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
12.984
|
||||
12.980
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
8,6
|
||||
9,9
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
238,8
|
||||
279,8
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
248,2
|
||||
289,7
|
||||
<TR>
|
||||
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -246,9 +246,9 @@ Hilbert cube
|
|||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
0,6
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
10,5
|
||||
10,2
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
11,1
|
||||
10,9
|
||||
<TR>
|
||||
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -262,15 +262,15 @@ Asian Dragon
|
|||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
101.651
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
10.209
|
||||
11.158
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
34.237
|
||||
35.776
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
31,2
|
||||
31,7
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
757,5
|
||||
869,9
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
790,7
|
||||
903,5
|
||||
<TR>
|
||||
|
||||
<TD class="math" ALIGN=CENTER NOWRAP>
|
||||
|
|
@ -282,17 +282,17 @@ Building_C
|
|||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
172
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
3.432
|
||||
3.468
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
369
|
||||
370
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
1.457
|
||||
1.468
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
40,1
|
||||
41,9
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
12,3
|
||||
14,5
|
||||
<TD class="math" ALIGN=RIGHT NOWRAP>
|
||||
52,4
|
||||
56,5
|
||||
<TR>
|
||||
<TD ALIGN=LEFT NOWRAP COLSPAN=10><HR>
|
||||
</TABLE>
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ public:
|
|||
actionAutorefine->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental");
|
||||
actionNewAutorefine->setProperty("subMenuName", "Polygon Mesh Processing/Repair");
|
||||
actionAutorefineAndRMSelfIntersections->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental");
|
||||
actionRemoveNeedlesAndCaps->setProperty("subMenuName", "Polygon Mesh Processing/Repair");
|
||||
actionSnapBorders->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental");
|
||||
actionAddBbox->setProperty("subMenuName", "Polygon Mesh Processing");
|
||||
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ private Q_SLOTS:
|
|||
void onVisibilityChanged(bool) {
|
||||
if (!dock_widget->isVisible())
|
||||
return;
|
||||
std::cout << "in visibility changed" << std::endl;
|
||||
onItemIndexSelected(scene->mainSelectionIndex());
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -299,57 +299,28 @@ EOF
|
|||
}
|
||||
}
|
||||
|
||||
sub sort_pf
|
||||
{
|
||||
# MSVS first
|
||||
if($a =~ m/^MS/) {
|
||||
if($b =~ m/^MS/) {
|
||||
return $a cmp $b;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
sub sort_pf {
|
||||
my $platform_a = $a;
|
||||
my $platform_b = $b;
|
||||
my $platform = $platform_a;
|
||||
foreach (@available_platforms) {
|
||||
if (short_pfname($_) eq $a) {
|
||||
$platform = $_;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if($b =~ m/^MS/) { return 1; }
|
||||
|
||||
# g++/gcc second
|
||||
if($a =~ m/^g[c+][c+]/) {
|
||||
if($b =~ m/^g[c+][c+]/) {
|
||||
return $a cmp $b;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
$platform_a = $platform;
|
||||
$platform_b = $b;
|
||||
foreach (@available_platforms) {
|
||||
if (short_pfname($_) eq $b) {
|
||||
$platform = $_;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if($b =~ m/^g[c+][c+]/) { return 1; }
|
||||
|
||||
# Intel third
|
||||
if($a =~ m/^[iI]/) {
|
||||
if($b =~ m/^[iI]/) {
|
||||
return $a cmp $b;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if($b =~ m/^[iI]/) { return 1; }
|
||||
|
||||
# SunPro last
|
||||
if($a =~ m/^[Ss][uU[Nn]/) {
|
||||
if($b =~ m/^[Ss][uU[Nn]/) {
|
||||
return $a cmp $b;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if($b =~ m/^[Ss][uU[Nn]/) { return -1; }
|
||||
|
||||
return $a cmp $b;
|
||||
$platform_b = $platform;
|
||||
my $os_a = $platforms_info{$platform_a}->{operating_system} // '';
|
||||
my $os_b = $platforms_info{$platform_b}->{operating_system} // '';
|
||||
return $os_a cmp $os_b;
|
||||
}
|
||||
|
||||
sub parse_platform($)
|
||||
|
|
@ -399,7 +370,6 @@ sub choose_platforms()
|
|||
{
|
||||
my (%platform_index, $pf);
|
||||
# List all platforms for which there are results
|
||||
@available_platforms = list_platforms();
|
||||
my $index = 0;
|
||||
# Put all known platforms in a hash table.
|
||||
for ($index=0; $index < @known_platforms; $index += 1) {
|
||||
|
|
@ -437,37 +407,8 @@ sub choose_platforms()
|
|||
}
|
||||
}
|
||||
|
||||
sub print_platform_descriptions()
|
||||
{
|
||||
print OUTPUT <<'EOF';
|
||||
|
||||
<h2><a name="platforms">Platform Description and Summary</a></h2>
|
||||
|
||||
<table border="1" cellspacing="2" cellpadding="5" class="summary">
|
||||
<tr align="center">
|
||||
<th colspan="2">Platform Name</th>
|
||||
<th>Compiler</th>
|
||||
<th>Operating System</th>
|
||||
<th>Tester</th>
|
||||
<th class="ok">y</th>
|
||||
<th class="third_party_warning">t</th>
|
||||
<th class="warning">w</th>
|
||||
<th class="timeout">o</th>
|
||||
<th class="error">n</th>
|
||||
<th class="requirements">r</th>
|
||||
<th>DEBUG?</th>
|
||||
<th>CMake</th>
|
||||
<th>BOOST</th>
|
||||
<th>MPFR</th>
|
||||
<th>GMP</th>
|
||||
<th>QT</th>
|
||||
<th>LEDA</th>
|
||||
<th>CXXFLAGS</th>
|
||||
<th>LDFLAGS</th>
|
||||
</tr>
|
||||
EOF
|
||||
my ($platform_num, $pf)=(0);
|
||||
foreach $pf (@platforms_to_do) {
|
||||
sub read_platform_info {
|
||||
foreach my $pf (@available_platforms) {
|
||||
my $platform_info;
|
||||
if (open (PLATFORM_JSON, "<results_${pf}.json")) { ## read the json file of the platform
|
||||
local $/;
|
||||
|
|
@ -479,6 +420,7 @@ EOF
|
|||
}
|
||||
elsif (open (PLATFORM_INFO, "<results_${pf}.info")) { ## if the json file does not exist, read the old .info file
|
||||
$_ = <PLATFORM_INFO>; # CGAL_VERSION
|
||||
chomp(my $platform_name = <PLATFORM_INFO>);
|
||||
chomp(my $compiler = <PLATFORM_INFO>);
|
||||
chomp(my $operating_system = <PLATFORM_INFO>);
|
||||
chomp(my $tester_name = <PLATFORM_INFO>);
|
||||
|
|
@ -491,7 +433,7 @@ EOF
|
|||
chomp($versions_and_flags[$index] = <PLATFORM_INFO>);
|
||||
}
|
||||
$platform_info = {
|
||||
name => $pf,
|
||||
platform_name => $platform_name,
|
||||
compiler => $compiler,
|
||||
operating_system => $operating_system,
|
||||
tester_name => $tester_name,
|
||||
|
|
@ -531,11 +473,44 @@ EOF
|
|||
$platform_info->{third_party_libs} = \@tpl_list;
|
||||
$platforms_info{$pf} = $platform_info;
|
||||
}
|
||||
$platform_is_64bits{$pf} = ! ($pf =~ m/32/);
|
||||
$platform_is_optimized{$pf} = ($platform_info->{CXXFLAGS} =~ m|([-/]x?O[1-9])|);
|
||||
}
|
||||
}
|
||||
|
||||
sub print_platform_descriptions()
|
||||
{
|
||||
print OUTPUT <<'EOF';
|
||||
|
||||
<h2><a name="platforms">Platform Description and Summary</a></h2>
|
||||
|
||||
<table border="1" cellspacing="2" cellpadding="5" class="summary">
|
||||
<tr align="center">
|
||||
<th colspan="2">Platform Name</th>
|
||||
<th>Compiler</th>
|
||||
<th>Operating System</th>
|
||||
<th>Tester</th>
|
||||
<th class="ok">y</th>
|
||||
<th class="third_party_warning">t</th>
|
||||
<th class="warning">w</th>
|
||||
<th class="timeout">o</th>
|
||||
<th class="error">n</th>
|
||||
<th class="requirements">r</th>
|
||||
<th>DEBUG?</th>
|
||||
<th>CMake</th>
|
||||
<th>BOOST</th>
|
||||
<th>MPFR</th>
|
||||
<th>GMP</th>
|
||||
<th>QT</th>
|
||||
<th>LEDA</th>
|
||||
<th>CXXFLAGS</th>
|
||||
<th>LDFLAGS</th>
|
||||
</tr>
|
||||
EOF
|
||||
my $platform_num = 0;
|
||||
foreach my $pf (@platforms_to_do) {
|
||||
my $platform_info = $platforms_info{$pf};
|
||||
my $pf_num_plus_one = $platform_num + 1;
|
||||
# my $pf_short = join('_',parse_platform_2($pf));
|
||||
(my $pf_short) = ($pf =~ m/_(.*)/);
|
||||
($platform_is_64bits{$pf}) = ! ($pf =~ m/32/);
|
||||
($platform_is_optimized{$pf}) = ($platform_info->{CXXFLAGS} =~ m|([-/]x?O[1-9])|);
|
||||
my $county = $testresults[$platform_num]->{"y"};
|
||||
my $countt = $testresults[$platform_num]->{"t"};
|
||||
my $countw = $testresults[$platform_num]->{"w"};
|
||||
|
|
@ -546,7 +521,7 @@ EOF
|
|||
print OUTPUT <<~EOF;
|
||||
<tr>
|
||||
<td><a name="platform$pf_num_plus_one">$pf_num_plus_one</a></td>
|
||||
<td><a href="$release_name/Installation/TestReport_$pf.gz">$pf_short</a></td>
|
||||
<td><a href="$release_name/Installation/TestReport_$pf.gz">$platform_info->{platform_name}</a></td>
|
||||
<td>$platform_info->{compiler}</td>
|
||||
<td>$platform_info->{operating_system}</td>
|
||||
<td><a href="mailto:$platform_info->{tester_address}">$platform_info->{tester_name}</a></td>
|
||||
|
|
@ -680,6 +655,8 @@ sub main()
|
|||
# init_known_platforms();
|
||||
chdir $testresult_dir or die;
|
||||
chdir $release_name or die;
|
||||
@available_platforms = list_platforms();
|
||||
read_platform_info();
|
||||
choose_platforms();
|
||||
chdir "..";
|
||||
|
||||
|
|
@ -761,7 +738,7 @@ sub get_warnings_and_errors {
|
|||
}
|
||||
|
||||
sub create_summary_page {
|
||||
my $platform_options = join("\n", map { "<option value=\"$_\">$_</option>" } @platforms_to_do);
|
||||
my $platform_options = join("\n", map { "<option value=\"$_\">$platforms_info{$_}->{platform_name}</option>" } @platforms_to_do);
|
||||
my $test_directory;
|
||||
my @letters = ('r', 'n', 'w', 'o');
|
||||
my $letters_options = join("\n", map { "<option value=\"$_\">$_</option>" } @letters);
|
||||
|
|
@ -773,6 +750,8 @@ sub create_summary_page {
|
|||
my ($platform_num, $platform) = (0, "");
|
||||
foreach $platform (@platforms_to_do) {
|
||||
my $platform_info = $platforms_info{$platform};
|
||||
my $build_type = $platform_is_optimized{$platform} ? " - " : "YES";
|
||||
$platform_info->{debug} = $build_type;
|
||||
foreach my $test_directory (sort keys %test_directories) {
|
||||
my $result_letter = $testresults[$platform_num]->{$test_directory};
|
||||
if (defined($result_letter) && grep { $_ eq $result_letter } @letters) {
|
||||
|
|
@ -792,7 +771,7 @@ sub create_summary_page {
|
|||
release => $release_name,
|
||||
platforms => \@platforms_data,
|
||||
};
|
||||
my $json = JSON->new->allow_nonref;
|
||||
my $json = JSON->new->allow_nonref->pretty;
|
||||
my $json_text = $json->encode($final_data);
|
||||
my $fh = new IO::Compress::Gzip "$testresult_dir/$release_name/search_index.json.gz"
|
||||
or die "IO::Compress::Gzip failed: $GzipError\n";
|
||||
|
|
|
|||
|
|
@ -176,11 +176,12 @@ TABLE.result TD > a.package_name {
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: white;
|
||||
margin: 10% auto;
|
||||
margin: 3% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 60%;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ sub reformat_results($)
|
|||
open (PLATFORM_INFO,">${platform}.info") or return;
|
||||
open (PLATFORM_NEW_RESULTS,">${platform}.new_results") or return;
|
||||
my $CGAL_VERSION = "-";
|
||||
my $PLATFORM_NAME = "-";
|
||||
my $LEDA_VERSION = "-";
|
||||
my $COMPILER = "-";
|
||||
my $OS = "-";
|
||||
|
|
@ -89,6 +90,7 @@ sub reformat_results($)
|
|||
}
|
||||
if (/-- Operating system: (.*)/) {
|
||||
$OS = $1;
|
||||
$OS =~ s/"//g;
|
||||
}
|
||||
if (/^TESTER_NAME\s+(.*)$/) {
|
||||
$TESTER_NAME = $1;
|
||||
|
|
@ -154,6 +156,12 @@ sub reformat_results($)
|
|||
$TPL = "$TPL $1 $2,";
|
||||
push @third_party_libs, { name => $1, version => $2 };
|
||||
}
|
||||
if (/^CGAL_TEST_PLATFORM\s+(.*)$/) {
|
||||
$PLATFORM_NAME = "$1" if ($PLATFORM_NAME eq "-");
|
||||
}
|
||||
if (/^CGAL_SUMMARY_NAME\s+(.*)$/) {
|
||||
$PLATFORM_NAME = "$1";
|
||||
}
|
||||
NEXT: if(! ($_= <PLATFORM_RESULTS>)) {
|
||||
# should never happen!!
|
||||
last;
|
||||
|
|
@ -163,8 +171,9 @@ NEXT: if(! ($_= <PLATFORM_RESULTS>)) {
|
|||
print PLATFORM_NEW_RESULTS $_;
|
||||
}
|
||||
rename("${platform}.new_results","${platform}.txt") or die "cannot rename!";
|
||||
my $platform_info = {
|
||||
my $platform_info = {
|
||||
"cgal_version" => $CGAL_VERSION,
|
||||
"platform_name" => $PLATFORM_NAME,
|
||||
"compiler" => $COMPILER,
|
||||
"operating_system" => $OS,
|
||||
"tester_name" => $TESTER_NAME,
|
||||
|
|
@ -184,6 +193,7 @@ NEXT: if(! ($_= <PLATFORM_RESULTS>)) {
|
|||
close PLATFORM_JSON;
|
||||
print PLATFORM_INFO <<"EOF";
|
||||
$CGAL_VERSION
|
||||
$PLATFORM_NAME
|
||||
$COMPILER
|
||||
$OS
|
||||
$TESTER_NAME
|
||||
|
|
@ -197,6 +207,7 @@ $LEDA_VERSION
|
|||
$CXXFLAGS
|
||||
$LDFLAGS
|
||||
$TPL
|
||||
$PLATFORM_NAME
|
||||
EOF
|
||||
close(PLATFORM_INFO);
|
||||
close(PLATFORM_RESULTS);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ minimum_dihedral_angle(
|
|||
const typename K::Point_3& p1,
|
||||
const typename K::Point_3& p2,
|
||||
const typename K::Point_3& p3,
|
||||
K k = K())
|
||||
const K& k = K())
|
||||
{
|
||||
typedef typename K::FT FT;
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ minimum_dihedral_angle(
|
|||
const typename K::Point_3& p1,
|
||||
const typename K::Point_3& p2,
|
||||
const typename K::Point_3& p3,
|
||||
K k = K())
|
||||
const K& k = K())
|
||||
{
|
||||
typedef typename K::FT FT;
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ minimum_dihedral_angle(
|
|||
|
||||
template <typename K>
|
||||
typename K::FT
|
||||
minimum_dihedral_angle(const typename K::Tetrahedron_3& t, K k = K() )
|
||||
minimum_dihedral_angle(const typename K::Tetrahedron_3& t , const K& k = K())
|
||||
{
|
||||
return minimum_dihedral_angle(t[0],t[1],t[2],t[3],k);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#include <CGAL/Exact_integer.h>
|
||||
#include <CGAL/Filtered_extended_homogeneous.h>
|
||||
#include <CGAL/Exact_rational.h>
|
||||
#include <CGAL/Extended_cartesian.h>
|
||||
#include <CGAL/Nef_polyhedron_2.h>
|
||||
#include <cassert>
|
||||
|
||||
typedef CGAL::Exact_integer RT;
|
||||
typedef CGAL::Filtered_extended_homogeneous<RT> Extended_kernel;
|
||||
typedef CGAL::Exact_rational FT;
|
||||
typedef CGAL::Extended_cartesian<FT> Extended_kernel;
|
||||
typedef CGAL::Nef_polyhedron_2<Extended_kernel> Nef_polyhedron;
|
||||
typedef Nef_polyhedron::Point Point;
|
||||
typedef Nef_polyhedron::Line Line;
|
||||
|
|
@ -13,12 +13,12 @@ int main() {
|
|||
|
||||
Nef_polyhedron N1(Nef_polyhedron::COMPLETE);
|
||||
|
||||
Line l(2,4,2); // l : 2x + 4y + 2 = 0
|
||||
Line l(2.1,4.8,2.0); // l : 2.1x + 4.8y + 2 = 0
|
||||
Nef_polyhedron N2(l,Nef_polyhedron::INCLUDED);
|
||||
Nef_polyhedron N3 = N2.complement();
|
||||
assert(N1 == N2.join(N3));
|
||||
|
||||
Point p1(0,0), p2(10,10), p3(-20,15);
|
||||
Point p1(0.1,0.), p2(10.8,10.25), p3(-20.18,15.14);
|
||||
Point triangle[3] = { p1, p2, p3 };
|
||||
Nef_polyhedron N4(triangle, triangle+3);
|
||||
Nef_polyhedron N5 = N2.intersection(N4);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace CGAL {
|
|||
\brief Alias that specializes the `Orthtree` class to a 3D octree storing 3D points.
|
||||
|
||||
\tparam GeomTraits a model of `Kernel`
|
||||
\tparam PointRange a model of `Range` whose value type is the key type of `PointMap`
|
||||
\tparam PointRange a model of `Range` whose value type is the key type of `PointMap` and whose iterator type is a model of `RandomAccessIterator`
|
||||
\tparam PointMap a model of `ReadablePropertyMap` whose value type is `GeomTraits::Point_3`
|
||||
\tparam cubic_nodes Boolean to enforce cubic nodes
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ public:
|
|||
/// @{
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
static inline constexpr bool has_data = Orthtree_impl::has_Node_data<GeomTraits>::value;
|
||||
static inline constexpr bool supports_neighbor_search = true;// Orthtree_impl::has_Squared_distance_of_element<GeomTraits>::value;
|
||||
static inline constexpr bool supports_neighbor_search = Orthtree_impl::has_Squared_distance_of_element<GeomTraits>::value;
|
||||
#else
|
||||
static inline constexpr bool has_data = bool_value; ///< `true` if `GeomTraits` is a model of `OrthtreeTraitsWithData` and `false` otherwise.
|
||||
static inline constexpr bool supports_neighbor_search = bool_value; ///< `true` if `GeomTraits` is a model of `CollectionPartitioningOrthtreeTraits` and `false` otherwise.
|
||||
|
|
@ -385,7 +385,8 @@ public:
|
|||
\param max_depth deepest a tree is allowed to be (nodes at this depth will not be split).
|
||||
\param bucket_size maximum number of items a node is allowed to contain.
|
||||
*/
|
||||
void refine(size_t max_depth = 10, size_t bucket_size = 20) {
|
||||
template<typename Orthtree = Self>
|
||||
auto refine(size_t max_depth = 10, size_t bucket_size = 20) -> std::enable_if_t<Orthtree::has_data, void> {
|
||||
refine(Orthtrees::Maximum_depth_and_maximum_contained_elements(max_depth, bucket_size));
|
||||
}
|
||||
|
||||
|
|
@ -681,10 +682,10 @@ public:
|
|||
|
||||
\warning Nearest neighbor searches requires `GeomTraits` to be a model of `CollectionPartitioningOrthtreeTraits`.
|
||||
*/
|
||||
template<typename OutputIterator>
|
||||
template<typename OutputIterator, typename Orthtree = Self>
|
||||
auto nearest_k_neighbors(const Point& query,
|
||||
std::size_t k,
|
||||
OutputIterator output) const -> std::enable_if_t<supports_neighbor_search, OutputIterator> {
|
||||
OutputIterator output) const -> std::enable_if_t<Orthtree::supports_neighbor_search, OutputIterator> {
|
||||
Sphere query_sphere(query, (std::numeric_limits<FT>::max)());
|
||||
CGAL_precondition(k > 0);
|
||||
|
||||
|
|
@ -704,8 +705,8 @@ public:
|
|||
|
||||
\warning Nearest neighbor searches requires `GeomTraits` to be a model of `CollectionPartitioningOrthtreeTraits`.
|
||||
*/
|
||||
template<typename OutputIterator>
|
||||
auto neighbors_within_radius(const Sphere& query, OutputIterator output) const -> std::enable_if_t<supports_neighbor_search, OutputIterator> {
|
||||
template<typename OutputIterator, typename Orthtree = Self>
|
||||
auto neighbors_within_radius(const Sphere& query, OutputIterator output) const -> std::enable_if_t<Orthtree::supports_neighbor_search, OutputIterator> {
|
||||
return nearest_k_neighbors_within_radius(query, (std::numeric_limits<std::size_t>::max)(), output);
|
||||
}
|
||||
|
||||
|
|
@ -726,12 +727,12 @@ public:
|
|||
|
||||
\warning Nearest neighbor searches requires `GeomTraits` to be a model of `CollectionPartitioningOrthtreeTraits`.
|
||||
*/
|
||||
template <typename OutputIterator>
|
||||
template <typename OutputIterator, typename Orthtree = Self>
|
||||
auto nearest_k_neighbors_within_radius(
|
||||
const Sphere& query,
|
||||
std::size_t k,
|
||||
OutputIterator output
|
||||
) const -> std::enable_if_t<supports_neighbor_search, OutputIterator> {
|
||||
) const -> std::enable_if_t<Orthtree::supports_neighbor_search, OutputIterator> {
|
||||
CGAL_precondition(k > 0);
|
||||
Sphere query_sphere = query;
|
||||
|
||||
|
|
@ -1298,13 +1299,13 @@ private: // functions :
|
|||
return output;
|
||||
}
|
||||
|
||||
template <typename Result>
|
||||
template <typename Result, typename Orthtree = Self>
|
||||
auto nearest_k_neighbors_recursive(
|
||||
Sphere& search_bounds,
|
||||
Node_index node,
|
||||
std::vector<Result>& results,
|
||||
std::size_t k,
|
||||
FT epsilon = 0) const -> std::enable_if_t<supports_neighbor_search> {
|
||||
FT epsilon = 0) const -> std::enable_if_t<Orthtree::supports_neighbor_search> {
|
||||
|
||||
// Check whether the node has children
|
||||
if (is_leaf(node)) {
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ public:
|
|||
\ingroup PkgOrthtreeSplitPredicates
|
||||
\brief A class used to choose when a node should be split depending on the depth and the number of contained elements.
|
||||
|
||||
This predicate makes a note split if it contains more than a
|
||||
This predicate makes a node split if it contains more than a
|
||||
certain number of items and if its depth is lower than a certain
|
||||
limit.
|
||||
|
||||
|
|
|
|||
|
|
@ -89,11 +89,16 @@ struct Orthtree_traits_base {
|
|||
using Adjacency = int;
|
||||
/// @}
|
||||
|
||||
auto construct_point_d_object() const {
|
||||
return [](auto... Args) -> Point_d {
|
||||
std::initializer_list<FT> args_list{Args...};
|
||||
return Point_d{static_cast<int>(args_list.size()), args_list.begin(), args_list.end()};
|
||||
};
|
||||
struct Construct_point_d {
|
||||
template <typename ...Args, typename T = std::common_type_t<Args...>>
|
||||
Point_d operator()(Args ...args) {
|
||||
std::initializer_list<T> args_list{ args... };
|
||||
return Point_d{ static_cast<int>(args_list.size()), args_list.begin(), args_list.end() };
|
||||
}
|
||||
};
|
||||
|
||||
Construct_point_d construct_point_d_object() const {
|
||||
return Construct_point_d();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -115,7 +120,9 @@ struct Orthtree_traits_base<GeomTraits, 2> {
|
|||
UP
|
||||
};
|
||||
|
||||
auto construct_point_d_object() const {
|
||||
using Construct_point_d = Point_d(*)(const FT&, const FT&);
|
||||
|
||||
Construct_point_d construct_point_d_object() const {
|
||||
return [](const FT& x, const FT& y) -> Point_d {
|
||||
return {x, y};
|
||||
};
|
||||
|
|
@ -153,7 +160,9 @@ struct Orthtree_traits_base<GeomTraits, 3> {
|
|||
RIGHT_TOP_FRONT
|
||||
};
|
||||
|
||||
auto construct_point_d_object() const {
|
||||
using Construct_point_d = Point_d(*)(const FT&, const FT&, const FT&);
|
||||
|
||||
Construct_point_d construct_point_d_object() const {
|
||||
return [](const FT& x, const FT& y, const FT& z) -> Point_d {
|
||||
return {x, y, z};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -96,11 +96,15 @@ public:
|
|||
using Node_index = typename Base::Node_index;
|
||||
using Node_data_element = typename std::iterator_traits<typename PointRange::iterator>::value_type;
|
||||
|
||||
static_assert(std::is_same_v<typename std::iterator_traits<typename PointRange::iterator>::iterator_category, std::random_access_iterator_tag>);
|
||||
|
||||
Orthtree_traits_point(
|
||||
PointRange& points,
|
||||
PointMap point_map = PointMap()
|
||||
) : m_points(points), m_point_map(point_map) {}
|
||||
|
||||
using Construct_root_node_bbox = typename Self::Bbox_d(*)();
|
||||
|
||||
auto construct_root_node_bbox_object() const {
|
||||
return [&]() -> typename Self::Bbox_d {
|
||||
|
||||
|
|
@ -152,41 +156,65 @@ public:
|
|||
};
|
||||
}
|
||||
|
||||
auto construct_root_node_contents_object() const {
|
||||
return [&]() -> typename Self::Node_data {
|
||||
return {m_points.begin(), m_points.end()};
|
||||
};
|
||||
struct Construct_root_node_contents {
|
||||
PointRange& m_points;
|
||||
Construct_root_node_contents(PointRange& points) : m_points(points) {}
|
||||
typename Self::Node_data operator()() {
|
||||
return { m_points.begin(), m_points.end() };
|
||||
}
|
||||
};
|
||||
|
||||
Construct_root_node_contents construct_root_node_contents_object() const {
|
||||
return Construct_root_node_contents(m_points);
|
||||
}
|
||||
|
||||
auto distribute_node_contents_object() const {
|
||||
return [&](Node_index n, Tree& tree, const typename Self::Point_d& center) {
|
||||
struct Distribute_node_contents {
|
||||
const PointMap m_point_map;
|
||||
Distribute_node_contents(const PointMap& point_map) : m_point_map(point_map) {}
|
||||
void operator()(Node_index n, Tree& tree, const typename Self::Point_d& center) {
|
||||
CGAL_precondition(!tree.is_leaf(n));
|
||||
reassign_points(tree, m_point_map, n, center, tree.data(n));
|
||||
};
|
||||
};
|
||||
|
||||
Distribute_node_contents distribute_node_contents_object() const {
|
||||
return Distribute_node_contents(m_point_map);
|
||||
}
|
||||
|
||||
auto construct_sphere_d_object() const {
|
||||
using Construct_sphere_d = typename Self::Sphere_d(*)(const typename Self::Point_d&, const typename Self::FT&);
|
||||
|
||||
Construct_sphere_d construct_sphere_d_object() const {
|
||||
return [](const typename Self::Point_d& center, const typename Self::FT& squared_radius) -> typename Self::Sphere_d {
|
||||
return typename Self::Sphere_d(center, squared_radius);
|
||||
};
|
||||
}
|
||||
|
||||
auto construct_center_d_object() const {
|
||||
using Construct_center_d = typename Self::Point_d(*)(const typename Self::Sphere_d&);
|
||||
|
||||
Construct_center_d construct_center_d_object() const {
|
||||
return [](const typename Self::Sphere_d& sphere) -> typename Self::Point_d {
|
||||
return sphere.center();
|
||||
};
|
||||
}
|
||||
|
||||
auto compute_squared_radius_d_object() const {
|
||||
using Compute_squared_radius_d = typename Self::FT(*)(const typename Self::Sphere_d&);
|
||||
|
||||
Compute_squared_radius_d compute_squared_radius_d_object() const {
|
||||
return [](const typename Self::Sphere_d& sphere) -> typename Self::FT {
|
||||
return sphere.squared_radius();
|
||||
};
|
||||
}
|
||||
|
||||
auto squared_distance_of_element_object() const {
|
||||
return [&](const Node_data_element& index, const typename Self::Point_d& point) -> typename Self::FT {
|
||||
struct Squared_distance_of_element {
|
||||
const PointMap m_point_map;
|
||||
Squared_distance_of_element(const PointMap& point_map) : m_point_map(point_map) {}
|
||||
typename Self::FT operator()(const Node_data_element& index, const typename Self::Point_d& point) {
|
||||
return CGAL::squared_distance(get(m_point_map, index), point);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Squared_distance_of_element squared_distance_of_element_object() const {
|
||||
return Squared_distance_of_element(m_point_map);
|
||||
}
|
||||
|
||||
PointRange& m_points;
|
||||
|
|
|
|||
|
|
@ -236,11 +236,19 @@ C3t3 make_mesh(const Labeling_function& labeling_function, const Iso_cuboid& can
|
|||
{
|
||||
Periodic_mesh_domain domain(labeling_function, canonical_cube);
|
||||
|
||||
#ifdef CGAL_NDEBUG
|
||||
Periodic_mesh_criteria criteria(facet_angle = 30.,
|
||||
facet_size = 0.03 * 2 /*domain's edge length*/,
|
||||
facet_distance = 0.03 * 2 /*domain's edge length*/,
|
||||
cell_radius_edge_ratio = 2.,
|
||||
cell_size = 0.05);
|
||||
#else
|
||||
Periodic_mesh_criteria criteria(facet_angle = 30.,
|
||||
facet_size = 0.1 * 2 /*domain's edge length*/,
|
||||
facet_distance = 0.1 * 2 /*domain's edge length*/,
|
||||
cell_radius_edge_ratio = 2.,
|
||||
cell_size = 0.1);
|
||||
#endif
|
||||
|
||||
return CGAL::make_periodic_3_mesh_3<C3t3>(domain, criteria);
|
||||
}
|
||||
|
|
@ -313,7 +321,6 @@ int main(int, char**)
|
|||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "EXIT SUCCESS" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -544,7 +544,7 @@ public:
|
|||
typedef CGAL::Periodic_3_regular_triangulation_remove_traits_3< Gt > P3removeT;
|
||||
typedef CGAL::Regular_triangulation_3< P3removeT > Euclidean_triangulation;
|
||||
typedef Vertex_remover< Euclidean_triangulation > Remover;
|
||||
P3removeT remove_traits(domain());
|
||||
P3removeT remove_traits(geom_traits());
|
||||
Euclidean_triangulation tmp(remove_traits);
|
||||
Remover remover(this, tmp);
|
||||
Conflict_tester ct(this);
|
||||
|
|
@ -576,7 +576,7 @@ public:
|
|||
typedef CGAL::Regular_triangulation_3< P3removeT > Euclidean_triangulation;
|
||||
typedef Vertex_remover< Euclidean_triangulation > Remover;
|
||||
|
||||
P3removeT remove_traits(domain());
|
||||
P3removeT remove_traits(geom_traits());
|
||||
Euclidean_triangulation tmp(remove_traits);
|
||||
Remover remover(this, tmp);
|
||||
Cover_manager cover_manager(*this);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
\example Polygon_mesh_processing/refine_fair_example.cpp
|
||||
\example Polygon_mesh_processing/mesh_slicer_example.cpp
|
||||
\example Polygon_mesh_processing/isotropic_remeshing_example.cpp
|
||||
\example Polygon_mesh_processing/isotropic_remeshing_of_patch_example.cpp
|
||||
\example Polygon_mesh_processing/isotropic_remeshing_with_allow_move.cpp
|
||||
\example Polygon_mesh_processing/isotropic_remeshing_with_custom_sizing_example.cpp
|
||||
\example Polygon_mesh_processing/isotropic_remeshing_with_sizing_example.cpp
|
||||
\example Polygon_mesh_processing/interpolated_corrected_curvatures_SM.cpp
|
||||
\example Polygon_mesh_processing/interpolated_corrected_curvatures_PH.cpp
|
||||
\example Polygon_mesh_processing/interpolated_corrected_curvatures_vertex.cpp
|
||||
|
|
@ -48,5 +52,4 @@
|
|||
\example Polygon_mesh_processing/remesh_almost_planar_patches.cpp
|
||||
\example Polygon_mesh_processing/sample_example.cpp
|
||||
\example Polygon_mesh_processing/soup_autorefinement.cpp
|
||||
\example Polygon_mesh_processing/isotropic_remeshing_with_allow_move.cpp
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1091,6 +1091,10 @@ public:
|
|||
boost::dynamic_bitset<> coplanar_patches_of_tm2_for_union_and_intersection(nb_patches_tm2,false);
|
||||
patch_status_not_set_tm1.set();
|
||||
patch_status_not_set_tm2.set();
|
||||
// extra containers used when entire connected components are identical (filled only if needed)
|
||||
std::vector<std::size_t> coplanar_tm1_to_coplanar_tm2;
|
||||
std::vector<vertex_descriptor> extreme_vertex_per_cc_1;
|
||||
std::vector<vertex_descriptor> extreme_vertex_per_cc_2;
|
||||
|
||||
// first set coplanar status of patches using the coplanar faces collected during the
|
||||
// extra intersection edges collected. This is important in the case of full connected components
|
||||
|
|
@ -1847,8 +1851,61 @@ public:
|
|||
{
|
||||
if (coplanar_patches_of_tm1.test(patch_id))
|
||||
{
|
||||
if (is_tm1_inside_out == is_tm2_inside_out)
|
||||
// Two "identical" coplanar patches that are entire connected components
|
||||
// we have the correspondence between cpln patches thanks to faces in tm1_coplanar_faces and tm2_coplanar_faces
|
||||
CGAL_assertion(tm1_coplanar_faces.size()==tm2_coplanar_faces.size());
|
||||
if (coplanar_tm1_to_coplanar_tm2.empty()) // fill container only once
|
||||
{
|
||||
coplanar_tm1_to_coplanar_tm2.resize(nb_patches_tm1, NID);
|
||||
for (std::size_t i=0; i<tm1_coplanar_faces.size(); ++i)
|
||||
{
|
||||
std::size_t pid1 = tm1_patch_ids[get(fids1, tm1_coplanar_faces[i])];
|
||||
std::size_t pid2 = tm2_patch_ids[get(fids2, tm2_coplanar_faces[i])];
|
||||
coplanar_tm1_to_coplanar_tm2[pid1]=pid2;
|
||||
}
|
||||
|
||||
const vertex_descriptor null_v = boost::graph_traits<TriangleMesh>::null_vertex();
|
||||
extreme_vertex_per_cc_1.assign(nb_patches_tm1, null_v);
|
||||
for (face_descriptor fd : faces(tm1))
|
||||
{
|
||||
std::size_t patch_id = tm1_patch_ids[get(fids1, fd)];
|
||||
if (!coplanar_patches_of_tm1.test(patch_id)) continue;
|
||||
halfedge_descriptor hd=halfedge(fd, tm1);
|
||||
for (halfedge_descriptor h : CGAL::halfedges_around_face(hd, tm1))
|
||||
{
|
||||
vertex_descriptor vd = target(h, tm1);
|
||||
if (extreme_vertex_per_cc_1[patch_id]==null_v || get(vpm1,extreme_vertex_per_cc_1[patch_id])<get(vpm1,vd))
|
||||
extreme_vertex_per_cc_1[patch_id]=vd;
|
||||
}
|
||||
}
|
||||
|
||||
extreme_vertex_per_cc_2.assign(nb_patches_tm2, null_v);
|
||||
for (face_descriptor fd : faces(tm2))
|
||||
{
|
||||
std::size_t patch_id = tm2_patch_ids[get(fids2, fd)];
|
||||
if (!coplanar_patches_of_tm2.test(patch_id)) continue;
|
||||
halfedge_descriptor hd=halfedge(fd, tm2);
|
||||
for (halfedge_descriptor h : CGAL::halfedges_around_face(hd, tm2))
|
||||
{
|
||||
vertex_descriptor vd = target(h, tm2);
|
||||
if (extreme_vertex_per_cc_2[patch_id]==null_v || get(vpm2,extreme_vertex_per_cc_2[patch_id])<get(vpm2,vd))
|
||||
extreme_vertex_per_cc_2[patch_id]=vd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t patch_id2=coplanar_tm1_to_coplanar_tm2[patch_id];
|
||||
CGAL_assertion(patch_id2!=NID);
|
||||
|
||||
bool is_oo_tm1 = ::CGAL::Polygon_mesh_processing::internal::is_outward_oriented(extreme_vertex_per_cc_1[patch_id], tm1, parameters::vertex_point_map(vpm1)),
|
||||
is_oo_tm2 = ::CGAL::Polygon_mesh_processing::internal::is_outward_oriented(extreme_vertex_per_cc_2[patch_id2], tm2, parameters::vertex_point_map(vpm2));
|
||||
|
||||
if (is_oo_tm1==is_oo_tm2)
|
||||
{
|
||||
coplanar_patches_of_tm1_for_union_and_intersection.set(patch_id);
|
||||
coplanar_patches_of_tm2_for_union_and_intersection.set(patch_id2);
|
||||
patch_status_not_set_tm2.reset( patch_id2 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -642,6 +642,8 @@ class Intersection_of_triangle_meshes
|
|||
{
|
||||
if(is_new_node)
|
||||
visitor.new_node_added(node_id,ON_FACE,v_1,f_2,tm1,tm2,true,false);
|
||||
else
|
||||
return;
|
||||
|
||||
Edge_to_faces& tm1_edge_to_tm2_faces = &tm1 <= &tm2
|
||||
? stm_edge_to_ltm_faces
|
||||
|
|
@ -677,6 +679,8 @@ class Intersection_of_triangle_meshes
|
|||
{
|
||||
if(is_new_node)
|
||||
visitor.new_node_added(node_id,ON_VERTEX,h_2,v_1,tm2,tm1,false,false);
|
||||
else
|
||||
return;
|
||||
|
||||
Edge_to_faces& tm1_edge_to_tm2_faces = &tm1 <= &tm2
|
||||
? stm_edge_to_ltm_faces
|
||||
|
|
@ -724,6 +728,8 @@ class Intersection_of_triangle_meshes
|
|||
{
|
||||
if(is_new_node)
|
||||
visitor.new_node_added(node_id,ON_VERTEX,v_2,v_1,tm2,tm1,true,false);
|
||||
else
|
||||
return;
|
||||
|
||||
Edge_to_faces& tm1_edge_to_tm2_faces = &tm1 <= &tm2
|
||||
? stm_edge_to_ltm_faces
|
||||
|
|
|
|||
|
|
@ -879,14 +879,14 @@ namespace internal {
|
|||
std::array<halfedge_descriptor, 2> r1 = internal::is_badly_shaped(
|
||||
face(he, mesh_),
|
||||
mesh_, vpmap_, vcmap_, ecmap_, gt_,
|
||||
cap_threshold, // bound on the angle: above 160 deg => cap
|
||||
4, // bound on shortest/longest edge above 4 => needle
|
||||
cap_threshold, // bound on the angle: above 160 deg => cap
|
||||
0,// collapse length threshold : not needed here
|
||||
0); // flip triangle height threshold
|
||||
|
||||
std::array<halfedge_descriptor, 2> r2 = internal::is_badly_shaped(
|
||||
face(opposite(he, mesh_), mesh_),
|
||||
mesh_, vpmap_, vcmap_, ecmap_, gt_, cap_threshold, 4, 0, 0);
|
||||
mesh_, vpmap_, vcmap_, ecmap_, gt_, 4, cap_threshold, 0, 0);
|
||||
|
||||
const bool badly_shaped = (r1[0] != boost::graph_traits<PolygonMesh>::null_halfedge()//needle
|
||||
|| r1[1] != boost::graph_traits<PolygonMesh>::null_halfedge()//cap
|
||||
|
|
@ -1036,15 +1036,7 @@ namespace internal {
|
|||
// property map of constrained vertices for relaxation
|
||||
auto vertex_constraint = [&](const vertex_descriptor v)
|
||||
{
|
||||
for (halfedge_descriptor h : halfedges_around_target(v, mesh_))
|
||||
{
|
||||
Halfedge_status s = status(h);
|
||||
if ( s == PATCH
|
||||
|| s == PATCH_BORDER
|
||||
|| status(opposite(h, mesh_)) == PATCH_BORDER)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return !is_move_allowed(v, relax_constraints);
|
||||
};
|
||||
auto constrained_vertices_pmap
|
||||
= boost::make_function_property_map<vertex_descriptor>(vertex_constraint);
|
||||
|
|
@ -1402,6 +1394,23 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool is_move_allowed(const vertex_descriptor v, const bool relax_constraints) const
|
||||
{
|
||||
if (is_constrained(v))
|
||||
return false;
|
||||
|
||||
for (halfedge_descriptor h : halfedges_around_target(v, mesh_))
|
||||
{
|
||||
if (is_on_patch(h))
|
||||
continue;
|
||||
else if (is_on_patch_border(h) && relax_constraints)
|
||||
continue;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
halfedge_descriptor next_on_patch_border(const halfedge_descriptor& h) const
|
||||
{
|
||||
CGAL_precondition(is_on_patch_border(h));
|
||||
|
|
@ -1683,6 +1692,17 @@ private:
|
|||
// else keep current status for en and eno
|
||||
}
|
||||
|
||||
void remove_border_face(const halfedge_descriptor h)
|
||||
{
|
||||
CGAL_assertion(is_border(opposite(h, mesh_), mesh_));
|
||||
for (halfedge_descriptor hf : halfedges_around_face(h, mesh_))
|
||||
{
|
||||
set_status(hf, MESH_BORDER); //only 1 or 2 of the listed halfedges
|
||||
//will survive face removal, but status will be correct
|
||||
}
|
||||
CGAL::Euler::remove_face(h, mesh_);
|
||||
}
|
||||
|
||||
template<typename Bimap, typename SizingFunction>
|
||||
bool fix_degenerate_faces(const vertex_descriptor& v,
|
||||
Bimap& short_edges,
|
||||
|
|
@ -1712,7 +1732,7 @@ private:
|
|||
|
||||
if(is_border(opposite(h, mesh_), mesh_))
|
||||
{
|
||||
CGAL::Euler::remove_face(h, mesh_);
|
||||
remove_border_face(h);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1723,7 +1743,7 @@ private:
|
|||
|
||||
if(is_border(hfo, mesh_))
|
||||
{
|
||||
CGAL::Euler::remove_face(h, mesh_);
|
||||
remove_border_face(h);
|
||||
break;
|
||||
}
|
||||
vertex_descriptor vc = target(hf, mesh_);
|
||||
|
|
|
|||
|
|
@ -51,17 +51,15 @@ namespace Polygon_mesh_processing {
|
|||
namespace internal {
|
||||
|
||||
template <typename TriangleMesh, typename VPM, typename VCM, typename ECM, typename Traits>
|
||||
std::array<typename boost::graph_traits<TriangleMesh>::halfedge_descriptor, 2>
|
||||
is_badly_shaped(const typename boost::graph_traits<TriangleMesh>::face_descriptor f,
|
||||
TriangleMesh& tmesh,
|
||||
const VPM& vpm,
|
||||
const VCM& vcm,
|
||||
const ECM& ecm,
|
||||
const Traits& gt,
|
||||
const double cap_threshold, // angle over 160° ==> cap
|
||||
const double needle_threshold, // longest edge / shortest edge over this ratio ==> needle
|
||||
const double collapse_length_threshold, // max length of edges allowed to be collapsed
|
||||
const double flip_triangle_height_threshold_squared) // max height of triangles allowed to be flipped
|
||||
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor
|
||||
is_it_a_needle(const typename boost::graph_traits<TriangleMesh>::face_descriptor f,
|
||||
TriangleMesh& tmesh,
|
||||
const VPM& vpm,
|
||||
const VCM& vcm,
|
||||
const ECM& /* ecm */, //not used because vcm is filled with end points of edges in ecm
|
||||
const Traits& gt,
|
||||
const double needle_threshold, // longest edge / shortest edge over this ratio ==> needle
|
||||
const double collapse_length_threshold) // max length of edges allowed to be collapsed
|
||||
{
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
|
|
@ -78,23 +76,70 @@ is_badly_shaped(const typename boost::graph_traits<TriangleMesh>::face_descripto
|
|||
if(collapse_length_threshold == 0 ||
|
||||
edge_length(res, tmesh, parameters::vertex_point_map(vpm).geom_traits(gt)) <= collapse_length_threshold)
|
||||
{
|
||||
return make_array(res, null_h);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
res = PMP::is_cap_triangle_face(f, tmesh, cap_threshold, parameters::vertex_point_map(vpm).geom_traits(gt));
|
||||
return null_h;
|
||||
}
|
||||
|
||||
template <typename TriangleMesh, typename VPM, typename VCM, typename ECM, typename Traits>
|
||||
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor
|
||||
is_it_a_cap(const typename boost::graph_traits<TriangleMesh>::face_descriptor f,
|
||||
TriangleMesh& tmesh,
|
||||
const VPM& vpm,
|
||||
const VCM& /* vcm */,
|
||||
const ECM& ecm,
|
||||
const Traits& gt,
|
||||
const double cap_threshold, // angle over 160° ==> cap
|
||||
const double flip_triangle_height_threshold_squared) // max height of triangles allowed to be flipped
|
||||
{
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
const halfedge_descriptor null_h = boost::graph_traits<TriangleMesh>::null_halfedge();
|
||||
|
||||
halfedge_descriptor res =
|
||||
PMP::is_cap_triangle_face(f, tmesh, cap_threshold, parameters::vertex_point_map(vpm).geom_traits(gt));
|
||||
if( res != null_h && !get(ecm, edge(res, tmesh) ) &&
|
||||
(flip_triangle_height_threshold_squared == 0 ||
|
||||
typename Traits::Compare_squared_distance_3()( get(vpm, target(next(res,tmesh), tmesh)),
|
||||
typename Traits::Line_3(get(vpm, source(res,tmesh)), get(vpm, target(res,tmesh))),
|
||||
flip_triangle_height_threshold_squared) != LARGER ))
|
||||
{
|
||||
return make_array(null_h, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
return make_array(null_h, null_h);
|
||||
return null_h;
|
||||
}
|
||||
|
||||
// This function tests both needle-ness and cap-ness
|
||||
template <typename TriangleMesh, typename VPM, typename VCM, typename ECM, typename Traits>
|
||||
std::array<typename boost::graph_traits<TriangleMesh>::halfedge_descriptor, 2>
|
||||
is_badly_shaped(const typename boost::graph_traits<TriangleMesh>::face_descriptor f,
|
||||
TriangleMesh& tmesh,
|
||||
const VPM& vpm,
|
||||
const VCM& vcm,
|
||||
const ECM& ecm,
|
||||
const Traits& gt,
|
||||
const double needle_threshold, // longest edge / shortest edge over this ratio ==> needle
|
||||
const double cap_threshold, // angle over 160° ==> cap
|
||||
const double collapse_length_threshold, // max length of edges allowed to be collapsed
|
||||
const double flip_triangle_height_threshold_squared) // max height of triangles allowed to be flipped
|
||||
{
|
||||
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
const halfedge_descriptor null_h = boost::graph_traits<TriangleMesh>::null_halfedge();
|
||||
std::array<halfedge_descriptor,2> retval = make_array(null_h, null_h);
|
||||
|
||||
retval[0] = is_it_a_needle(f, tmesh, vpm, vcm, ecm, gt, needle_threshold, collapse_length_threshold);
|
||||
retval[1] = is_it_a_cap(f, tmesh, vpm, vcm, ecm, gt, cap_threshold, flip_triangle_height_threshold_squared);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// This function tests both needle-ness and cap-ness and fills both ranges
|
||||
template <typename TriangleMesh, typename HalfedgeContainer,
|
||||
typename VPM, typename VCM, typename ECM, typename Traits>
|
||||
void collect_badly_shaped_triangles(const typename boost::graph_traits<TriangleMesh>::face_descriptor f,
|
||||
|
|
@ -112,11 +157,13 @@ void collect_badly_shaped_triangles(const typename boost::graph_traits<TriangleM
|
|||
{
|
||||
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
|
||||
std::array<halfedge_descriptor, 2> res = is_badly_shaped(f, tmesh, vpm, vcm, ecm, gt, cap_threshold,
|
||||
needle_threshold,
|
||||
const halfedge_descriptor null_h = boost::graph_traits<TriangleMesh>::null_halfedge();
|
||||
|
||||
std::array<halfedge_descriptor, 2> res = is_badly_shaped(f, tmesh, vpm, vcm, ecm, gt,
|
||||
needle_threshold, cap_threshold,
|
||||
collapse_length_threshold, flip_triangle_height_threshold_squared);
|
||||
|
||||
if(res[0] != boost::graph_traits<TriangleMesh>::null_halfedge())
|
||||
if(res[0] != null_h)
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "add new needle: " << edge(res[0], tmesh) << std::endl;
|
||||
|
|
@ -125,17 +172,15 @@ void collect_badly_shaped_triangles(const typename boost::graph_traits<TriangleM
|
|||
CGAL_assertion(!get(ecm, edge(res[0], tmesh)));
|
||||
edges_to_collapse.insert(res[0]);
|
||||
}
|
||||
else // let's not make it possible to have a face be both a cap and a needle (for now)
|
||||
|
||||
if(res[1] != null_h)
|
||||
{
|
||||
if(res[1] != boost::graph_traits<TriangleMesh>::null_halfedge())
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "add new cap: " << edge(res[1],tmesh) << std::endl;
|
||||
std::cout << "add new cap: " << edge(res[1],tmesh) << std::endl;
|
||||
#endif
|
||||
CGAL_assertion(!is_border(res[1], tmesh));
|
||||
CGAL_assertion(!get(ecm, edge(res[1], tmesh)));
|
||||
edges_to_flip.insert(res[1]);
|
||||
}
|
||||
CGAL_assertion(!is_border(res[1], tmesh));
|
||||
CGAL_assertion(!get(ecm, edge(res[1], tmesh)));
|
||||
edges_to_flip.insert(res[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -607,6 +652,8 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
typedef typename boost::graph_traits<TriangleMesh>::edge_descriptor edge_descriptor;
|
||||
typedef typename boost::graph_traits<TriangleMesh>::face_descriptor face_descriptor;
|
||||
|
||||
const halfedge_descriptor null_h = boost::graph_traits<TriangleMesh>::null_halfedge();
|
||||
|
||||
typedef Static_boolean_property_map<vertex_descriptor, false> Default_VCM;
|
||||
typedef typename internal_np::Lookup_named_param_def<internal_np::vertex_is_constrained_t,
|
||||
NamedParameters,
|
||||
|
|
@ -654,6 +701,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
CGAL_precondition(is_valid_polygon_mesh(tmesh));
|
||||
CGAL_precondition(is_triangle_mesh(tmesh));
|
||||
|
||||
// constrain extremities of constrained edges
|
||||
for(face_descriptor f : face_range)
|
||||
{
|
||||
if(f == boost::graph_traits<TriangleMesh>::null_face())
|
||||
|
|
@ -673,36 +721,38 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
}
|
||||
}
|
||||
|
||||
// Start the process of removing bad elements
|
||||
std::set<halfedge_descriptor> edges_to_collapse;
|
||||
std::set<halfedge_descriptor> edges_to_flip;
|
||||
// @todo maybe using a priority queue handling the more almost degenerate elements first should be used
|
||||
std::unordered_set<halfedge_descriptor> edges_to_collapse;
|
||||
std::unordered_set<halfedge_descriptor> edges_to_flip;
|
||||
|
||||
// @todo could probably do something a bit better by looping edges, consider the incident faces
|
||||
// f1 / f2 and look at f1 if f1<f2, and the edge is smaller than the two other edges...
|
||||
// initial needless-ness and cap-ness checks
|
||||
for(face_descriptor f : face_range)
|
||||
{
|
||||
internal::collect_badly_shaped_triangles(f, tmesh, vpm, vcm, ecm, gt,
|
||||
cap_threshold, needle_threshold,
|
||||
collapse_length_threshold, flip_triangle_height_threshold_squared,
|
||||
edges_to_collapse, edges_to_flip);
|
||||
halfedge_descriptor needle_h = internal::is_it_a_needle(f, tmesh, vpm, vcm, ecm, gt,
|
||||
needle_threshold, collapse_length_threshold);
|
||||
if(needle_h != null_h)
|
||||
edges_to_collapse.insert(needle_h);
|
||||
else
|
||||
{
|
||||
halfedge_descriptor cap_h = internal::is_it_a_cap(f, tmesh, vpm, vcm, ecm, gt,
|
||||
cap_threshold, flip_triangle_height_threshold_squared);
|
||||
if(cap_h != null_h)
|
||||
edges_to_flip.insert(cap_h);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES
|
||||
std::cout << edges_to_collapse.size() << " to collapse" << std::endl;
|
||||
std::cout << edges_to_flip.size() << " to flip" << std::endl;
|
||||
#endif
|
||||
|
||||
// Start the process of removing bad elements
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES
|
||||
int iter = 0;
|
||||
#endif
|
||||
|
||||
for(;;)
|
||||
{
|
||||
bool something_was_done = false;
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES
|
||||
std::cout << edges_to_collapse.size() << " needles and " << edges_to_flip.size() << " caps" << std::endl;
|
||||
std::cout << "Iter: " << iter << std::endl;
|
||||
std::cout << edges_to_collapse.size() << " needles and " << edges_to_flip.size() << " caps" << std::endl;
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "degen_cleaning_iter_" << iter++ << ".off";
|
||||
CGAL::IO::write_polygon_mesh(oss.str(), tmesh, CGAL::parameters::stream_precision(17));
|
||||
|
|
@ -711,65 +761,85 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
if(edges_to_collapse.empty() && edges_to_flip.empty())
|
||||
return true;
|
||||
|
||||
// @todo maybe using a priority queue handling the more almost degenerate elements should be used
|
||||
std::set<halfedge_descriptor> next_edges_to_collapse;
|
||||
std::set<halfedge_descriptor> next_edges_to_flip;
|
||||
std::unordered_set<halfedge_descriptor> next_edges_to_collapse;
|
||||
|
||||
// Treat needles ===============================================================================
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
int kk=0;
|
||||
std::ofstream(std::string("tmp/n-00000.off")) << tmesh;
|
||||
#endif
|
||||
|
||||
auto run_cap_check = [&](halfedge_descriptor h, bool consider_for_collapse=true)
|
||||
{
|
||||
halfedge_descriptor cap_h = internal::is_it_a_cap(face(h, tmesh), tmesh, vpm, vcm, ecm, gt,
|
||||
cap_threshold, flip_triangle_height_threshold_squared);
|
||||
if(cap_h != null_h)
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "\t\t But the face is a cap" << std::endl;
|
||||
#endif
|
||||
edges_to_flip.insert(cap_h);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (consider_for_collapse) next_edges_to_collapse.insert(h);
|
||||
}
|
||||
};
|
||||
|
||||
while(!edges_to_collapse.empty())
|
||||
{
|
||||
// note that on the first iteration, 'h' does not indicate a known needle
|
||||
halfedge_descriptor h = *edges_to_collapse.begin();
|
||||
edges_to_collapse.erase(edges_to_collapse.begin());
|
||||
CGAL_assertion(is_valid_halfedge_descriptor(h, tmesh));
|
||||
|
||||
// Verify that the element is still badly shaped
|
||||
halfedge_descriptor needle_h = internal::is_it_a_needle(face(h, tmesh), tmesh, vpm, vcm, ecm, gt,
|
||||
needle_threshold, collapse_length_threshold);
|
||||
if(needle_h == null_h)
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "\t Needle criterion not verified" << std::endl;
|
||||
#endif
|
||||
run_cap_check(h, false);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = needle_h;
|
||||
}
|
||||
|
||||
CGAL_assertion(!is_border(h, tmesh));
|
||||
|
||||
const edge_descriptor e = edge(h, tmesh);
|
||||
CGAL_assertion(!get(ecm, edge(h, tmesh)));
|
||||
|
||||
if(get(vcm, source(h, tmesh)) && get(vcm, target(h, tmesh)))
|
||||
continue;
|
||||
CGAL_assertion(!get(vcm, source(h, tmesh)) && !get(vcm, target(h, tmesh)));
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << " treat needle: " << e
|
||||
<< " (" << source(e, tmesh) << " " << tmesh.point(source(h, tmesh))
|
||||
<< " --- " << source(e, tmesh) << " " << tmesh.point(target(h, tmesh)) << ")" << std::endl;
|
||||
#endif
|
||||
|
||||
if(CGAL::Euler::does_satisfy_link_condition(e, tmesh))
|
||||
{
|
||||
// Verify that the element is still badly shaped
|
||||
const std::array<halfedge_descriptor, 2> nc =
|
||||
internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, vcm, ecm, gt,
|
||||
cap_threshold, needle_threshold, collapse_length_threshold, flip_triangle_height_threshold_squared);
|
||||
|
||||
if(nc[0] != h)
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "\t Needle criteria no longer verified" << std::endl;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// pick the orientation of edge to keep the vertex minimizing the volume variation
|
||||
const halfedge_descriptor best_h = internal::get_best_edge_orientation(e, tmesh, vpm, vcm, gt);
|
||||
if(best_h == boost::graph_traits<TriangleMesh>::null_halfedge())
|
||||
if(best_h == null_h)
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "\t Geometrically invalid edge collapse!" << std::endl;
|
||||
#endif
|
||||
next_edges_to_collapse.insert(h);
|
||||
run_cap_check(h);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!accept_change.collapse(edge(best_h, tmesh)))
|
||||
if(!accept_change.collapse(edge(best_h, tmesh)))
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "\t edge collapse prevented by the user functor" << std::endl;
|
||||
#endif
|
||||
next_edges_to_collapse.insert(h);
|
||||
run_cap_check(h);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -830,7 +900,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
else
|
||||
v = Euler::collapse_edge(edge(best_h, tmesh), tmesh);
|
||||
|
||||
// moving to the midpoint is not a good idea. On a circle for example you might endpoint with
|
||||
// moving to the midpoint is not a good idea. On a circle for example you might end with
|
||||
// a bad geometry because you iteratively move one point
|
||||
// auto mp = midpoint(tmesh.point(source(h, tmesh)), tmesh.point(target(h, tmesh)));
|
||||
// tmesh.point(v) = mp;
|
||||
|
|
@ -840,10 +910,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
{
|
||||
if(!is_border(hv, tmesh))
|
||||
{
|
||||
internal::collect_badly_shaped_triangles(face(hv, tmesh), tmesh, vpm, vcm, ecm, gt,
|
||||
cap_threshold, needle_threshold,
|
||||
collapse_length_threshold, flip_triangle_height_threshold_squared,
|
||||
edges_to_collapse, edges_to_flip);
|
||||
next_edges_to_collapse.insert(hv); // shape will be tested when popped
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -862,24 +929,40 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "\t Uncollapsable edge!" << std::endl;
|
||||
#endif
|
||||
next_edges_to_collapse.insert(h);
|
||||
run_cap_check(h);
|
||||
}
|
||||
}
|
||||
|
||||
// Treat caps ==================================================================================
|
||||
CGAL_assertion(next_edges_to_flip.empty());
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
kk=0;
|
||||
std::ofstream(std::string("tmp/c-000.off")) << tmesh;
|
||||
#endif
|
||||
|
||||
while(!edges_to_flip.empty())
|
||||
{
|
||||
halfedge_descriptor h = *edges_to_flip.begin();
|
||||
edges_to_flip.erase(edges_to_flip.begin());
|
||||
|
||||
CGAL_assertion(is_valid_halfedge_descriptor(h, tmesh));
|
||||
CGAL_assertion(!is_border(h, tmesh));
|
||||
|
||||
// check if the face is still a cap
|
||||
halfedge_descriptor cap_h = internal::is_it_a_cap(face(h, tmesh), tmesh, vpm, vcm, ecm, gt,
|
||||
cap_threshold, flip_triangle_height_threshold_squared);
|
||||
|
||||
if(cap_h == null_h)
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "\t Cap criterion no longer verified" << std::endl;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = cap_h;
|
||||
}
|
||||
|
||||
const edge_descriptor e = edge(h, tmesh);
|
||||
CGAL_assertion(!get(ecm, e));
|
||||
|
||||
|
|
@ -889,23 +972,11 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
<< " --- " << target(e, tmesh) << " " << tmesh.point(target(h, tmesh)) << ")" << std::endl;
|
||||
#endif
|
||||
|
||||
std::array<halfedge_descriptor,2> nc = internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, vcm, ecm, gt,
|
||||
cap_threshold, needle_threshold,
|
||||
collapse_length_threshold, flip_triangle_height_threshold_squared);
|
||||
// Check the triangle is still a cap
|
||||
if(nc[1] != h)
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "\t Cap criteria no longer verified" << std::endl;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// special case of `edge(h, tmesh)` being a border edge --> remove the face
|
||||
if(is_border(opposite(h, tmesh), tmesh))
|
||||
{
|
||||
// check a non-manifold vertex won't be created
|
||||
bool removal_is_nm=false;
|
||||
// check that a non-manifold vertex won't be created
|
||||
bool removal_is_nm = false;
|
||||
for(halfedge_descriptor hh : CGAL::halfedges_around_target(next(h, tmesh), tmesh))
|
||||
{
|
||||
if (is_border(hh, tmesh))
|
||||
|
|
@ -914,13 +985,13 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (removal_is_nm) continue;
|
||||
|
||||
if(removal_is_nm)
|
||||
continue;
|
||||
|
||||
for(halfedge_descriptor hh : CGAL::halfedges_around_face(h, tmesh))
|
||||
{
|
||||
// Remove from even 'next_edges_to_flip' because it might have been re-added from a flip
|
||||
edges_to_flip.erase(hh);
|
||||
next_edges_to_flip.erase(hh);
|
||||
next_edges_to_collapse.erase(hh);
|
||||
}
|
||||
|
||||
|
|
@ -941,15 +1012,16 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "\t Flipping prevented: not the best diagonal" << std::endl;
|
||||
#endif
|
||||
next_edges_to_flip.insert(h);
|
||||
next_edges_to_collapse.insert(h);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!accept_change.flip(h))
|
||||
if(!accept_change.flip(h))
|
||||
{
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
std::cout << "\t Flipping prevented: rejected by user functor" << std::endl;
|
||||
#endif
|
||||
next_edges_to_collapse.insert(h);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -963,16 +1035,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
for(int i=0; i<2; ++i)
|
||||
{
|
||||
CGAL_assertion(!is_border(h, tmesh));
|
||||
std::array<halfedge_descriptor, 2> nc =
|
||||
internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, vcm, ecm, gt,
|
||||
cap_threshold, needle_threshold,
|
||||
collapse_length_threshold, flip_triangle_height_threshold_squared);
|
||||
|
||||
if(nc[1] != boost::graph_traits<TriangleMesh>::null_halfedge() && nc[1] != h)
|
||||
next_edges_to_flip.insert(nc[1]);
|
||||
else if(nc[0] != boost::graph_traits<TriangleMesh>::null_halfedge())
|
||||
next_edges_to_collapse.insert(nc[0]);
|
||||
|
||||
next_edges_to_collapse.insert(h);
|
||||
h = opposite(h, tmesh);
|
||||
}
|
||||
|
||||
|
|
@ -984,7 +1047,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
std::cout << "\t Unflippable edge!" << std::endl;
|
||||
#endif
|
||||
CGAL_assertion(!is_border(h, tmesh));
|
||||
next_edges_to_flip.insert(h);
|
||||
next_edges_to_collapse.insert(h);
|
||||
}
|
||||
|
||||
#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA
|
||||
|
|
@ -1001,7 +1064,6 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range,
|
|||
return false;
|
||||
|
||||
std::swap(edges_to_collapse, next_edges_to_collapse);
|
||||
std::swap(edges_to_flip, next_edges_to_flip);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace Polygon_mesh_processing {
|
|||
* \ingroup PMPDeprecated
|
||||
*
|
||||
* \deprecated This function is deprecated since \cgal 5.5,
|
||||
* `CGAL::angle_and_area_smoothing()` should be used instead.
|
||||
* `CGAL::Polygon_mesh_processing::angle_and_area_smoothing()` should be used instead.
|
||||
*/
|
||||
template<typename TriangleMesh, typename FaceRange, typename NamedParameters = parameters::Default_named_parameters>
|
||||
CGAL_DEPRECATED void smooth_mesh(const FaceRange& faces,
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ create_single_source_cgal_program("test_pmp_np_function.cpp")
|
|||
create_single_source_cgal_program("test_degenerate_pmp_clip_split_corefine.cpp")
|
||||
create_single_source_cgal_program("test_isolevel_refinement.cpp")
|
||||
create_single_source_cgal_program("test_corefinement_nm_bo.cpp")
|
||||
create_single_source_cgal_program("test_corefinement_cavities.cpp")
|
||||
# create_single_source_cgal_program("test_pmp_repair_self_intersections.cpp")
|
||||
|
||||
find_package(Eigen3 3.2.0 QUIET) #(requires 3.2.0 or greater)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/corefinement.h>
|
||||
|
||||
template <class Point, class Mesh>
|
||||
void make_hexa(double x, double y, double z,
|
||||
double X, double Y, double Z,
|
||||
Mesh& mesh, int t)
|
||||
{
|
||||
CGAL::make_hexahedron(
|
||||
Point(x,y,Z),
|
||||
Point(X,y,Z),
|
||||
Point(X,y,z),
|
||||
Point(x,y,z),
|
||||
Point(x,Y,z),
|
||||
Point(x,Y,Z),
|
||||
Point(X,Y,Z),
|
||||
Point(X,Y,z),
|
||||
mesh);
|
||||
|
||||
using face_descriptor = typename boost::graph_traits<Mesh>::face_descriptor;
|
||||
using halfedge_descriptor = typename boost::graph_traits<Mesh>::halfedge_descriptor;
|
||||
|
||||
std::vector<face_descriptor> fcs(faces(mesh).begin(), faces(mesh).end());
|
||||
for (face_descriptor f : fcs)
|
||||
{
|
||||
halfedge_descriptor h = halfedge(f, mesh);
|
||||
if (t==1) h=next(h,mesh);
|
||||
halfedge_descriptor h2=next(next(h, mesh), mesh);
|
||||
CGAL::Euler::split_face(h, h2, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
using K = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using Point_3 = K::Point_3;
|
||||
using Mesh = CGAL::Surface_mesh<Point_3>;
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
|
||||
void test_operations(Mesh A, Mesh B,
|
||||
bool reverse_A, bool reverse_B,
|
||||
std::string round,
|
||||
std::size_t union_v, std::size_t inter_v, std::size_t diff1_v, std::size_t diff2_v)
|
||||
{
|
||||
#ifndef VERBOSE
|
||||
CGAL_USE(round);
|
||||
#endif
|
||||
if (reverse_A) PMP::reverse_face_orientations(A);
|
||||
if (reverse_B) PMP::reverse_face_orientations(B);
|
||||
|
||||
Mesh out_union, out_inter, out_diff1, out_diff2;
|
||||
std::array<std::optional<Mesh*>, 4> output;
|
||||
output[PMP::Corefinement::UNION] = &out_union;
|
||||
output[PMP::Corefinement::INTERSECTION] = &out_inter;
|
||||
output[PMP::Corefinement::TM1_MINUS_TM2] = &out_diff1;
|
||||
output[PMP::Corefinement::TM2_MINUS_TM1] = &out_diff2;
|
||||
|
||||
Mesh lA=A, lB=B;
|
||||
PMP::corefine_and_compute_boolean_operations(lA,lB,output);
|
||||
#ifdef VERBOSE
|
||||
std::ofstream("out_union_"+round+".off") << out_union;
|
||||
std::ofstream("out_inter_"+round+".off") << out_inter;
|
||||
std::ofstream("out_diff1_"+round+".off") << out_diff1;
|
||||
std::ofstream("out_diff2_"+round+".off") << out_diff2;
|
||||
#endif
|
||||
assert(vertices(out_union).size()==union_v);
|
||||
assert(vertices(out_inter).size()==inter_v);
|
||||
assert(vertices(out_diff1).size()==diff1_v);
|
||||
assert(vertices(out_diff2).size()==diff2_v);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
Mesh A, mh, B;
|
||||
make_hexa<Point_3>(0, 0, 0,
|
||||
4, 4, 4,
|
||||
A, 0);
|
||||
make_hexa<Point_3>(1, 1, 1,
|
||||
2, 2, 2,
|
||||
mh, 0);
|
||||
make_hexa<Point_3>(1, 1, 1,
|
||||
2, 2, 2,
|
||||
B, 1);
|
||||
|
||||
Mesh A2, mh2, B2;
|
||||
make_hexa<Point_3>(5, 0, 0,
|
||||
9, 4, 4,
|
||||
A2, 0);
|
||||
make_hexa<Point_3>(6, 1, 1,
|
||||
7, 2, 2,
|
||||
mh2, 0);
|
||||
make_hexa<Point_3>(6, 1, 1,
|
||||
7, 2, 2,
|
||||
B2, 1);
|
||||
|
||||
A.join(A2);
|
||||
mh.join(mh2);
|
||||
PMP::reverse_face_orientations(mh);
|
||||
A.join(mh);
|
||||
B.join(B2);
|
||||
|
||||
#ifdef VERBOSE
|
||||
std::ofstream("A.off") << A;
|
||||
std::ofstream("B.off") << B;
|
||||
#endif
|
||||
|
||||
test_operations(A, B, false, false, "r00", 16, 0, 44, 28);
|
||||
test_operations(A, B, false, true, "r01", 28, 44, 0, 16);
|
||||
test_operations(A, B, true, false, "r10", 44, 28, 16, 0);
|
||||
test_operations(A, B, true, true, "r11", 0, 16, 28, 44);
|
||||
|
||||
test_operations(A, A, false, false, "a00", 32, 32, 0, 0);
|
||||
test_operations(A, A, false, true, "a01", 0, 0, 32, 32);
|
||||
test_operations(A, A, true, false, "a10", 0, 0, 32, 32);
|
||||
test_operations(A, A, true, true, "a11", 32, 32, 0, 0);
|
||||
|
||||
test_operations(B, B, false, false, "b00", 16, 16, 0, 0);
|
||||
test_operations(B, B, false, true, "b01", 0, 0, 16, 16);
|
||||
test_operations(B, B, true, false, "b10", 0, 0, 16, 16);
|
||||
test_operations(B, B, true, true, "b11", 16, 16, 0, 0);
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ void general_test(std::string filename)
|
|||
std::ifstream input(filename);
|
||||
|
||||
Mesh mesh;
|
||||
if (!input || !(input >> mesh) || !CGAL::is_triangle_mesh(mesh)) {
|
||||
if (!CGAL::IO::read_polygon_mesh(filename, mesh) || !CGAL::is_triangle_mesh(mesh)) {
|
||||
std::cerr << "Not a valid input file." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -57,7 +57,8 @@ void test_with_envelope(std::string filename, double eps)
|
|||
std::ifstream input(filename);
|
||||
|
||||
Mesh mesh, bk;
|
||||
if (!input || !(input >> mesh) || !CGAL::is_triangle_mesh(mesh)) {
|
||||
if (!CGAL::IO::read_polygon_mesh(filename, mesh) || !CGAL::is_triangle_mesh(mesh))
|
||||
{
|
||||
std::cerr << "Not a valid input file." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -132,7 +133,8 @@ void test_parameters_on_pig(std::string filename)
|
|||
std::ifstream input(filename);
|
||||
|
||||
Mesh mesh, bk;
|
||||
if (!input || !(input >> mesh) || !CGAL::is_triangle_mesh(mesh)) {
|
||||
if (!CGAL::IO::read_polygon_mesh(filename, mesh) || !CGAL::is_triangle_mesh(mesh))
|
||||
{
|
||||
std::cerr << "Not a valid input file." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -165,13 +167,11 @@ void test_parameters_on_pig(std::string filename)
|
|||
int main(int argc, char** argv)
|
||||
{
|
||||
const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/pig.off");
|
||||
double eps = (argc > 2) ? atof(argv[2]) : 0.01;
|
||||
|
||||
general_test(filename);
|
||||
if (argc==2)
|
||||
test_with_envelope(filename, 0.01);
|
||||
else
|
||||
if (argc==3)
|
||||
test_with_envelope(filename, atof(argv[2]));
|
||||
|
||||
test_with_envelope(filename, eps);
|
||||
|
||||
// only run that test with pig.off
|
||||
if (argc==1)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,190 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import json
|
||||
from typing import Dict, List
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
import subprocess
|
||||
import re
|
||||
import requests
|
||||
|
||||
CGAL_SERVER_URL = "https://cgal.geometryfactory.com/CGAL"
|
||||
LATEST_VERSION_URL = f"{CGAL_SERVER_URL}/Releases/LATEST"
|
||||
JSON_DATA_URL_TEMPLATE = f"{
|
||||
CGAL_SERVER_URL}/testsuite/CGAL-{{version}}/search_index.json"
|
||||
TESTSUITE_URL_TEMPLATE = f"{
|
||||
CGAL_SERVER_URL}/testsuite/results-{{version}}.shtml"
|
||||
TIMEOUT_DURATION = 10
|
||||
|
||||
|
||||
@dataclass
|
||||
class TPLInfo:
|
||||
name: str
|
||||
version: str
|
||||
status: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlatformInfo:
|
||||
name: str
|
||||
debug: str
|
||||
os: str
|
||||
tester: str
|
||||
compiler: str
|
||||
tpl_info: List[TPLInfo]
|
||||
|
||||
|
||||
def fetch_data_from_url(url: str) -> str:
|
||||
"""Fetch data from a given URL."""
|
||||
response = requests.get(url, timeout=TIMEOUT_DURATION)
|
||||
response.raise_for_status()
|
||||
return response.text.strip()
|
||||
|
||||
|
||||
def get_latest_version() -> str:
|
||||
"""Return latest CGAL version from LATEST (CGAL-<version>.tar.gz)"""
|
||||
tarball_name = fetch_data_from_url(LATEST_VERSION_URL)
|
||||
match = re.match(r'CGAL-([^.]+\.[^-]+-[^-]+-\d+)', tarball_name)
|
||||
if not match:
|
||||
raise ValueError(f"Unexpected tarball name format: {tarball_name}")
|
||||
return match.group(1)
|
||||
|
||||
|
||||
def fetch_json_data(version: str) -> Dict:
|
||||
"""Fetch JSON data for the given CGAL testsuite."""
|
||||
url = JSON_DATA_URL_TEMPLATE.format(version=version)
|
||||
json_data = fetch_data_from_url(url)
|
||||
return json.loads(json_data)
|
||||
|
||||
|
||||
def analyze_tpl_data(json_data: Dict) -> List[PlatformInfo]:
|
||||
"""Analyze TPL data from JSON and return a list of PlatformInfo."""
|
||||
platforms_info = []
|
||||
for platform in json_data.get('platforms', []):
|
||||
tpl_list = [
|
||||
TPLInfo(
|
||||
name=item.get('name', 'Unknown'),
|
||||
version=item.get('version', 'N/A'),
|
||||
status=item.get('status', 'unknown')
|
||||
)
|
||||
for item in platform.get('third_party_libs', [])
|
||||
]
|
||||
platform_info = PlatformInfo(
|
||||
name=platform.get('platform_name', 'Unknown Platform'),
|
||||
debug=platform.get('debug', '-'),
|
||||
os=platform.get('operating_system', '-'),
|
||||
tester=platform.get('tester_name', '-'),
|
||||
compiler=platform.get('compiler', '-'),
|
||||
tpl_info=tpl_list
|
||||
)
|
||||
platforms_info.append(platform_info)
|
||||
return platforms_info
|
||||
|
||||
|
||||
def get_docker_images() -> Dict[str, List[str]]:
|
||||
"""
|
||||
Get Docker image information by calling `list_test_runner_machines`.
|
||||
Returns a dictionary with machine names as keys and lists of images as values.
|
||||
"""
|
||||
try:
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
result = subprocess.run(
|
||||
[os.path.join(script_dir, 'list_test_runner_machines'), '--plain'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
output = result.stdout.strip()
|
||||
|
||||
machines_info = {}
|
||||
current_machine = None
|
||||
parsing_images = False
|
||||
|
||||
for line in output.splitlines():
|
||||
if line.startswith("## "):
|
||||
current_machine = line.strip("# ").strip()
|
||||
machines_info[current_machine] = []
|
||||
parsing_images = False
|
||||
|
||||
elif line.startswith("Tested images:"):
|
||||
parsing_images = True
|
||||
|
||||
elif parsing_images and (line.startswith("cgal/testsuite-docker:") or line.startswith("docker.io/cgal/testsuite-docker:")):
|
||||
machines_info[current_machine].append(line.strip())
|
||||
|
||||
return machines_info
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise RuntimeError(
|
||||
f"Error running `list_test_runner_machines`: {e}") from e
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Error parsing Docker information: {e}") from e
|
||||
|
||||
|
||||
def add_docker_summary(report: List[str], machines_info: Dict[str, List[str]]):
|
||||
"""Add a summary of Docker images used on each machine to the report."""
|
||||
report.append("\n## Docker Test Summary")
|
||||
for machine, images in machines_info.items():
|
||||
report.append(f"\n### Machine: {machine} ({len(images)} images)")
|
||||
report.append("\n#### Tested Images\n")
|
||||
for image in images:
|
||||
report.append(f"- {image}")
|
||||
|
||||
|
||||
def generate_markdown_report(platforms_info: List[PlatformInfo], version: str) -> str:
|
||||
"""Generate a markdown report from the platforms information."""
|
||||
machines_info = get_docker_images()
|
||||
report = []
|
||||
report.append("# TestSuite Report")
|
||||
report.append(f"\nGenerated on: {
|
||||
datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
url = TESTSUITE_URL_TEMPLATE.format(version=version)
|
||||
report.append(f"\nCGAL Version: [{version}]({url})")
|
||||
add_docker_summary(report, machines_info)
|
||||
report.append("\n## Platforms Summary\n")
|
||||
report.append("| Platform | Debug | OS | Tester | Compiler |")
|
||||
report.append("|----------|-------|----|--------|----------|")
|
||||
for platform in platforms_info:
|
||||
report.append(
|
||||
f"| {platform.name} | {platform.debug} | {platform.os} | "
|
||||
f"{platform.tester} | {platform.compiler} |"
|
||||
)
|
||||
report.append("\n## Detailed Third-party Libraries")
|
||||
for platform in platforms_info:
|
||||
report.append(f"\n### Platform: {platform.name}\n")
|
||||
tpl_list = sorted(platform.tpl_info, key=lambda x: x.name)
|
||||
report.append("| Library Name | Version | Status |")
|
||||
report.append("|--------------|---------|--------|")
|
||||
for tpl in tpl_list:
|
||||
version_str = str(tpl.version) if tpl.version else "N/A"
|
||||
status_str = "❌" if tpl.version == "not found" else "✅"
|
||||
report.append(f"| {tpl.name} | {version_str} | {status_str} |")
|
||||
found_tpls = sum(1 for tpl in tpl_list if tpl.version != "not found")
|
||||
total_tpls = len(tpl_list)
|
||||
report.append(
|
||||
f"\n**Summary**: found {found_tpls} third-party libraries out of {total_tpls}")
|
||||
return "\n".join(report)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to generate the testsuite report."""
|
||||
try:
|
||||
version = get_latest_version()
|
||||
json_data = fetch_json_data(version)
|
||||
platforms_info = analyze_tpl_data(json_data)
|
||||
markdown_report = generate_markdown_report(platforms_info, version)
|
||||
print(markdown_report)
|
||||
except requests.RequestException as e:
|
||||
print(f"**Error fetching data:**\n\n```\n{str(e)}\n```\n")
|
||||
raise
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"**Error: Invalid JSON data**\n\n```\n{str(e)}\n```")
|
||||
print(f"\nFile:\n\n```json\n{e.doc}\n```")
|
||||
raise
|
||||
except Exception as e:
|
||||
print(f"**Error processing data:**\n\n```\n{str(e)}\n```\n")
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,320 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Declare an associative array to store the images used on each machine
|
||||
declare -A MACHINE_CONTAINER_IMAGES
|
||||
|
||||
TEST_MACHINES=(
|
||||
"lrineau@bonnard"
|
||||
"lrineau@cgal"
|
||||
"cgaltest@friedrich"
|
||||
"lrineau@rubens"
|
||||
)
|
||||
|
||||
machine_title() {
|
||||
printf '\n## %s ##\n' "$1"
|
||||
}
|
||||
|
||||
machine_info() {
|
||||
HOST=$1
|
||||
remote_script=$(printf "export PS4='+ %s >> %s'\n" "$HOST" "$PS4")$'\n'$(
|
||||
cat <<'EOF'
|
||||
source /etc/os-release
|
||||
printf '\n- OS: `%s`\n- container implementation: `%s`\n' "$PRETTY_NAME" "$(docker --version)"
|
||||
EOF
|
||||
)
|
||||
ssh "$HOST" bash -$- -s <<<"$remote_script"
|
||||
}
|
||||
|
||||
machine_tested_images() {
|
||||
echo
|
||||
echo '```plain'
|
||||
printf '%s\n' "${MACHINE_CONTAINER_IMAGES["$1"]}"
|
||||
echo '```'
|
||||
}
|
||||
|
||||
docker_is_active_cmd() {
|
||||
systemctl is-active -q docker
|
||||
return $?
|
||||
}
|
||||
declare -xf docker_is_active_cmd
|
||||
|
||||
docker_cmd() {
|
||||
if docker_is_active_cmd; then
|
||||
docker "$@"
|
||||
else
|
||||
podman --url unix:/var/run/podman/podman.sock "$@"
|
||||
fi
|
||||
}
|
||||
declare -xf docker_cmd
|
||||
|
||||
list_of_containers_cmd() {
|
||||
docker_cmd ps -a --format '{{.Names}}' --filter name="CGAL-"
|
||||
}
|
||||
declare -xf list_of_containers_cmd
|
||||
|
||||
container_status_cmd() {
|
||||
docker_cmd inspect --format '{{.State.Status}}' "$1"
|
||||
}
|
||||
declare -xf container_status_cmd
|
||||
|
||||
container_human_readable_status_cmd() {
|
||||
docker_cmd ps --all --filter name="$1" --format '{{.Status}}'
|
||||
}
|
||||
declare -xf container_human_readable_status_cmd
|
||||
|
||||
simplify_date_cmd() {
|
||||
date=$1
|
||||
pattern=' \+[0-9]{4} [+]?[A-Z0-9]{3,}$'
|
||||
if [[ $date =~ $pattern ]]; then
|
||||
date=${date% *}
|
||||
fi
|
||||
echo "$date"
|
||||
}
|
||||
declare -xf simplify_date_cmd
|
||||
|
||||
container_start_time_cmd() {
|
||||
simplify_date_cmd "$(docker_cmd inspect --format '{{.State.StartedAt}}' "$1")"
|
||||
}
|
||||
declare -xf container_start_time_cmd
|
||||
|
||||
container_end_time_cmd() {
|
||||
simplify_date_cmd "$(docker_cmd inspect --format '{{.State.FinishedAt}}' "$1")"
|
||||
}
|
||||
declare -xf container_end_time_cmd
|
||||
|
||||
container_running_time_cmd() {
|
||||
start_time=$(container_start_time_cmd "$1")
|
||||
end_time=$(container_end_time_cmd "$1")
|
||||
status=$(container_status_cmd "$1")
|
||||
if [ "$status" = "running" ]; then
|
||||
end_time=$(date -u '+%Y-%m-%dT%H:%M:%S.%NZ')
|
||||
fi
|
||||
secs=$(($(date -d "$end_time" +%s) - $(date -d "$start_time" +%s)))
|
||||
printf '%02dh:%02dm:%02ds\n' $((secs / 3600)) $((secs % 3600 / 60)) $((secs % 60))
|
||||
}
|
||||
declare -xf container_running_time_cmd
|
||||
|
||||
display_one_container_line_cmd() {
|
||||
printf '%s\t%s\t%s\t%s\t%s\n' "$1" "$2" "$3" "$4" "$5"
|
||||
}
|
||||
declare -xf display_one_container_line_cmd
|
||||
|
||||
list_cgal_test_container_cmd() {
|
||||
# docker_cmd ps -a --filter name=CGAL-
|
||||
display_one_container_line_cmd "CONTAINER" "START TIME" "END TIME" "RUNNING TIME" "STATUS"
|
||||
for container in $(list_of_containers_cmd); do
|
||||
start_time="$(container_start_time_cmd "$container")"
|
||||
end_time="$(container_end_time_cmd "$container")"
|
||||
dur=$(container_running_time_cmd "$container")
|
||||
status="$(container_status_cmd "$container") - $(container_human_readable_status_cmd "$container")"
|
||||
display_one_container_line_cmd "$container" "$start_time" "$end_time" "$dur" "$status"
|
||||
done
|
||||
}
|
||||
declare -xf list_cgal_test_container_cmd
|
||||
|
||||
display_all_exported_cmd_functions() {
|
||||
functions=$(declare -F | awk '/ -fx .*_cmd$/ {print $3}')
|
||||
for func in $functions; do
|
||||
declare -f "$func"
|
||||
done
|
||||
}
|
||||
|
||||
machine_list_cgal_test_container() {
|
||||
printf '\n```tsv\n'
|
||||
remote_script=$(
|
||||
display_all_exported_cmd_functions
|
||||
printf "export PS4='+ %s >> %s'\n" "$1" "$PS4"
|
||||
echo list_cgal_test_container_cmd
|
||||
)
|
||||
ssh "$1" bash -$- -s <<<"$remote_script"
|
||||
printf '```\n'
|
||||
}
|
||||
|
||||
help() {
|
||||
cat <<HEREDOC
|
||||
Usage: $0 [OPTION]
|
||||
|
||||
List the test runner machines and the containers running on them.
|
||||
|
||||
Output Format Options:
|
||||
--table output in markdown table format
|
||||
--column output in column format
|
||||
--bat output with bat
|
||||
--plain output in plain text
|
||||
|
||||
If no option is given, the script will try to use bat, then column, and finally
|
||||
plain text.
|
||||
|
||||
Information Options:
|
||||
--images list the images used on each machine
|
||||
--containers list the containers running on each machine
|
||||
--info list the OS and the container implementation on each machine
|
||||
|
||||
If no information option is given, the script will list all the information.
|
||||
HEREDOC
|
||||
}
|
||||
|
||||
error_out() {
|
||||
exec >&2
|
||||
echo "ERROR: $1"
|
||||
echo
|
||||
help
|
||||
exit 1
|
||||
}
|
||||
|
||||
command -v sed >/dev/null || {
|
||||
error_out 'sed is required'
|
||||
}
|
||||
|
||||
if [[ $1 == --table ]] && ! command -v pandoc >/dev/null; then
|
||||
error_out 'pandoc is required for the option --table'
|
||||
fi
|
||||
if [[ $1 == --column ]] && ! command -v column >/dev/null; then
|
||||
error_out 'column is required for the option --column'
|
||||
fi
|
||||
if [[ $1 == --bat ]] && ! command -v bat >/dev/null; then
|
||||
error_out 'bat is required for the option --bat'
|
||||
fi
|
||||
|
||||
set_pretty_csv_to_md_table() {
|
||||
pretty_csv() (
|
||||
echo
|
||||
sed '/```/ d; /^$/ d' | pandoc -f tsv -t gfm
|
||||
)
|
||||
}
|
||||
|
||||
set_pretty_csv_to_column() {
|
||||
pretty_csv() {
|
||||
echo
|
||||
column -t -s $'\t' -o $'\t' | sed 's/^\(```[^ ]*\) *\t.*/\1/'
|
||||
}
|
||||
}
|
||||
|
||||
set_pretty_csv_to_column_and_bat() {
|
||||
pretty_csv() {
|
||||
echo
|
||||
column -t -s $'\t' -o $'\t' | sed 's/^\(```[^ ]*\) *\t.*/\1/' | bat --paging=never --plain -l csv
|
||||
}
|
||||
}
|
||||
|
||||
set_pretty_csv_to_bat() {
|
||||
pretty_csv() {
|
||||
bat --tabs=50 --paging=never --plain -l csv
|
||||
}
|
||||
}
|
||||
|
||||
set_pretty_csv_to_cat() {
|
||||
pretty_csv() {
|
||||
cat
|
||||
}
|
||||
}
|
||||
|
||||
WHAT=()
|
||||
|
||||
add_to_what() {
|
||||
for i in "$@"; do
|
||||
WHAT+=("$i")
|
||||
done
|
||||
}
|
||||
|
||||
what_contains() {
|
||||
local item=$1
|
||||
for i in "${WHAT[@]}"; do
|
||||
if [[ "$i" == "$item" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--table) set_pretty_csv_to_md_table ;;
|
||||
--column) set_pretty_csv_to_column ;;
|
||||
--bat) set_pretty_csv_to_bat ;;
|
||||
--plain) set_pretty_csv_to_cat ;;
|
||||
--images) add_to_what images ;;
|
||||
--containers) add_to_what containers ;;
|
||||
--info) add_to_what info ;;
|
||||
-h | --help)
|
||||
help >&2
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
error_out "Unknown option $arg"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ${#WHAT[@]} -eq 0 ]; then
|
||||
add_to_what info images containers
|
||||
fi
|
||||
|
||||
STDOUT_IS_A_TTY=
|
||||
if <&1 tty -s; then
|
||||
STDOUT_IS_A_TTY=1
|
||||
fi
|
||||
|
||||
BAT=
|
||||
[ -n "$STDOUT_IS_A_TTY" ] && BAT=$(command -v bat)
|
||||
|
||||
COLUMN=$(command -v column)
|
||||
|
||||
PANDOC=$(command -v pandoc)
|
||||
if ! declare -f pretty_csv >/dev/null; then
|
||||
if [ -n "$BAT" ]; then
|
||||
if [ -n "$COLUMN" ]; then
|
||||
set_pretty_csv_to_column_and_bat
|
||||
else
|
||||
set_pretty_csv_to_bat
|
||||
fi
|
||||
elif [ -n "$PANDOC" ]; then
|
||||
set_pretty_csv_to_md_table
|
||||
elif [ -n "$COLUMN" ]; then
|
||||
set_pretty_csv_to_column
|
||||
else
|
||||
set_pretty_csv_to_cat
|
||||
fi
|
||||
fi
|
||||
|
||||
ERROR_MACHINES=""
|
||||
for machine in "${TEST_MACHINES[@]}"; do
|
||||
USER=${machine%@*}
|
||||
HOST=${machine#*@}
|
||||
# shellcheck disable=SC2029
|
||||
MACHINE_CONTAINER_IMAGES[$machine]=$(ssh "$HOST" cat "/home/$USER/.config/CGAL/test_cgal_docker_images") || {
|
||||
ERROR_MACHINES="$ERROR_MACHINES $machine"
|
||||
}
|
||||
done
|
||||
if [ -n "$ERROR_MACHINES" ]; then
|
||||
printf '\n> %s\n> %s\n' '[!CAUTION]' 'ERROR:'
|
||||
for machine in $ERROR_MACHINES; do
|
||||
USER=${machine%@*}
|
||||
HOST=${machine#*@}
|
||||
# shellcheck disable=SC2016
|
||||
printf '> - ERROR: cannot read file `/home/%s/.config/CGAL/test_cgal_docker_images` on ssh host `%s`\n' "$USER" "$HOST"
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
cat <<HEREDOC
|
||||
# Test runner machines #
|
||||
|
||||
The following machines are used to run the tests:
|
||||
HEREDOC
|
||||
|
||||
for machine in "${TEST_MACHINES[@]}"; do
|
||||
USER=${machine%@*}
|
||||
HOST=${machine#*@}
|
||||
machine_title "$machine"
|
||||
if what_contains info; then
|
||||
machine_info "$HOST"
|
||||
fi
|
||||
if what_contains images; then
|
||||
printf '\nTested images:\n'
|
||||
machine_tested_images "$machine"
|
||||
fi
|
||||
if what_contains containers; then
|
||||
printf '\nCGAL test containers:\n'
|
||||
machine_list_cgal_test_container "$HOST" "$USER" | pretty_csv
|
||||
fi
|
||||
done
|
||||
|
|
@ -365,6 +365,9 @@ run_test_on_platform()
|
|||
echo "CGAL_VERSION ${CGAL_GIT_VERSION}">> "$RESULT_FILE"
|
||||
fi
|
||||
sed -n '/The CXX compiler/s/-- The CXX compiler identification is/COMPILER_VERSION =/p' < "${CGAL_BINARY_DIR}/installation.log" |sed -E "s/ = (.*)/\ = '\1\'/">> "$RESULT_FILE"
|
||||
if [ -n "${CGAL_SUMMARY_NAME}" ]; then
|
||||
echo "CGAL_SUMMARY_NAME ${CGAL_SUMMARY_NAME}" >> "$RESULT_FILE"
|
||||
fi
|
||||
echo "TESTER ${CGAL_TESTER}" >> "$RESULT_FILE"
|
||||
echo "TESTER_NAME ${CGAL_TESTER}" >> "$RESULT_FILE"
|
||||
echo "TESTER_ADDRESS ${TESTER_ADDRESS}" >> "$RESULT_FILE"
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ fi
|
|||
|
||||
#check no file contains non-utf8 characters
|
||||
echo '.. Checking if non utf-8 characters are used...'
|
||||
txt_not_utf8=$(git ls-files -z --stage | awk -F"\t" 'BEGIN { RS="\0" }; { printf "%s\n", $2; }' | xargs file -N | grep "text" | grep -E -v "UTF-8|ASCII|CSV|XML|EPS|FIG|assembler source|Perl script|from flex")
|
||||
txt_not_utf8=$(git ls-files -z --stage | awk -F"\t" 'BEGIN { RS="\0" }; { printf "%s\n", $2; }' | xargs file -N | grep "text" | grep -E -v "UTF-8|ASCII|CSV|XML|EPS|FIG|JSON|pixmap|magic|assembler source|Perl script|from flex")
|
||||
if [ -n "${txt_not_utf8}" ]; then
|
||||
echo "The following files have non utf-8 characters:"
|
||||
echo ${txt_not_utf8}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ public:
|
|||
*/
|
||||
MixedIntegerProgramVariable(MixedIntegerProgramTraits* solver, Variable_type type, FT lb =, FT ub, const std::string& name, int idx);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Operations
|
||||
/// @{
|
||||
|
||||
|
|
@ -131,6 +133,8 @@ public:
|
|||
*/
|
||||
MixedIntegerProgramLinearConstraint(MixedIntegerProgramTraits* solver, FT lb, FT ub, const std::string& name, int idx);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Operations
|
||||
/// @{
|
||||
|
||||
|
|
@ -238,6 +242,8 @@ public:
|
|||
*/
|
||||
MixedIntegerProgramLinearObjective(MixedIntegerProgramTraits* solver, Sense sense);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Operations
|
||||
/// @{
|
||||
|
||||
|
|
|
|||
|
|
@ -156,9 +156,9 @@ bool read_multi_point_WKT(std::istream& in,
|
|||
//!
|
||||
//! The first line starting with LINESTRING in the stream will be used.
|
||||
//!
|
||||
//! \tparam Linestring must be a model of `RandomAccessRange` of `CGAL::Point_2`,
|
||||
//! \tparam Linestring must be a model of `RandomAccessRange` of `CGAL::Point_2` or `CGAL::Point_3`,
|
||||
//! and have:
|
||||
//! - a function `push_back()` that takes a `CGAL::Point_2`.
|
||||
//! - a function `push_back()` that takes a point.
|
||||
//! - a function `clear()`,
|
||||
//! - a function `resize()` that takes a `size_type`
|
||||
//! - an `operator[]()` that takes a `size_type`.
|
||||
|
|
@ -166,6 +166,7 @@ bool read_multi_point_WKT(std::istream& in,
|
|||
//! \attention Only %Cartesian Kernels with double or float as `FT` are supported.
|
||||
//!
|
||||
//! \see `CGAL::Point_2`
|
||||
//! \see `CGAL::Point_3`
|
||||
template<typename LineString>
|
||||
bool read_linestring_WKT(std::istream& in,
|
||||
LineString& polyline)
|
||||
|
|
@ -209,7 +210,6 @@ bool read_linestring_WKT(std::istream& in,
|
|||
//!
|
||||
//! \attention Only %Cartesian Kernels with double or float as `FT` are supported.
|
||||
//!
|
||||
//! \see `CGAL::Point_2`
|
||||
template<typename MultiLineString>
|
||||
bool read_multi_linestring_WKT(std::istream& in,
|
||||
MultiLineString& mls)
|
||||
|
|
@ -359,11 +359,12 @@ bool read_multi_polygon_WKT(std::istream& in,
|
|||
//!
|
||||
//! \brief writes `point` into a WKT stream.
|
||||
//!
|
||||
//! \tparam Point is a `CGAL::Point_2`
|
||||
//! \tparam Point is a `CGAL::Point_2` or `CGAL::Point_3`
|
||||
//!
|
||||
//! \attention Only %Cartesian Kernels with double or float as `FT` are supported.
|
||||
//!
|
||||
//! \see `CGAL::Point_2`
|
||||
//! \see `CGAL::Point_3`
|
||||
template<typename Point>
|
||||
std::ostream& write_point_WKT(std::ostream& out,
|
||||
const Point& point)
|
||||
|
|
@ -399,11 +400,12 @@ std::ostream& write_polygon_WKT(std::ostream& out,
|
|||
//!
|
||||
//! \brief writes the content of `ls` into a WKT stream.
|
||||
//!
|
||||
//! \tparam LineString must be a `RandomAccessRange` of `CGAL::Point_2`.
|
||||
//! \tparam LineString must be a `RandomAccessRange` of `CGAL::Point_2` or `CGAL::Point_3`.
|
||||
//!
|
||||
//! \attention Only %Cartesian Kernels with double or float as `FT` are supported.
|
||||
//!
|
||||
//!\see `CGAL::Point_2`
|
||||
//!\see `CGAL::Point_3`
|
||||
template<typename LineString>
|
||||
std::ostream& write_linestring_WKT(std::ostream& out,
|
||||
LineString ls)
|
||||
|
|
@ -420,11 +422,12 @@ std::ostream& write_linestring_WKT(std::ostream& out,
|
|||
//!
|
||||
//! \brief writes the content of `mp` into a WKT stream.
|
||||
//!
|
||||
//! \tparam MultiPoint must be a `RandomAccessRange` of `CGAL::Point_2`.
|
||||
//! \tparam MultiPoint must be a `RandomAccessRange` of `CGAL::Point_2` or `CGAL::Point_3`.
|
||||
//!
|
||||
//! \attention Only %Cartesian Kernels with double or float as `FT` are supported.
|
||||
//!
|
||||
//!\see `CGAL::Point_2`
|
||||
//!\see `CGAL::Point_2`
|
||||
template<typename MultiPoint>
|
||||
std::ostream& write_multi_point_WKT(std::ostream& out,
|
||||
MultiPoint& mp)
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
#include <CGAL/IO/WKT.h>
|
||||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
|
|
@ -17,7 +17,69 @@ typedef std::vector<Point> MultiPoint
|
|||
typedef std::vector<Linestring> MultiLinestring;
|
||||
typedef std::vector<Poly> MultiPolygon;
|
||||
|
||||
|
||||
typedef CGAL::Point_3<Kernel> Point3;
|
||||
typedef std::vector<Point3> Linestring3;
|
||||
typedef std::vector<Point3> MultiPoint3;
|
||||
typedef std::vector<Linestring3> MultiLinestring3;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool test_WKT_3D()
|
||||
{
|
||||
{
|
||||
Point3 p(1,2,3), q(0,0,0);
|
||||
std::stringstream ss;
|
||||
CGAL::IO::write_point_WKT(ss, p);
|
||||
bool b = CGAL::IO::read_point_WKT(ss, q);
|
||||
assert(b);
|
||||
CGAL_USE(b);
|
||||
assert(p == q);
|
||||
}
|
||||
{
|
||||
Point3 p(1,2,3), q(3,2,1);
|
||||
MultiPoint3 mp, mq;
|
||||
mp.push_back(p);
|
||||
mp.push_back(q);
|
||||
std::stringstream ss;
|
||||
CGAL::IO::write_multi_point_WKT(ss, mp);
|
||||
bool b = CGAL::IO::read_multi_point_WKT(ss, mq);
|
||||
assert(b);
|
||||
CGAL_USE(b);
|
||||
assert(mp == mq);
|
||||
}
|
||||
{
|
||||
Point3 p(1,2,3), q(3,2,1);
|
||||
Linestring3 mp, mq;
|
||||
mp.push_back(p);
|
||||
mp.push_back(q);
|
||||
std::stringstream ss;
|
||||
CGAL::IO::write_linestring_WKT(ss, mp);
|
||||
bool b = CGAL::IO::read_linestring_WKT(ss, mq);
|
||||
assert(b);
|
||||
CGAL_USE(b);
|
||||
assert(mp == mq);
|
||||
}
|
||||
{
|
||||
Point3 p(1,2,3), q(3,2,1), r(4,5,6);
|
||||
Linestring3 mp, mq;
|
||||
mp.push_back(p);
|
||||
mp.push_back(q);
|
||||
mq.push_back(p);
|
||||
mq.push_back(r);
|
||||
MultiLinestring3 mmp, mmq;
|
||||
mmp.push_back(mp);
|
||||
mmp.push_back(mq);
|
||||
std::stringstream ss;
|
||||
CGAL::IO::write_multi_linestring_WKT(ss, mmp);
|
||||
bool b = CGAL::IO::read_multi_linestring_WKT(ss, mmq);
|
||||
assert(b);
|
||||
CGAL_USE(b);
|
||||
assert(mmp == mmq);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Read
|
||||
|
||||
|
|
@ -273,6 +335,8 @@ int main()
|
|||
assert(ok);
|
||||
ok = test_write_WKT();
|
||||
assert(ok);
|
||||
ok = test_WKT_3D();
|
||||
assert(ok);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ The type of the surface mesh to simplify. Must be a model of the `MutableFaceGra
|
|||
*/
|
||||
typedef Edge_profile::Triangle_mesh TriangleMesh;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Operations
|
||||
/// @{
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ int main(int argc, char* argv[])
|
|||
output.close();
|
||||
|
||||
// Output skeleton points and the corresponding surface points
|
||||
output.open("correspondance.cgal");
|
||||
output.open("correspondence.cgal");
|
||||
for(Skeleton_vertex v : vertices(skeleton))
|
||||
for(vertex_descriptor vd : skeleton[v].vertices)
|
||||
output << "2 " << skeleton[v].point << " " << get(CGAL::vertex_point, tmesh, vd) << "\n";
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ int main()
|
|||
output.close();
|
||||
|
||||
// Output skeleton points and the corresponding surface points
|
||||
output.open("correspondance-lcc.polylines.txt");
|
||||
output.open("correspondence-lcc.polylines.txt");
|
||||
for(Skeleton_vertex v : CGAL::make_range(vertices(skeleton)))
|
||||
for(vertex_descriptor vd : skeleton[v].vertices)
|
||||
output << "2 " << skeleton[v].point << " " << get(CGAL::vertex_point, lcc, vd) << "\n";
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ int main(int argc, char* argv[])
|
|||
output.close();
|
||||
|
||||
// Output skeleton points and the corresponding surface points
|
||||
output.open("correspondance-poly.polylines.txt");
|
||||
output.open("correspondence-poly.polylines.txt");
|
||||
for(Skeleton_vertex v : CGAL::make_range(vertices(skeleton)))
|
||||
for(vertex_descriptor vd : skeleton[v].vertices)
|
||||
output << "2 " << skeleton[v].point << " " << get(CGAL::vertex_point, tmesh, vd) << "\n";
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ int main(int argc, char* argv[])
|
|||
output.close();
|
||||
|
||||
// Output skeleton points and the corresponding surface points
|
||||
output.open("correspondance-sm.polylines.txt");
|
||||
output.open("correspondence-sm.polylines.txt");
|
||||
for(Skeleton_vertex v : CGAL::make_range(vertices(skeleton)))
|
||||
for(vertex_descriptor vd : skeleton[v].vertices)
|
||||
output << "2 " << skeleton[v].point << " " << get(CGAL::vertex_point, tmesh, vd) << "\n";
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ int main(int argc, char* argv[])
|
|||
output.close();
|
||||
|
||||
// Output skeleton points and the corresponding surface points
|
||||
output.open("correspondance-sm.polylines.txt");
|
||||
output.open("correspondence-sm.polylines.txt");
|
||||
for(Skeleton_vertex v : CGAL::make_range(vertices(skeleton)))
|
||||
for(vertex_descriptor vd : skeleton[v].vertices)
|
||||
output << "2 " << skeleton[v].point << " " << get(CGAL::vertex_point, tmesh, vd) << "\n";
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue