From edc8892f743651706ce4c6773dd66802bf36db04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20M=C3=B6ller?= Date: Tue, 18 Sep 2012 12:14:41 +0000 Subject: [PATCH] Add Kernel_d doc. --- .gitattributes | 59 ++ Documentation/doxyassist.xml | 16 +- Kernel_d/doc/Kernel_d/CGAL/Cartesian_d.h | 29 + Kernel_d/doc/Kernel_d/CGAL/Homogeneous_d.h | 29 + .../CGAL/Kernel_d/Aff_transformation_d.h | 158 ++++++ .../doc/Kernel_d/CGAL/Kernel_d/Direction_d.h | 176 ++++++ .../doc/Kernel_d/CGAL/Kernel_d/Hyperplane_d.h | 237 ++++++++ .../doc/Kernel_d/CGAL/Kernel_d/Iso_box_d.h | 99 ++++ Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Line_d.h | 163 ++++++ Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Point_d.h | 249 +++++++++ Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Ray_d.h | 157 ++++++ .../doc/Kernel_d/CGAL/Kernel_d/Segment_d.h | 219 ++++++++ .../doc/Kernel_d/CGAL/Kernel_d/Sphere_d.h | 222 ++++++++ .../doc/Kernel_d/CGAL/Kernel_d/Vector_d.h | 311 +++++++++++ Kernel_d/doc/Kernel_d/CGAL/Linear_algebraCd.h | 31 ++ Kernel_d/doc/Kernel_d/CGAL/Linear_algebraHd.h | 32 ++ Kernel_d/doc/Kernel_d/CGAL/constructions_d.h | 77 +++ Kernel_d/doc/Kernel_d/CGAL/intersections_d.h | 150 +++++ Kernel_d/doc/Kernel_d/CGAL/predicates_d.h | 194 +++++++ Kernel_d/doc/Kernel_d/Classified.txt | 8 + .../Kernel_d/Concepts/Kernel--Affine_rank_d.h | 29 + .../Concepts/Kernel--Affinely_independent_d.h | 31 ++ .../Kernel--CartesianConstIterator_d.h | 25 + .../Concepts/Kernel--Center_of_sphere_d.h | 28 + .../Kernel--Compare_lexicographically_d.h | 30 + .../Concepts/Kernel--Component_accessor_d.h | 41 ++ .../Concepts/Kernel--Compute_coordinate_d.h | 25 + ...ernel--ConstructCartesianConstIterator_d.h | 28 + .../Kernel--Contained_in_affine_hull_d.h | 30 + .../Kernel--Contained_in_linear_hull_d.h | 29 + .../Concepts/Kernel--Contained_in_simplex_d.h | 30 + .../doc/Kernel_d/Concepts/Kernel--Equal_d.h | 28 + .../Concepts/Kernel--Has_on_positive_side_d.h | 27 + .../Kernel_d/Concepts/Kernel--Intersect_d.h | 30 + .../Concepts/Kernel--Less_coordinate_d.h | 30 + .../Kernel--Less_lexicographically_d.h | 29 + ...ernel--Less_or_equal_lexicographically_d.h | 29 + .../Concepts/Kernel--Lift_to_paraboloid_d.h | 27 + .../Kernel_d/Concepts/Kernel--Linear_base_d.h | 33 ++ .../Kernel_d/Concepts/Kernel--Linear_rank_d.h | 29 + .../Concepts/Kernel--Linearly_independent_d.h | 30 + .../Kernel_d/Concepts/Kernel--Midpoint_d.h | 26 + .../Kernel_d/Concepts/Kernel--Orientation_d.h | 36 ++ .../Concepts/Kernel--Oriented_side_d.h | 27 + .../Concepts/Kernel--Orthogonal_vector_d.h | 24 + .../Concepts/Kernel--Point_dimension_d.h | 25 + .../Concepts/Kernel--Point_of_sphere_d.h | 24 + .../Concepts/Kernel--Point_to_vector_d.h | 24 + .../Concepts/Kernel--Project_along_d_axis_d.h | 25 + .../Kernel--Side_of_bounded_sphere_d.h | 31 ++ .../Kernel--Side_of_oriented_sphere_d.h | 33 ++ .../Concepts/Kernel--Squared_distance_d.h | 28 + .../Kernel_d/Concepts/Kernel--Value_at_d.h | 28 + .../Concepts/Kernel--Vector_to_point_d.h | 24 + Kernel_d/doc/Kernel_d/Concepts/Kernel_d.h | 365 +++++++++++++ .../Kernel_d/Concepts/LinearAlgebraTraits_d.h | 183 +++++++ Kernel_d/doc/Kernel_d/Concepts/Matrix.h | 354 ++++++++++++ Kernel_d/doc/Kernel_d/Concepts/Vector.h | 172 ++++++ Kernel_d/doc/Kernel_d/Kernel_d.txt | 516 ++++++++++++++++++ Kernel_d/doc/Kernel_d/PackageDescription.txt | 34 ++ Kernel_d/doc/Kernel_d/fig/hypercube.png | Bin 0 -> 18676 bytes 61 files changed, 5212 insertions(+), 1 deletion(-) create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Cartesian_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Homogeneous_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Aff_transformation_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Direction_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Hyperplane_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Iso_box_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Line_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Point_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Ray_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Segment_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Sphere_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Vector_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Linear_algebraCd.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/Linear_algebraHd.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/constructions_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/intersections_d.h create mode 100644 Kernel_d/doc/Kernel_d/CGAL/predicates_d.h create mode 100644 Kernel_d/doc/Kernel_d/Classified.txt create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Affine_rank_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Affinely_independent_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--CartesianConstIterator_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Center_of_sphere_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Compare_lexicographically_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Component_accessor_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Compute_coordinate_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--ConstructCartesianConstIterator_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_affine_hull_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_linear_hull_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_simplex_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Equal_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Has_on_positive_side_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Intersect_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_coordinate_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_lexicographically_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_or_equal_lexicographically_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Lift_to_paraboloid_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Linear_base_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Linear_rank_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Linearly_independent_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Midpoint_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Orientation_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Oriented_side_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Orthogonal_vector_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_dimension_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_of_sphere_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_to_vector_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Project_along_d_axis_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Side_of_bounded_sphere_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Side_of_oriented_sphere_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Squared_distance_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Value_at_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel--Vector_to_point_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Kernel_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/LinearAlgebraTraits_d.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Matrix.h create mode 100644 Kernel_d/doc/Kernel_d/Concepts/Vector.h create mode 100644 Kernel_d/doc/Kernel_d/Kernel_d.txt create mode 100644 Kernel_d/doc/Kernel_d/PackageDescription.txt create mode 100644 Kernel_d/doc/Kernel_d/fig/hypercube.png diff --git a/.gitattributes b/.gitattributes index 24b4e3da566..5a3be227975 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3010,6 +3010,65 @@ Kernel_23/include/CGAL/internal/Projection_traits_3.h -text Kernel_23/test/Kernel_23/include/CGAL/_Result_of_kernel.h -text Kernel_23/test/Kernel_23/overload_bug.cpp -text Kernel_23/test/Kernel_23/test_result_of.cpp -text +Kernel_d/doc/Kernel_d/CGAL/Cartesian_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Homogeneous_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Aff_transformation_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Direction_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Hyperplane_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Iso_box_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Line_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Point_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Ray_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Segment_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Sphere_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Vector_d.h -text +Kernel_d/doc/Kernel_d/CGAL/Linear_algebraCd.h -text +Kernel_d/doc/Kernel_d/CGAL/Linear_algebraHd.h -text +Kernel_d/doc/Kernel_d/CGAL/constructions_d.h -text +Kernel_d/doc/Kernel_d/CGAL/intersections_d.h -text +Kernel_d/doc/Kernel_d/CGAL/predicates_d.h -text +Kernel_d/doc/Kernel_d/Classified.txt -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Affine_rank_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Affinely_independent_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--CartesianConstIterator_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Center_of_sphere_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Compare_lexicographically_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Component_accessor_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Compute_coordinate_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--ConstructCartesianConstIterator_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_affine_hull_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_linear_hull_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_simplex_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Equal_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Has_on_positive_side_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Intersect_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_coordinate_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_lexicographically_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_or_equal_lexicographically_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Lift_to_paraboloid_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Linear_base_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Linear_rank_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Linearly_independent_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Midpoint_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Orientation_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Oriented_side_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Orthogonal_vector_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_dimension_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_of_sphere_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_to_vector_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Project_along_d_axis_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Side_of_bounded_sphere_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Side_of_oriented_sphere_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Squared_distance_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Value_at_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel--Vector_to_point_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Kernel_d.h -text +Kernel_d/doc/Kernel_d/Concepts/LinearAlgebraTraits_d.h -text +Kernel_d/doc/Kernel_d/Concepts/Matrix.h -text +Kernel_d/doc/Kernel_d/Concepts/Vector.h -text +Kernel_d/doc/Kernel_d/Kernel_d.txt -text +Kernel_d/doc/Kernel_d/PackageDescription.txt -text +Kernel_d/doc/Kernel_d/fig/hypercube.png -text svneol=unset#image/png Kernel_d/doc_tex/Kernel_d/hypercube.png -text Kernel_d/doc_tex/Kernel_d_ref/Kernel_Compute_coordinate_d.tex -text Kernel_d/doc_tex/Kernel_d_ref/Kernel_Less_coordinate_d.tex -text diff --git a/Documentation/doxyassist.xml b/Documentation/doxyassist.xml index 225102e4fd2..e323f198a07 100644 --- a/Documentation/doxyassist.xml +++ b/Documentation/doxyassist.xml @@ -468,12 +468,24 @@ namespace for the XML file to be processed properly. --> ../Algebraic_kernel_d/doc/Algebraic_kernel_d/ ../Algebraic_kernel_d/doc/Algebraic_kernel_d/ ./tags/Algebraic_kernel_d.tag - ../Algebraic_kernel_d/examples ../Algebraic_kernel_d/doc/Algebraic_kernel_d/fig true + + dD Geometry Kernel + ../Kernel_d/doc + + ../Kernel_d/doc/Kernel_d/ + ../Kernel_d/doc/Kernel_d/ + ../Kernel_d/doc/Kernel_d/ + ./tags/Kernel_d.tag + ../Kernel_d/examples + ../Kernel_d/doc/Kernel_d/fig + true + + Convex Decomposition of Polyhedra @@ -1141,6 +1153,7 @@ namespace for the XML file to be processed properly. --> ../Circular_kernel_2/doc/Circular_kernel_2/fig ../Circular_kernel_3/doc/Circular_kernel_3/fig ../Algebraic_kernel_d/doc/Algebraic_kernel_d/fig + ../Kernel_d/doc/Kernel_d/fig ../Point_set_2/doc/Point_set_2/fig ../SearchStructures/doc/SearchStructures/fig ../Polytope_distance_d/doc/Polytope_distance_d/fig @@ -1212,6 +1225,7 @@ namespace for the XML file to be processed properly. --> ./tags/Circular_kernel_2.tag=../../CGAL.CGAL.2D-Circular-Geometry-Kernel/html ./tags/Circular_kernel_3.tag=../../CGAL.CGAL.3D-Spherical-Geometry-Kernel/html ./tags/Algebraic_kernel_d.tag=../../CGAL.CGAL.Algebraic-Kernel/html + ./tags/Kernel_d.tag=../../CGAL.CGAL.dD-Geometry-Kernel/html ./tags/Point_set_2.tag=../../CGAL.CGAL.2D-Range-and-Neighbor-Search/html ./tags/SearchStructures.tag=../../CGAL.CGAL.dD-Range-and-Segment-Trees/html ./tags/Polyhedron.tag=../../CGAL.CGAL.3D-Polyhedral-Surface/html diff --git a/Kernel_d/doc/Kernel_d/CGAL/Cartesian_d.h b/Kernel_d/doc/Kernel_d/CGAL/Cartesian_d.h new file mode 100644 index 00000000000..d054bae5e71 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Cartesian_d.h @@ -0,0 +1,29 @@ + +namespace CGAL { + +/*! +\ingroup PkgKernelDKernels + +A model for `Kernel_d` that uses Cartesian coordinates to represent the +geometric objects. In order for `Cartesian_d` to model Euclidean geometry +in \f$ E^d\f$ , for some mathematical field \f$ E\f$ (e.g., +the rationals \f$\mathbb{Q}\f$ or the reals \f$\mathbb{R}\f$), the template parameter `FieldNumberType` +must model the mathematical field \f$ E\f$. That is, the field operations on this +number type must compute the mathematically correct results. If the number +type provided as a model for `FieldNumberType` is only an approximation of a +field (such as the built-in type `double`), then the geometry provided by +the kernel is only an approximation of Euclidean geometry. + +\models ::Kernel_d + +\sa `CGAL::Homogeneous_d` + +*/ +template< typename FieldNumberType > +class Cartesian_d { +public: + +/// @} + +}; /* end Cartesian_d */ +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Homogeneous_d.h b/Kernel_d/doc/Kernel_d/CGAL/Homogeneous_d.h new file mode 100644 index 00000000000..da6712d36cf --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Homogeneous_d.h @@ -0,0 +1,29 @@ + +namespace CGAL { + +/*! +\ingroup PkgKernelDKernels + +A model for a `Kernel_d` using homogeneous coordinates to represent the +geometric objects. In order for `Homogeneous` to model Euclidean geometry +in \f$ E^d\f$, for some mathematical ring \f$ E\f$ (e.g., +the integers \f$\mathbb{Z}\f$ or the rationals \f$\mathbb{Q}\f$), the template parameter `RT` +must model the mathematical ring \f$ E\f$. That is, the ring operations on this +number type must compute the mathematically correct results. If the number +type provided as a model for `RingNumberType` is only an approximation of a +ring (such as the built-in type `double`), then the geometry provided by +the kernel is only an approximation of Euclidean geometry. + +\models ::Kernel_d + +\sa `CGAL::Cartesian_d` + +*/ +template< typename RingNumberType > +class Homogeneous { +public: + +/// @} + +}; /* end Homogeneous */ +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Aff_transformation_d.h b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Aff_transformation_d.h new file mode 100644 index 00000000000..34371c69c78 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Aff_transformation_d.h @@ -0,0 +1,158 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDKernelObjs + +An instance of the data type `Aff_transformation_d` is an +affine transformation of \f$ d\f$-dimensional space. It is specified by a +square matrix \f$ M\f$ of dimension \f$ d + 1\f$. All entries in the last row of +`M` except the diagonal entry must be zero; the diagonal entry +must be non-zero. A point \f$ p\f$ with homogeneous coordinates \f$ (p[0], +\ldots, p[d])\f$ can be transformed into the point `p.transform(A)` += \f$ Mp\f$, where `A` is an affine transformation created from `M` +by the constructors below. + +Implementation +-------------- + +Affine Transformations are implemented by matrices of number type +`RT` as a handle type. All operations like creation, +initialization, input and output on a transformation \f$ t\f$ take time +\f$ O(t.dimension()^2)\f$. `dimension()` takes constant time. +The operations for inversion and composition have the cubic costs of +the used matrix operations. The space requirement is +\f$ O(t.dimension()^2)\f$. + +*/ +template< typename Kernel > +class Aff_transformation_d { +public: + +/// \name Types +/// @{ + +/*! +the linear algebra layer. +*/ +typedef Hidden_type LA; + +/*! +the matrix type. +*/ +typedef Hidden_type Matrix; + +/// @} + +/// \name Creation +/// @{ + +/*! +introduces some +transformation. +*/ +Aff_transformation_d(); + +/*! +introduces the identity transformation in +\f$ d\f$-dimensional space. +*/ +Aff_transformation_d(int d, +Identity_transformation); + +/*! +introduces the +transformation of \f$ d\f$-space specified by matrix \f$ M\f$. + +\pre `M` is a square matrix of dimension \f$ d + 1\f$ where entries in the last row of `M` except the diagonal entry must be zero; the diagonal entry must be non-zero. +*/ +Aff_transformation_d(Matrix M); + +/*! +introduces the transformation of \f$ d\f$-space +specified by a diagonal matrix with entries `set [start,end)` on +the diagonal (a scaling of the space). + +\pre `set [start,end)` is a vector of dimension \f$ d+1\f$. +*/ +template +Aff_transformation_d(Scaling, Forward_iterator start, +Forward_iterator end); + +/*! +introduces the translation by vector \f$ v\f$. +*/ +Aff_transformation_d(Translation, Vector_d +v); + +/*! +returns a scaling by a scale factor `num/den`. + +\pre `den !=0 `. +*/ +Aff_transformation_d(int d, Scaling, RT num, RT +den); + +/*! +returns a planar rotation +with sine and cosine values `sin_num/den` and `cos_num/den` +in the plane spanned by the base vectors \f$ b_{e1}\f$ and \f$ b_{e2}\f$ in +\f$ d\f$-space. Thus the default use delivers a planar rotation in the +\f$ x\f$-\f$ y\f$ plane. + +\pre \f$ sin_num^2 + cos_num^2 = den^2\f$ and \f$ 0 \leq e_1 < e_2 < d\f$. +\pre `den != 0`. + +*/ +Aff_transformation_d(int d, Rotation, RT sin_num, RT +cos_num, RT den, int e1 = 0, int e2 = 1); + +/*! +returns a planar +rotation within a two-dimensional linear subspace. The subspace is +spanned by the base vectors \f$ b_{e1}\f$ and \f$ b_{e2}\f$ in \f$ d\f$-space. The +rotation parameters are given by the \f$ 2\f$-dimensional direction +`dir`, such that the difference between the sines and cosines of +the rotation given by `dir` and the approximated rotation are at +most `num/den` each. +\pre `dir.dimension()==2`, `!dir.is_degenerate()` and `num < den` is positive, `den != 0`, \f$ 0 \leq e_1 < e_2 < d\f$. +*/ +Aff_transformation_d(int d, Rotation, Direction_d +dir, RT num, RT den, int e1 = 0, int e2 = 1); + +/// @} + +/// \name Operations +/// @{ + +/*! +the dimension of the underlying space +*/ +int dimension() ; + +/*! +returns the transformation matrix + +*/ +const Matrix& matrix() ; + +/*! +returns the inverse +transformation. + +\pre `t.matrix()` is invertible. +*/ +Aff_transformation_d inverse() ; + +/*! +composition of transformations. Note +that transformations are not necessarily commutative. `t*s` is +the transformation which transforms first by `t` and then by +`s`. +*/ +Aff_transformation_d operator*(const +Aff_transformation_d& s) ; + +/// @} + +}; /* end Aff_transformation_d */ +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Direction_d.h b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Direction_d.h new file mode 100644 index 00000000000..ce964cec203 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Direction_d.h @@ -0,0 +1,176 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDKernelObjs + +A `Direction_d` is a vector in the \f$ d\f$-dimensional vector space +where we forget about its length. We represent directions in +\f$ d\f$-dimensional space as a tuple \f$ (h_0,\ldots,h_d)\f$ of variables of +type `RT` which we call the homogeneous coordinates of the +direction. The coordinate \f$ h_d\f$ must be positive. The Cartesian +coordinates of a direction are \f$ c_i = h_i/h_d\f$ for \f$ 0 \le i < d\f$, +which are of type `FT`. Two directions are equal if their +Cartesian coordinates are positive multiples of each other. Directions +are in one-to-one correspondence to points on the unit sphere. + +Downward compatibility +-------------- + +We provide the operations of the lower dimensional interface `dx()`, +`dy()`, `dz()`. + +Implementation +-------------- + +Directions are implemented by arrays of integers as an item type. All +operations like creation, initialization, tests, inversion, input and +output on a direction \f$ d\f$ take time \f$ O(d.\mathit{dimension}())\f$. +`dimension()`, coordinate access and conversion take constant +time. The space requirement is \f$ O(d.\mathit{dimension}())\f$. + +*/ +template< typename Kernel > +class Direction_d { +public: + +/// \name Types +/// @{ + +/*! +the linear algebra layer. +*/ +typedef Hidden_type LA; + +/*! + +a read-only iterator for the deltas of `dir`. +*/ +typedef Hidden_type Delta_const_iterator; + +/*! +construction tag. +*/ +typedef Hidden_type Base_direction; + +/// @} + +/// \name Creation +/// @{ + +/*! +introduces a variable `dir` of +type `Direction_d`. +*/ +Direction_d(); + +/*! + +introduces a variable `dir` of type `Direction_d` +initialized to the direction of `v`. +*/ +Direction_d(Vector_d v); + +/*! + +introduces a variable `dir` of type `Direction_d` in +dimension `d` with representation tuple `set [first,last)`. +\pre `d` is nonnegative, `[first,last)` has `d` elements. +\requires The value type of `InputIterator` is `RT`. +*/ +template +Direction_d(int d, InputIterator first, InputIterator last); + +/*! +returns +a variable `dir` of type `Direction_d` initialized to the +direction of the \f$ i\f$-th base vector of dimension \f$ d\f$. + +\pre \f$ 0 \leq i < d\f$. +*/ +Direction_d(int d, Base_direction, int i); + +/*! + +introduces a variable `dir` of type `Direction_d` in +\f$ 2\f$-dimensional space. +*/ +Direction_d(RT x, RT y); + +/*! + +introduces a variable `dir` of type `Direction_d` in +\f$ 3\f$-dimensional space. +*/ +Direction_d(RT x, RT y, RT z); + +/// @} + +/// \name Operations +/// @{ + +/*! + +returns the dimension of `dir`. +*/ +int dimension() ; + +/*! + +returns the \f$ i\f$-th component of `dir`. +\pre \f$ 0 \leq i < d\f$. +*/ +RT delta(int i) ; + +/*! + +returns the \f$ i\f$-th delta of `dir`. +\pre \f$ 0 \leq i < d\f$. +*/ +RT operator[](int i) ; + +/*! + +returns an iterator pointing to the first delta of `dir`. +*/ +Delta_const_iterator deltas_begin() ; + +/*! + +returns an iterator pointing beyond the last delta of `dir`. +*/ +Delta_const_iterator deltas_end() ; + +/*! + +returns a vector pointing in direction `dir`. +*/ +Vector_d vector() ; + +/*! + +returns true iff `dir.delta(i)==0` for all \f$ 0\leq i < d\f$. +*/ +bool is_degenerate() ; + +/*! + +returns \f$ t(p)\f$. +*/ +Direction_d transform(const Aff_transformation_d& t) ; + +/*! + +returns the direction opposite to `dir`. +*/ +Direction_d opposite() ; + +/*! + +returns the direction opposite to `dir`. +*/ +Direction_d operator- () ; + +/// @} + +}; /* end Direction_d */ +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Hyperplane_d.h b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Hyperplane_d.h new file mode 100644 index 00000000000..05c6944d768 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Hyperplane_d.h @@ -0,0 +1,237 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDKernelObjs + +An instance of data type `Hyperplane_d` is an oriented hyperplane +in \f$ d\f$ - dimensional space. A hyperplane \f$ h\f$ is represented by +coefficients \f$ (c_0,c_1,\ldots,c_d)\f$ of type `RT`. At least one of +\f$ c_0\f$ to \f$ c_{ d - 1 }\f$ must be non-zero. The plane equation is +\f$ \sum_{ 0 \le i < d } c_i x_i + c_d = 0\f$, where \f$ x_0\f$ to \f$ x_{d-1}\f$ are +Cartesian point coordinates. For a particular \f$ x\f$ the sign of \f$ \sum_{ +0 \le i < d } c_i x_i + c_d\f$ determines the position of a point \f$ x\f$ +with respect to the hyperplane (on the hyperplane, on the negative +side, or on the positive side). + +There are two equality predicates for hyperplanes. The (weak) equality +predicate (`weak_equality`) declares two hyperplanes equal if they +consist of the same set of points, the strong equality predicate +(`operator==`) requires in addition that the negative halfspaces +agree. In other words, two hyperplanes are strongly equal if their +coefficient vectors are positive multiples of each other and they are +(weakly) equal if their coefficient vectors are multiples of each +other. + +Implementation +-------------- + +Hyperplanes are implemented by arrays of integers as an item type. +All operations like creation, initialization, tests, vector +arithmetic, input and output on a hyperplane \f$ h\f$ take time +\f$ O(h.dimension())\f$. coordinate access and `dimension()` take +constant time. The space requirement is \f$ O(h.dimension())\f$. + +*/ +template< typename Kernel > +class Hyperplane_d { +public: + +/// \name Types +/// @{ + +/*! +the linear algebra layer. +*/ +typedef Hidden_type LA; + +/*! +a read-only iterator for the +coefficients. +*/ +typedef Hidden_type Coefficient_const_iterator; + +/// @} + +/// \name Creation +/// @{ + +/*! +introduces a variable +`h` of type `Hyperplane_d`. +*/ +Hyperplane_d(); + +/*! +introduces a +variable `h` of type `Hyperplane_d` initialized to the +hyperplane with coefficients `set [first,last)` and `D`. +\pre `size [first,last) == d`. +\requires The value type of InputIterator is `RT`. +*/ +template Hyperplane_d(int d, +InputIterator first, InputIterator last, RT D); + +/*! +introduces a variable +`h` of type `Hyperplane_d` initialized to the hyperplane +with coefficients `set [first,last)`. + +\pre `size [first,last) == d+1`. +\requires The value type of InputIterator is `RT`. +*/ +template Hyperplane_d(int d, +InputIterator first, InputIterator last); + +/*! +constructs +some hyperplane that passes through the points in `set [first,last)`. If `side` is `ON_POSITIVE_SIDE` or +`ON_NEGATIVE_SIDE` then `o` is on that side of the +constructed hyperplane. + +\pre A hyperplane with the stated properties must exist. +\requires The value type of `ForwardIterator` is `Point_d`. +*/ +template +Hyperplane_d(ForwardIterator first, ForwardIterator last, +Point_d o, Oriented_side side = ON_ORIENTED_BOUNDARY); + +/*! +constructs the hyperplane with normal direction `dir` that +passes through \f$ p\f$. The direction `dir` points into the positive +side. + +\pre `p.dimension()==dir.dimension()` and `dir` is not degenerate. +*/ +Hyperplane_d(Point_d p, Direction_d +dir); + +/*! +introduces a +variable `h` of type `Hyperplane_d` in \f$ 2\f$-dimensional +space with equation \f$ ax+by+c=0\f$. +*/ +Hyperplane_d(RT a, RT b, RT c); + +/*! +introduces a +variable `h` of type `Hyperplane_d` in \f$ 3\f$-dimensional +space with equation \f$ ax+by+cz+d=0\f$. +*/ +Hyperplane_d(RT a, RT b, RT c, RT d); + +/// @} + +/// \name Operations +/// @{ + +/*! +returns the dimension of `h`. +*/ +int dimension() ; + +/*! +returns the \f$ i\f$-th coefficient of +`h`. + +\pre \f$ 0 \leq i \leq d\f$. +*/ +RT operator[](int i) ; + +/*! +returns the \f$ i\f$-th coefficient of +`h`. + +\pre \f$ 0 \leq i \leq d\f$. +*/ +RT coefficient(int i) ; + +/*! +returns +an iterator pointing to the first coefficient. +*/ +Coefficient_const_iterator coefficients_begin() ; + +/*! +returns an +iterator pointing beyond the last coefficient. +*/ +Coefficient_const_iterator coefficients_end() ; + +/*! +returns the orthogonal +vector of `h`. It points from the negative halfspace into the +positive halfspace and its homogeneous coordinates are \f$ (c_0, +\ldots, c_{d - 1},1)\f$. +*/ +Vector_d orthogonal_vector() ; + +/*! +returns the +orthogonal direction of `h`. It points from the negative +halfspace into the positive halfspace. +*/ +Direction_d orthogonal_direction() ; + +/*! +returns +the side of the hyperplane `h` containing \f$ p\f$. + +\pre `h.dimension() == p.dimension()`. +*/ +Oriented_side oriented_side(const Point_d& p) ; + +/*! +returns true iff point +`p` lies on the hyperplane `h`. + +\pre `h.dimension() == p.dimension()`. +*/ +bool has_on(const Point_d& p) ; + +/*! +returns true +iff point `p` lies on the boundary of hyperplane `h`. +\pre `h.dimension() == p.dimension()`. +*/ +bool has_on_boundary(const Point_d& p) ; + +/*! +returns +true iff point `p` lies on the positive side of hyperplane +`h`. + +\pre `h.dimension() == p.dimension()`. +*/ +bool has_on_positive_side(const Point_d& p) ; + +/*! +returns +true iff point `p` lies on the negative side of hyperplane +`h`. + +\pre `h.dimension() == p.dimension()`. +*/ +bool has_on_negative_side(const Point_d& p) ; + +/*! +returns \f$ t(h)\f$. + +\pre `h.dimension() == t.dimension()`. + +*/ +Hyperplane_d transform(const Aff_transformation_d& t) +; + +/// @} + +}; /* end Hyperplane_d */ + +/*! +test for weak equality. + +\pre `h1.dimension() == h2.dimension()`. +\relates Hyperplane_d +*/ +bool weak_equality(const Hyperplane_d& h1, const Hyperplane_d& h2) ; + +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Iso_box_d.h b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Iso_box_d.h new file mode 100644 index 00000000000..7d2b124f468 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Iso_box_d.h @@ -0,0 +1,99 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDKernelObjs + +An object \f$ b\f$ of the data type `Iso_box_d` is an +iso-box in the Euclidean space \f$ \E^d\f$ with edges parallel to the +axes of the coordinate system. + +*/ +template< typename Kernel > +class Iso_box_d { +public: + +/// \name Creation +/// @{ + +/*! +introduces an iso-oriented iso-box `b` with diagonal +opposite vertices \f$ p\f$ and \f$ q\f$. + +*/ +Iso_box_d(const Point_d& p, +const Point_d &q); + +/// @} + +/// \name Operations +/// @{ + +/*! +Test for equality: two iso-oriented cuboid are equal, iff their +lower left and their upper right vertices are equal. +*/ +bool operator==(const Iso_box_d& b2) const; + +/*! +Test for inequality. +*/ +bool operator!=(const Iso_box_d& b2) const; + +/*! +returns the smallest vertex of `b`. +*/ +const Point_d& min() const; + +/*! +returns the largest vertex of `b`. +*/ +const Point_d& max() const; + +/// @} + +/// \name Predicates +/// @{ + +/*! +`b` is degenerate, if all vertices +are collinear. +*/ +bool is_degenerate() const; + +/*! +returns either `ON_UNBOUNDED_SIDE`, +`ON_BOUNDED_SIDE`, or the constant +`ON_BOUNDARY`, +depending on where point \f$ p\f$ is. +*/ +Bounded_side bounded_side(const Point_d& p) const; + +/*! + +*/ +bool has_on_boundary(const Point_d& p) const; + +/*! + +*/ +bool has_on_bounded_side(const Point_d& p) const; + +/*! + +*/ +bool has_on_unbounded_side(const Point_d& p) const; + +/// @} + +/// \name Miscellaneous +/// @{ + +/*! +returns the volume of `b`. +*/ +Kernel_d::FT volume() const; + +/// @} + +}; /* end Iso_box_d */ +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Line_d.h b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Line_d.h new file mode 100644 index 00000000000..a8eac07ef5d --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Line_d.h @@ -0,0 +1,163 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDKernelObjs + +An instance of data type `Line_d` is an oriented line in +\f$ d\f$-dimensional Euclidean space. + +Implementation +-------------- + +Lines are implemented by a pair of points as an item type. All +operations like creation, initialization, tests, direction +calculation, input and output on a line \f$ l\f$ take time +\f$ O(l.dimension())\f$. `dimension()`, coordinate and point +access, and identity test take constant time. The operations for +intersection calculation also take time \f$ O(l.dimension())\f$. The +space requirement is \f$ O(l.dimension())\f$. + +*/ +template< typename Kernel > +class Line_d { +public: + +/// \name Types +/// @{ + +/*! +the linear algebra layer. + +*/ +typedef Hidden_type LA; + +/// @} + +/// \name Creation +/// @{ + +/*! +introduces a variable `l` of +type `Line_d`. +*/ +Line_d(); + +/*! +introduces a +line through `p` and `q` and oriented from `p` to +`q`. + +\pre \f$ p\f$ and \f$ q\f$ are distinct and have the same dimension. +*/ +Line_d(Point_d p, Point_d q); + +/*! +introduces +a line through `p` with direction `dir`. + +\pre `p.dimension()==dir.dimension()`, `dir` is not degenerate. +*/ +Line_d(Point_d p, Direction_d dir); + +/*! +introduces a variable +`l` of type `Line_d` and initializes it to the line through +`s.source()` and `s.target()` with direction from +`s.source()` to `s.target()`. + +\pre \f$ s\f$ is not degenerate. +*/ +Line_d(Segment_d s); + +/*! +introduces a variable `l` of +type `Line_d` and initializes it to the line through +`r.point(1)` and `r.point(2)`. +*/ +Line_d(Ray_d r); + +/// @} + +/// \name Operations +/// @{ + +/*! +returns the dimension of the ambient +space. +*/ +int dimension(); + +/*! +returns an arbitrary point on +`l`. It holds that `point(i) == point(j)`, iff +`i==j`. Furthermore, `l` is directed from `point(i)` to +`point(j)`, for all `i < j`. +*/ +Point_d point(int i) ; + +/*! +returns the line +`(point(2),point(1))` of opposite direction. +*/ +Line_d opposite() ; + +/*! +returns the direction of +`l`. +*/ +Direction_d direction(); + +/*! +returns \f$ t(l)\f$. + +\pre `l.dimension()==t.dimension()`. +*/ +Line_d transform(const Aff_transformation_d & +t); + +/*! +returns +`l+v`, i.e., `l` translated by vector \f$ v\f$. +\pre `l.dimension()==v.dimension()`. +*/ +Line_d operator+(const Vector_d& v); + +/*! +returns the +point of intersection of `l` with the hyperplane that is +orthogonal to `l` and that contains `p`. + +\pre `l.dimension()==p.dimension()`. +*/ +Point_d projection(const Point_d& p) ; + +/*! +returns true if \f$ p\f$ lies +on `l` and false otherwise. + +\pre `l.dimension()==p.dimension()`. +*/ +bool has_on(const Point_d& p) ; + +/// @} + +}; /* end Line_d */ + + +/*! +Test for equality as unoriented lines + +\pre `l1.dimension()==l2.dimension()`. +\relates Line_d +*/ +bool weak_equality(const Line_d& l1, const Line_d& l2) ; + +/*! +returns true if `l1` and `l2` are parallel as unoriented +lines and false otherwise. + +\pre `l1.dimension()==l2.dimension()`. +\relates Line_d +*/ +bool parallel(const Line_d& l1, const Line_d& l2) ; +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Point_d.h b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Point_d.h new file mode 100644 index 00000000000..71caa362595 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Point_d.h @@ -0,0 +1,249 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDKernelObjs + +An instance of data type `Point_d` is a point of Euclidean +space in dimension \f$ d\f$. A point \f$ p = (p_0,\ldots,p_{ d - 1 })\f$ in +\f$ d\f$-dimensional space can be represented by homogeneous coordinates +\f$ (h_0,h_1,\ldots,h_d)\f$ of number type `RT` such that \f$ p_i = +h_i/h_d\f$, which is of type `FT`. The homogenizing coordinate \f$ h_d\f$ +is positive. + +We call \f$ p_i\f$, \f$ 0 \leq i < d\f$ the \f$ i\f$-th Cartesian coordinate and +\f$ h_i\f$, \f$ 0 \le i \le d\f$, the \f$ i\f$-th homogeneous coordinate. We call \f$ d\f$ +the dimension of the point. + +Downward compatibility +-------------- + +We provide operations of the lower +dimensional interface `x()`, `y()`, `z()`, `hx()`, +`hy()`, `hz()`, `hw()`. + +Implementation +-------------- + +Points are implemented by arrays of `RT` items. All operations +like creation, initialization, tests, point - vector arithmetic, input +and output on a point \f$ p\f$ take time \f$ O(p.dimension())\f$. +`dimension()`, coordinate access and conversions take constant +time. The space requirement for points is \f$ O(p.dimension())\f$. + +*/ +template< typename Kernel > +class Point_d { +public: + +/// \name Types +/// @{ + +/*! +the linear algebra layer. +*/ +typedef Hidden_type LA; + +/*! +a read-only iterator for the +Cartesian coordinates. +*/ +typedef Hidden_type Cartesian_const_iterator; + +/*! +a read-only iterator for the +homogeneous coordinates. +*/ +typedef Hidden_type Homogeneous_const_iterator; + +/// @} + +/// \name Creation +/// @{ + +/*! +introduces a variable `p` of +type `Point_d`. +*/ +Point_d(); + +/*! +introduces a variable +`p` of type `Point_d` in \f$ d\f$-dimensional space, +initialized to the origin. +*/ +Point_d(int d, Origin); + +/*! +introduces a variable +`p` of type `Point_d` in dimension `d`. If `size [first,last) == d` this creates a point with Cartesian coordinates +`set [first,last)`. If `size [first,last) == d+1` the range +specifies the homogeneous coordinates +\f$ H = set [first,last) = (\pm h_0, \pm h_1, \ldots, \pm h_d)\f$ +where the sign chosen is the sign of \f$ h_d\f$. + +\pre `d` is nonnegative, `[first,last)` has `d` or `d+1` elements where the last has to be non-zero. +\requires The value type of `InputIterator` is `RT`. +*/ +template Point_d(int d, +InputIterator first, InputIterator last); + +/*! +introduces a +variable `p` of type `Point_d` in dimension `d` +initialized to the point with homogeneous coordinates as defined by +`H = set [first,last)` and `D`: \f$ (\pm H[0], +\pm H[1], \ldots, \pm H[d-1], \pm D}\f$. +The sign chosen is the sign of \f$ D\f$. + +\pre `D` is non-zero, the iterator range defines a \f$ d\f$-tuple of `RT`. +\requires The value type of `InputIterator` is `RT`. +*/ +template Point_d(int d, +InputIterator first, InputIterator last, RT D); + +/*! +introduces a variable +`p` of type `Point_d` in \f$ 2\f$-dimensional space. +\pre \f$ w \neq0\f$. +*/ +Point_d(RT x, RT y, RT w = 1); + +/*! +introduces a +variable `p` of type `Point_d` in \f$ 3\f$-dimensional +space. + +\pre \f$ w \neq0\f$. +*/ +Point_d(RT x, RT y, RT z, RT w); + +/// @} + +/// \name Operations +/// @{ + +/*! +returns the dimension of `p`. + +*/ +int dimension() ; + +/*! +returns the \f$ i\f$-th Cartesian +coordinate of `p`. + +\pre \f$ 0 \leq i < d\f$. +*/ +FT cartesian(int i) ; + +/*! +returns the \f$ i\f$-th Cartesian +coordinate of `p`. + +\pre \f$ 0 \leq i < d\f$. +*/ +FT operator[](int i) ; + +/*! +returns the \f$ i\f$-th homogeneous +coordinate of `p`. + +\pre \f$ 0 \leq i \leq d\f$. +*/ +RT homogeneous(int i) ; + +/*! +returns an +iterator pointing to the zeroth Cartesian coordinate \f$ p_0\f$ of +`p`. +*/ +Cartesian_const_iterator cartesian_begin() ; + +/*! +returns an +iterator pointing beyond the last Cartesian coordinate of `p`. + +*/ +Cartesian_const_iterator cartesian_end() ; + +/*! +returns +an iterator pointing to the zeroth homogeneous coordinate \f$ h_0\f$ of +`p`. +*/ +Homogeneous_const_iterator homogeneous_begin() ; + +/*! +returns an +iterator pointing beyond the last homogeneous coordinate of +`p`. +*/ +Homogeneous_const_iterator homogeneous_end() ; + +/*! +returns \f$ t(p)\f$. +*/ +Point_d transform(const Aff_transformation_d& t) +; + +/// @} + +/// \name Arithmetic Operators, Tests and IO +/// @{ + +/*! +returns the +vector \f$ p-O\f$. +*/ +Vector_d operator-(const Origin& o) ; + +/*! +returns \f$ p - +q\f$. + +\pre `p.dimension() == q.dimension()`. +*/ +Vector_d operator-(const Point_d& q) ; + +/*! +returns \f$ p + +v\f$. + +\pre `p.dimension() == v.dimension()`. +*/ +Point_d operator+(const Vector_d& v) ; + +/*! +returns \f$ p - +v\f$. + +\pre `p.dimension() == v.dimension()`. +*/ +Point_d operator-(const Vector_d& v) ; + +/*! +adds `v` +to `p`. + +\pre `p.dimension() == v.dimension()`. +*/ +Point_d& operator+=(const Vector_d& v); + +/*! +subtracts +`v` from `p`. + +\pre `p.dimension() == v.dimension()`. +*/ +Point_d& operator-=(const Vector_d& v); + +/*! +returns true if `p` is +the origin. +*/ +bool operator==(const Origin&) ; + +/// @} + +}; /* end Point_d */ +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Ray_d.h b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Ray_d.h new file mode 100644 index 00000000000..7571dac0b7c --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Ray_d.h @@ -0,0 +1,157 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDKernelObjs + +An instance of data type `Ray_d` is a ray in \f$ d\f$-dimensional +Euclidean space. It starts in a point called the source of `r` and +it goes to infinity. + +Implementation +-------------- + +Rays are implemented by a pair of points as an item type. All +operations like creation, initialization, tests, direction +calculation, input and output on a ray \f$ r\f$ take time +\f$ O(r.dimension())\f$. `dimension()`, coordinate and point +access, and identity test take constant time. The space requirement is +\f$ O(r.dimension())\f$. + +*/ +template< typename Kernel > +class Ray_d { +public: + +/// \name Types +/// @{ + +/*! +the linear algebra layer. + +*/ +typedef Hidden_type LA; + +/// @} + +/// \name Creation +/// @{ + +/*! +introduces some ray in +\f$ d\f$-dimensional space. +*/ +Ray_d(); + +/*! +introduces a ray +through `p` and `q` and starting at `p`. + +\pre \f$ p\f$ and \f$ q\f$ are distinct and have the same dimension. + +\pre `p.dimension()==q.dimension()`. +*/ +Ray_d(Point_d p, Point_d q); + +/*! +introduces +a ray starting in `p` with direction `dir`. + +\pre `p` and `dir` have the same dimension and `dir` is not degenerate. + +\pre `p.dimension()==dir.dimension()`. +*/ +Ray_d(Point_d p, Direction_d dir); + +/*! +introduces a ray through +`s.source()` and `s.target()` and starting at +`s.source()`. + +\pre \f$ s\f$ is not degenerate. +*/ +Ray_d(Segment_d s); + +/// @} + +/// \name Operations +/// @{ + +/*! +returns the dimension of the ambient +space. +*/ +int dimension() ; + +/*! +returns the source point of `r`. + +*/ +Point_d source() ; + +/*! +returns a point on +`r`. `point(0)` is the source. `point(i)`, with \f$ i>0\f$, is +different from the source. + +\pre \f$ i \geq0\f$. +*/ +Point_d point(int i) ; + +/*! +returns the direction of +`r`. +*/ +Direction_d direction() ; + +/*! +returns the supporting line +of `r`. +*/ +Line_d supporting_line() ; + +/*! +returns the ray with direction +opposite to `r` and starting in `source`. +*/ +Ray_d opposite() ; + +/*! +returns \f$ t(r)\f$. + +\pre `r.dimension()==t.dimension()`. +*/ +Ray_d transform(const Aff_transformation_d& t) +; + +/*! +returns +`r+v`, i.e., `r` translated by vector \f$ v\f$. + +\pre `r.dimension()==v.dimension()`. +*/ +Ray_d operator+(const Vector_d& v) ; + +/*! +A point is on `r`, +iff it is equal to the source of `r`, or if it is in the interior +of `r`. + +\pre `r.dimension()==p.dimension()`. +*/ +bool has_on(const Point_d& p) ; + + +/// @} + +}; /* end Ray_d */ + +/*! +returns true if the unoriented supporting lines of `r1` and +`r2` are parallel and false otherwise. + +\pre `r1.dimension()==r2.dimension()`. +\relates Ray_d +*/ +bool parallel(const Ray_d& r1, const Ray_d& r2) ; + +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Segment_d.h b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Segment_d.h new file mode 100644 index 00000000000..9b432fa728d --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Segment_d.h @@ -0,0 +1,219 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDKernelObjs + +An instance \f$ s\f$ of the data type `Segment_d` is a directed +straight line segment in \f$ d\f$-dimensional Euclidean space connecting +two points \f$ p\f$ and \f$ q\f$. \f$ p\f$ is called the source point and \f$ q\f$ is +called the target point of \f$ s\f$, both points are called endpoints of +\f$ s\f$. A segment whose endpoints are equal is called degenerate. + +Implementation +-------------- + +Segments are implemented by a pair of points as an item type. All +operations like creation, initialization, tests, the calculation of +the direction and source - target vector, input and output on a +segment \f$ s\f$ take time \f$ O(s.dimension())\f$. `dimension()`, +coordinate and end point access, and identity test take constant time. +The operations for intersection calculation also take time +\f$ O(s.dimension())\f$. The space requirement is +\f$ O(s.dimension())\f$. + +*/ +template< typename Kernel > +class Segment_d { +public: + +/// \name Types +/// @{ + +/*! +the linear algebra layer. +*/ +typedef Hidden_type LA; + +/// @} + +/// \name Creation +/// @{ + +/*! +introduces a variable `s` +of type `Segment_d`. +*/ +Segment_d(); + +/*! +introduces a +variable `s` of type `Segment_d` which is initialized to +the segment \f$ (p,q)\f$. + +\pre `p.dimension()==q.dimension()`. +*/ +Segment_d(Point_d p, Point_d q); + +/*! +introduces a +variable `s` of type `Segment_d` which is initialized to +the segment `(p,p+v)`. + +\pre `p.dimension()==v.dimension()`. +*/ +Segment_d(Point_d p, Vector_d v); + +/// @} + +/// \name Operations +/// @{ + +/*! +returns the dimension of the ambient +space. +*/ +int dimension(); + +/*! +returns the source point of segment +`s`. +*/ +Point_d source(); + +/*! +returns the target point of segment +`s`. +*/ +Point_d target(); + +/*! +returns source or target of +`s`: `vertex(0)` returns the source, `vertex(1)` returns +the target. The parameter \f$ i\f$ is taken modulo \f$ 2\f$, which gives easy +access to the other vertex. + +\pre \f$ i \geq0\f$. +*/ +Point_d vertex(int i) ; + +/*! +returns `vertex(i)`. +*/ +Point_d point(int i) ; + +/*! +returns `vertex(i)`. +*/ +Point_d operator[](int i) ; + +/*! +returns the lexicographically smaller +vertex. +*/ +Point_d min() ; + +/*! +returns the lexicographically larger +vertex. +*/ +Point_d max() ; + +/*! +returns the segment +`(target(),source())`. +*/ +Segment_d opposite() ; + +/*! +returns the direction from +source to target. + +\pre `s` is non-degenerate. +*/ +Direction_d direction() ; + +/*! +returns the vector from source to +target. +*/ +Vector_d vector() ; + +/*! +returns the square of the length of +`s`. +*/ +FT squared_length() ; + +/*! +returns true if \f$ p\f$ lies +on `s` and false otherwise. + +\pre `s.dimension()==p.dimension()`. +*/ +bool has_on(const Point_d& p) ; + +/*! +returns the supporting line +of `s`. + +\pre `s` is non-degenerate. +*/ +Line_d supporting_line() ; + +/*! +returns \f$ t(s)\f$. + +\pre `s.dimension()==t.dimension()`. +*/ +Segment_d transform(const Aff_transformation_d& t) +; + +/*! +returns +\f$ s+v\f$, i.e., `s` translated by vector \f$ v\f$. + +\pre `s.dimension()==v.dimension()`. +*/ +Segment_d operator+(const Vector_d& v) ; + +/*! +returns true if `s` is +degenerate i.e. `s.source()=s.target()`. +*/ +bool is_degenerate() ; + +/// @} + +}; /* end Segment_d */ + +/*! +Test for equality as unoriented +segments. + +\pre `s1.dimension()==s2.dimension()`. +\relates Segment_d +*/ +bool weak_equality(const Segment_d& s1, const Segment_d& s2) ; + +/*! +return true if one of the segments is degenerate or if the +unoriented supporting lines are parallel. + +\pre `s1.dimension()==s2.dimension()`. +\relates Segment_d +*/ +bool parallel(const Segment_d& s1, const Segment_d& s2) ; + + +/*! +if `s1` and `s2` +touch in a common end point, this point is assigned to `common` +and the result is `true`, otherwise the result is `false`. If +`s1==s2` then one of the endpoints is returned. + +\pre `s1.dimension()==s2.dimension()`. +\relates Segment_d +*/ +bool common_endpoint(const Segment_d& s1, const Segment_d& s2, Point_d& common) ; + +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Sphere_d.h b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Sphere_d.h new file mode 100644 index 00000000000..04772b72362 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Sphere_d.h @@ -0,0 +1,222 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDKernelObjs + +An instance \f$ S\f$ of the data type `Sphere_d` is an oriented sphere +in some \f$ d\f$-dimensional space. A sphere is defined by \f$ d+1\f$ points +(class `Point_d`). We use \f$ A\f$ to denote the array of the +defining points. A set \f$ A\f$ of defining points is legal if +either the points are affinely independent or if the points are all +equal. Only a legal set of points defines a sphere in the geometric +sense and hence many operations on spheres require the set of defining +points to be legal. The orientation of \f$ S\f$ is equal to the +orientation of the defining points, i.e., `orientation(A)`. + +Implementation +-------------- + +Spheres are implemented by a vector of points as a handle type. All +operations like creation, initialization, tests, input and output of a +sphere \f$ s\f$ take time \f$ O(s.dimension()) \f$. `dimension()`, +point access take constant time. The `center()`-operation takes +time \f$ O(d^3)\f$ on its first call and constant time thereafter. The +sidedness and orientation tests take time \f$ O(d^3)\f$. The space +requirement for spheres is \f$ O(s.dimension())\f$ neglecting the +storage room of the points. + +*/ +template< typename Kernel > +class Sphere_d { +public: + +/// \name Types +/// @{ + +/*! +the linear algebra layer. +*/ +typedef Hidden_type LA; + +/*! +a read-only iterator for points defining +the sphere. +*/ +typedef Hidden_type point_iterator; + +/// @} + +/// \name Creation +/// @{ + +/*! +introduces a variable `S` +of type `Sphere_d`. +*/ +Sphere_d(); + +/*! +introduces a variable +`S` of type `Sphere_d`. `S` is initialized to the +sphere through the points in `A = tuple [first,last)`. + +\pre \f$A\f$ consists of \f$d+1\f$ \f$d\f$-dimensional points. + +\requires The value type of ForwardIterator is `Point_d`. +*/ +template Sphere_d(int d, +ForwardIterator first, ForwardIterator last); + +/// @} + +/// \name Operations +/// @{ + +/*! +returns the dimension of the ambient space. +*/ +int dimension(); + +/*! +returns the \f$ i\f$th defining +point. + +\pre \f$ 0 \le i \le dim \f$ +*/ +Point_d point(int i) ; + +/*! +returns an iterator +pointing to the first defining point. +*/ +point_iterator points_begin() ; + +/*! +returns an iterator pointing +beyond the last defining point. +*/ +point_iterator points_end() ; + +/*! +returns true iff the defining points +are not full dimensional. +*/ +bool is_degenerate(); + +/*! +returns true iff the set of defining +points is legal. A set of defining points is legal iff their +orientation is non-zero or if they are all equal. +*/ +bool is_legal() ; + +/*! +returns the center of `S`. +\pre `S` is legal. +*/ +Point_d center() ; + +/*! +returns the squared radius of the +sphere. + +\pre `S` is legal. +*/ +FT squared_radius() ; + +/*! +returns the orientation of +`S`. +*/ +Orientation orientation() ; + +/*! +returns +either the constant `ON_ORIENTED_BOUNDARY`, +`ON_POSITIVE_SIDE`, or `ON_NEGATIVE_SIDE`, iff p lies on the +boundary, properly on the positive side, or properly on the negative +side of sphere, resp. + +\pre `S.dimension()==p.dimension()`. + +*/ +Oriented_side oriented_side(const Point_d& p) ; + +/*! +returns +`ON_BOUNDED_SIDE`, `ON_BOUNDARY`, or `ON_UNBOUNDED_SIDE` +iff p lies properly inside, on the boundary, or properly outside of +sphere, resp. + +\pre `S.dimension()==p.dimension()`. +*/ +Bounded_side bounded_side(const Point_d& p) ; + +/*! +returns +`S.oriented_side(p)==ON_POSITIVE_SIDE`. + +\pre `S.dimension()==p.dimension()`. +*/ +bool has_on_positive_side (const Point_d& p) ; + +/*! +returns +`S.oriented_side(p)==ON_NEGATIVE_SIDE`. + +\pre `S.dimension()==p.dimension()`. +*/ +bool has_on_negative_side (const Point_d& p) ; + +/*! +returns +`S.oriented_side(p)==ON_ORIENTED_BOUNDARY`, which is the same as +`S.bounded_side(p)==ON_BOUNDARY`. + +\pre `S.dimension()==p.dimension()`. +*/ +bool has_on_boundary (const Point_d& p) ; + +/*! +returns +`S.bounded_side(p)==ON_BOUNDED_SIDE`. + +\pre `S.dimension()==p.dimension()`. +*/ +bool has_on_bounded_side (const Point_d& p) ; + +/*! +returns +`S.bounded_side(p)==ON_UNBOUNDED_SIDE`. + +\pre `S.dimension()==p.dimension()`. +*/ +bool has_on_unbounded_side (const Point_d& p) ; + +/*! +returns the sphere with the same +center and squared radius as `S` but with opposite orientation. + +*/ +Sphere_d opposite() ; + +/*! +returns the +sphere translated by `v`. + +\pre `S.dimension()==v.dimension()`. +*/ +Sphere_d operator+(const Vector_d& v) ; + +/// @} + +}; /* end Sphere_d */ + +/*! +Test for equality as unoriented spheres. +\pre `S1.dimension()==S2.dimension()`. +\relates Sphere_d +*/ +bool weak_equality(const Sphere_d& S1, const Sphere_d& S2) ; + +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Vector_d.h b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Vector_d.h new file mode 100644 index 00000000000..b810951fa5c --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Kernel_d/Vector_d.h @@ -0,0 +1,311 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDKernelObjs + +An instance of data type `Vector_d` is a vector of Euclidean +space in dimension \f$ d\f$. A vector \f$ r = (r_0,\ldots,r_{ d - 1})\f$ can be +represented in homogeneous coordinates \f$ (h_0,\ldots,h_d)\f$ of number +type `RT`, such that \f$ r_i = h_i/h_d\f$ which is of type `FT`. We +call the \f$ r_i\f$'s the Cartesian coordinates of the vector. The +homogenizing coordinate \f$ h_d\f$ is positive. + +This data type is meant for use in computational geometry. It realizes +free vectors as opposed to position vectors (type `Point_d`). The +main difference between position vectors and free vectors is their +behavior under affine transformations, e.g., free vectors are +invariant under translations. + +Downward compatibility +-------------- + +We provide all operations of the +lower dimensional interface `x()`, `y()`, `z()`, +`hx()`, `hy()`, `hz()`, `hw()`. + +Implementation +-------------- + +Vectors are implemented by arrays of variables of type `RT`. All +operations like creation, initialization, tests, vector arithmetic, +input and output on a vector \f$ v\f$ take time \f$ O(v.dimension())\f$. +coordinate access, `dimension()` and conversions take constant +time. The space requirement of a vector is \f$ O(v.dimension())\f$. + +*/ +template< typename Kernel > +class Vector_d { +public: + +/// \name Types +/// @{ + +/*! +the linear algebra layer. +*/ +typedef Hidden_type LA; + +/*! +a read-only iterator for the +Cartesian coordinates. +*/ +typedef Hidden_type Cartesian_const_iterator; + +/*! +a read-only iterator for the +homogeneous coordinates. +*/ +typedef Hidden_type Homogeneous_const_iterator; + +/*! +construction tag. +*/ +typedef Hidden_type Base_vector; + +/// @} + +/// \name Creation +/// @{ + +/*! +introduces a variable `v` +of type `Vector_d`. +*/ +Vector_d(); + +/*! +introduces the zero +vector `v` of type `Vector_d` in \f$ d\f$-dimensional space. +For the creation flag `CGAL::NULL_VECTOR` can be used. +*/ +Vector_d(int d, Null_vector); + +/*! +introduces a variable +`v` of type `Vector_d` in dimension `d`. If +`size [first,last) == d` this creates a vector with Cartesian +coordinates `set [first,last)`. If `size [first,last) == p+1` the range specifies the homogeneous coordinates \f$ H = set +[first,last) = (\pm h_0, \pm h_1, \ldots, \pm h_d)\f$ where the +sign chosen is the sign of \f$ h_d\f$. + +\pre `d` is nonnegative, `[first,last)` has `d` or `d+1` elements where the last has to be non-zero. +\requires The value type of `InputIterator` is `RT`. +*/ +template Vector_d(int d, +InputIterator first, InputIterator last); + +/*! +introduces a +variable `v` of type `Vector_d` in dimension `d` +initialized to the vector with homogeneous coordinates as defined by +`H = set [first,last)` and `D`: \f$ (\pmH[0], +\pmH[1], \ldots, \pmH[d-1], \pmD)\f$. The sign +chosen is the sign of \f$ D\f$. + +\pre `D` is non-zero, the iterator range defines a \f$ d\f$-tuple of `RT`. +\requires The value type of `InputIterator` is `RT`. +*/ +template Vector_d(int d, +InputIterator first, InputIterator last, RT D); + +/*! +returns a +variable `v` of type `Vector_d` initialized to the \f$ i\f$-th +base vector of dimension \f$ d\f$. + +\pre \f$ 0 \leq i < d\f$. +*/ +Vector_d(int d, Base_vector, int i); + +/*! +introduces a +variable `v` of type `Vector_d` in \f$ 2\f$-dimensional space. +\pre \f$ w \neq0\f$. +*/ +Vector_d(RT x, RT y, RT w = 1); + +/*! +introduces a +variable `v` of type `Vector_d` in \f$ 3\f$-dimensional space. +\pre \f$ w \neq0\f$. +*/ +Vector_d(RT x, RT y, RT z, RT w); + +/// @} + +/// \name Operations +/// @{ + +/*! +returns the dimension of `v`. +*/ +int dimension() ; + +/*! +returns the \f$ i\f$-th Cartesian +coordinate of `v`. + +\pre \f$ 0 \leq i < d\f$. +*/ +FT cartesian(int i) ; + +/*! +returns the \f$ i\f$-th Cartesian +coordinate of `v`. + +\pre \f$ 0 \leq i < d\f$. +*/ +FT operator[](int i) ; + +/*! +returns the \f$ i\f$-th homogeneous +coordinate of `v`. + +\pre \f$ 0 \leq i \leq d\f$. +*/ +RT homogeneous(int i) ; + +/*! +returns the square of the length of +`v`. +*/ +FT squared_length() ; + +/*! +returns an +iterator pointing to the zeroth Cartesian coordinate of `v`. +*/ +Cartesian_const_iterator cartesian_begin() ; + +/*! +returns an +iterator pointing beyond the last Cartesian coordinate of `v`. + +*/ +Cartesian_const_iterator cartesian_end() ; + +/*! +returns an +iterator pointing to the zeroth homogeneous coordinate of `v`. + +*/ +Homogeneous_const_iterator homogeneous_begin() ; + +/*! +returns an +iterator pointing beyond the last homogeneous coordinate of `v`. + +*/ +Homogeneous_const_iterator homogeneous_end() ; + +/*! +returns the direction of +`v`. +*/ +Direction_d direction() ; + +/*! +returns \f$ t(v)\f$. +*/ +Vector_d transform(const Aff_transformation_d& t) +; + +/// @} + +/// \name Arithmetic Operators, Tests and IO +/// @{ + +/*! +multiplies all +Cartesian coordinates by `n`. +*/ +Vector_d& operator*=(const RT& n) ; + +/*! +multiplies all +Cartesian coordinates by `r`. +*/ +Vector_d& operator*=(const FT& r) ; + +/*! +returns the vector +with Cartesian coordinates \f$ v_i/n, 0 \leq i < d\f$. +*/ +Vector_d operator/(const RT& n) ; + +/*! +returns the vector +with Cartesian coordinates \f$ v_i/r, 0 \leq i < d\f$. +*/ +Vector_d operator/(const FT& r) ; + +/*! +divides all +Cartesian coordinates by `n`. +*/ +Vector_d& operator/=(const RT& n) ; + +/*! +divides all +Cartesian coordinates by `r`. +*/ +Vector_d& operator/=(const FT& r) ; + +/*! +inner product, i.e., +\f$ \sum_{ 0 \le i < d } v_i w_i\f$, where \f$ v_i\f$ and \f$ w_i\f$ are the +Cartesian coordinates of \f$ v\f$ and \f$ w\f$ respectively. +*/ +FT operator* (const Vector_d& w) ; + +/*! +returns the +vector with Cartesian coordinates \f$ v_i+w_i, 0 \leq i < d\f$. +*/ +Vector_d operator+(const Vector_d& w) ; + +/*! +addition +plus assignment. +*/ +Vector_d& operator+=(const Vector_d& w) ; + +/*! +returns the +vector with Cartesian coordinates \f$ v_i-w_i, 0 \leq i < d\f$. +*/ +Vector_d operator-(const Vector_d& w) ; + +/*! +subtraction +plus assignment. +*/ +Vector_d& operator-=(const Vector_d& w) ; + +/*! +returns the vector in opposite +direction. +*/ +Vector_d operator-() ; + +/*! +returns true if `v` is the zero +vector. +*/ +bool is_zero() ; + +/*! +returns the vector with Cartesian coordinates \f$ n v_i\f$. +*/ +Vector_d operator*(const RT& n, const Vector_d& v); + +/*! +returns the vector with Cartesian coordinates \f$ r v_i, 0 \leq i < +d\f$. +*/ +Vector_d operator*(const FT& r, const Vector_d& v); + +/// @} + +}; /* end Vector_d */ +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Linear_algebraCd.h b/Kernel_d/doc/Kernel_d/CGAL/Linear_algebraCd.h new file mode 100644 index 00000000000..162ab88d525 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Linear_algebraCd.h @@ -0,0 +1,31 @@ + +namespace CGAL { + +/*! +\ingroup PkgKernelDLinAlgClasses + +The class `Linear_algebraCd` serves as the default traits class for the LA +parameter of `CGAL::Cartesian_d`. It implements linear +algebra for field number types `FT`. + +\models ::LinearAlgebraTraits_d + +Requirements +-------------- + +`FT` must be a field number type. + +Operations +-------------- + +Fits all operation requirements of the concept. + +*/ +template< typename FT > +class Linear_algebraCd { +public: + +/// @} + +}; /* end Linear_algebraCd */ +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Linear_algebraHd.h b/Kernel_d/doc/Kernel_d/CGAL/Linear_algebraHd.h new file mode 100644 index 00000000000..97b9544a378 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/Linear_algebraHd.h @@ -0,0 +1,32 @@ + +namespace CGAL { + +/*! +\ingroup PkgKernelDLinAlgClasses + +The class `Linear_algebraHd` serves as the default traits class for the LA +parameter of `CGAL::Homogeneous_d`. It implements linear +algebra for Euclidean ring number types `RT`. + +\models ::LinearAlgebraTraits_d + +Requirements +-------------- + +To make a ring number type `RT` work with this class it has to +provide a division `operator/` with remainder. + +Operations +-------------- + +Fits all operation requirements of the concept. + +*/ +template< typename RT > +class Linear_algebraHd { +public: + +/// @} + +}; /* end Linear_algebraHd */ +} /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/constructions_d.h b/Kernel_d/doc/Kernel_d/CGAL/constructions_d.h new file mode 100644 index 00000000000..3a4a0c5c2f4 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/constructions_d.h @@ -0,0 +1,77 @@ +namespace CGAL { + +/// \addtogroup PkgKernelDFunctions +/// @{ + +/*! + + +returns the center of the sphere spanned by the points in `A = tuple[first,last)`. + +\pre \f$ A\f$ contains \f$ d+1\f$ affinely independent points of dimension \f$ d\f$. +\requires The value type of `ForwardIterator` is `Point_d`. +*/ +template Point_d +center_of_sphere(ForwardIterator first, ForwardIterator last); + + +/*! + + +returns the projection of \f$ p = (x_0,\ldots,x_{d-1})\f$ onto the +paraboloid of revolution which is the point \f$ (p_0, +\ldots,p_{d-1},\sum_{0 \le i < d}p_i^2)\f$ in \f$ (d+1)\f$-space. +*/ +Point_d lift_to_paraboloid(const Point_d& p); + + +/*! + + +computes a basis of the linear space +spanned by the vectors in `A = tuple [first,last)` and returns +it via an iterator range starting in `result`. The returned +iterator marks the end of the output. +\pre \f$ A\f$ contains vectors of the same dimension \f$ d\f$. + +\requires The value type of `ForwardIterator` and `OutputIterator` is `Vector_d`. +*/ +template +OutputIterator linear_base(ForwardIterator first, ForwardIterator +last, OutputIterator result); + + +/*! + + +computes the midpoint of the segment \f$ pq\f$. + +\pre `p.dimension() == q.dimension()`. +*/ +Point_d midpoint(const Point_d& p, const Point_d& +q); + + +/*! + + +returns \f$ p\f$ projected along the \f$ d\f$-axis onto the hyperspace spanned +by the first \f$ d-1\f$ standard base vectors. +*/ +Point_d project_along_d_axis(const Point_d& p); + + +/*! + + +computes the square of the Euclidean distance between the two points +\f$ p\f$ and \f$ q\f$. + +\pre The dimensions of \f$ p\f$ and \f$ q\f$ are the same. +*/ +FT squared_distance(Point_d p, Point_d q); + +/// @} + +} /* namespace CGAL */ + diff --git a/Kernel_d/doc/Kernel_d/CGAL/intersections_d.h b/Kernel_d/doc/Kernel_d/CGAL/intersections_d.h new file mode 100644 index 00000000000..661e8a0d34d --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/intersections_d.h @@ -0,0 +1,150 @@ +namespace CGAL { + +/*! +\ingroup PkgKernelDFunctions + +checks whether `obj1` and `obj2` intersect. Two objects `obj1` and +`obj2` intersect if there is a point `p` that is part of both `obj1` +and `obj2`. The intersection region of those two objects is defined +as the set of all points `p` that are part of both `obj1` and +`obj2`. + +\pre The objects are of the same dimension. + +The types `Type1` and `Type2` can be any of the following: + +- `Point_d` +- `Line_d` +- `Ray_d` +- `Segment_d` +- `Hyperplane_d` + +\sa `intersection` +*/ +bool do_intersect(Type1 obj1, Type2 obj2); + +/*! +\ingroup PkgKernelDFunctions + +returns the intersection result of \f$ f1\f$ and \f$ f2\f$ by means of +the polymorphic wrapper type `Object`. The returned object can be +tested for the intersection result and assigned by means of the +`object_cast` function. + +\pre The objects are of the same dimension. + +The possible value for types `Type1` and `Type2` and +the possible return values wrapped in `Object` are the following: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Type1 Type2 Return Type
Line_d Line_d + + +
Point_d
Line_d
Segment_d Line_d + + +
Point_d
Segment_d
Segment_d Segment_d + + +
Point_d
Segment_d
Ray_d Line_d + + +
Point_d
Ray_d
Ray_d Segment_d + + +
Point_d
Segment_d
Ray_d Ray_d + + + +
Point_d
Segment_d
Ray_d
Hyperplane_d Line_d + + +
Point_d
Line_d
Hyperplane_d Ray_d + + +
Point_d
Ray_d
Hyperplane_d Segment_d + + +
Point_d
Segment_d
+
+ +Example +-------------- + +The following example demonstrates the most common use of +`intersection` routines. + +\code +#include + +template +void foo(Segment_d seg, Line_d lin) +{ + Object result = intersection(seg, lin); + if (const Point_d *ipnt = object_cast >(&result) ) { + // handle the point intersection case with *ipnt. + } else if (const Segment_d *iseg = object_cast >(&result) ) { + // handle the segment intersection case with *iseg. + } else { + // handle the no intersection case. + } +} +\endcode + +\sa `do_intersect`, \sa `Kernel_d::Intersect_d` + +*/ +Object intersection(Type1 f1, Type2 f2); + +} /* namespace CGAL */ + diff --git a/Kernel_d/doc/Kernel_d/CGAL/predicates_d.h b/Kernel_d/doc/Kernel_d/CGAL/predicates_d.h new file mode 100644 index 00000000000..f1c0031205f --- /dev/null +++ b/Kernel_d/doc/Kernel_d/CGAL/predicates_d.h @@ -0,0 +1,194 @@ +namespace CGAL { + +/// \addtogroup PkgKernelDFunctions +/// @{ + +/*! + + +returns true iff the points in `A = tuple [first,last)` are +affinely independent. + +\pre The objects are of the same dimension. +\requires The value type of `ForwardIterator` is `Point_d` +*/ +template bool +affinely_independent(ForwardIterator first, ForwardIterator last); + + +/*! + + +computes +the affine rank of the points in `A = tuple [first,last)`. +\pre The objects in \f$ A\f$ are of the same dimension. +\requires The value type of `ForwardIterator` is `Point_d`. +*/ +template int +affine_rank(ForwardIterator first, ForwardIterator last); + + +/*! + + +Compares the Cartesian +coordinates of points `p` and `q` lexicographically +in ascending order of its Cartesian components `p[i]` and +`q[i]` for \f$ i = 0,\ldots,d-1\f$. + +\pre `p.dimension() == q.dimension()`. +*/ +Comparison_result compare_lexicographically(const +Point_d& p, const Point_d& q); + + +/*! + + +determines whether \f$ p\f$ is contained in +the affine hull of the points in `A = tuple [first,last)`. +\pre The objects in `A` are of the same dimension. + +\requires The value type of `ForwardIterator` is `Point_d`. +*/ +template bool +contained_in_affine_hull( ForwardIterator first, ForwardIterator +last, const Point_d& p); + + +/*! + + +determines whether \f$ v\f$ is contained +in the linear hull of the vectors in `A = tuple [first,last)`. +\pre The objects in \f$ A\f$ are of the same dimension. + +\requires The value type of `ForwardIterator` is `Vector_d`. +*/ +template bool +contained_in_linear_hull( ForwardIterator first, ForwardIterator +last, const Vector_d& v); + + +/*! + + +determines whether \f$ p\f$ is contained in the +simplex of the points in `A = tuple [first,last)`. + +\pre The objects in \f$ A\f$ are of the same dimension and affinely +independent. +\requires The value type of `ForwardIterator` is `Point_d`. +*/ +template bool +contained_in_simplex( ForwardIterator first, ForwardIterator last, +const Point_d& p); + + +/*! + + +returns `true` iff `p` is +lexicographically smaller than `q` with respect to Cartesian +lexicographic order of points. + +\pre `p.dimension() == q.dimension()`. +*/ +bool lexicographically_smaller(const Point_d& p, const +Point_d& q); + + +/*! + + +returns `true` iff \f$ p\f$ is +lexicographically smaller than \f$ q\f$ with respect to Cartesian +lexicographic order of points or equal to \f$ q\f$. + +\pre `p.dimension() == q.dimension()`. +*/ +bool lexicographically_smaller_or_equal( const Point_d& +p, const Point_d& q); + + +/*! + + +decides whether the vectors in `A = tuple [first,last)` +are linearly independent. + +\pre The objects in `A` are of the same dimension. +\requires The value type of `ForwardIterator` is `Vector_d`. +*/ +template bool +linearly_independent( ForwardIterator first, ForwardIterator +last); + + +/*! + + +computes +the linear rank of the vectors in `A = tuple [first,last)`. +\pre The objects are of the same dimension. +\requires The value type of `ForwardIterator` is `Vector_d`. +*/ +template int +linear_rank(ForwardIterator first, ForwardIterator last); + + +/*! + + +determines the orientation of the points of the tuple `A = tuple [first,last)` where \f$ A\f$ consists of \f$ d+1\f$ points in +\f$ d\f$-space. This is the sign of the determinant +\f[ \left| \begin{array}{cccc} +1 & 1 & 1 & 1 \\ +A[0] & A[1] & \dots& A[d] +\end{array} \right| \f] +where `A[i]` denotes the Cartesian coordinate vector of +the \f$ i\f$-th point in \f$ A\f$. +\pre `size [first,last) == d+1` and `A[i].dimension() == d` \f$ \forall0 \leq i \leq d\f$. + +\requires The value type of `ForwardIterator` is `Point_d`. + +*/ +template Orientation +orientation(ForwardIterator first, ForwardIterator last); + + +/*! + + +returns the relative position of point +`p` to the sphere defined by `A = tuple [first,last)`. The +order of the points of \f$ A\f$ does not matter. + +\pre `orientation(first,last)` is not `ZERO`. +\requires The value type of `ForwardIterator` is `Point_d`. +*/ +template Bounded_side +side_of_bounded_sphere( ForwardIterator first, ForwardIterator last, +const Point_d& p); + +/*! + + +returns the relative position of +point `p` to the oriented sphere defined by the points in +`A = tuple [first,last)` The order of the points in \f$ A\f$ is +important, since it determines the orientation of the implicitly +constructed sphere. If the points in \f$ A\f$ are positively oriented, +the positive side is the bounded interior of the sphere. + +\pre `A` contains \f$ d+1\f$ points in \f$ d\f$-space. +\requires The value type of `ForwardIterator` is `Point_d`. +*/ +template Oriented_side +side_of_oriented_sphere( ForwardIterator first, ForwardIterator +last, const Point_d& p); + +/// @} + +} /* namespace CGAL */ + diff --git a/Kernel_d/doc/Kernel_d/Classified.txt b/Kernel_d/doc/Kernel_d/Classified.txt new file mode 100644 index 00000000000..bb67326a2ac --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Classified.txt @@ -0,0 +1,8 @@ + +\authors Michael Seel + +# Linear Algebra Concepts and Classes # +# Kernels # +# Kernel Objects # +# Global Kernel Functions # +# Kernel Concept # diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Affine_rank_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Affine_rank_d.h new file mode 100644 index 00000000000..1532d576bfc --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Affine_rank_d.h @@ -0,0 +1,29 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Affine_rank_d { +public: + +/// \name Has Models +/// @{ + +/*! +computes +the affine rank of the points in `A = tuple [first,last)`. +\pre The objects are of the same dimension. + +\requires The value type of `ForwardIterator` is `Kernel_d::Point_d`. +*/ +template int +operator()(ForwardIterator first, ForwardIterator last); + +/// @} + +}; /* end Kernel_d::Affine_rank_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Affinely_independent_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Affinely_independent_d.h new file mode 100644 index 00000000000..043df05e11b --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Affinely_independent_d.h @@ -0,0 +1,31 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Affinely_independent_d { +public: + +/// \name Has Models +/// @{ + +/*! +returns +true iff the points in `A = tuple [first,last)` are affinely +independent. + +\pre The objects are of the same dimension. + +\requires The value type of `ForwardIterator` is `Kernel_d::Point_d`. +*/ +template bool +operator()(ForwardIterator first, ForwardIterator last); + +/// @} + +}; /* end Kernel_d::Affinely_independent_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--CartesianConstIterator_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--CartesianConstIterator_d.h new file mode 100644 index 00000000000..cac66d39efb --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--CartesianConstIterator_d.h @@ -0,0 +1,25 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A type representing an iterator to the Cartesian coordinates of a point +in `d` dimensions. + +\refines `CopyConstructible` +\refines `Assignable` +\refines `DefaultConstructible` + +\models ::BidirectionalIterator + +\sa `Kernel_d::ConstructCartesianConstIterator_d` + +*/ + +class Kernel_d::CartesianConstIterator_d { +public: + +/// @} + +}; /* end Kernel_d::CartesianConstIterator_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Center_of_sphere_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Center_of_sphere_d.h new file mode 100644 index 00000000000..dc56f9e0264 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Center_of_sphere_d.h @@ -0,0 +1,28 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Center_of_sphere_d { +public: + +/// \name See Also +/// @{ + +/*! +returns the +center of the sphere spanned by the points in `A = tuple [first,last)`. +\pre \f$A\f$ contains \f$d+1\f$ affinely independent points of dimension \f$d\f$. +\requires The value type of `ForwardIterator` is `Kernel_d::Point_d`. +*/ +template Kernel_d::Point_d +operator()(ForwardIterator first, ForwardIterator last); + +/// @} + +}; /* end Kernel_d::Center_of_sphere_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Compare_lexicographically_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Compare_lexicographically_d.h new file mode 100644 index 00000000000..a35bb7fe905 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Compare_lexicographically_d.h @@ -0,0 +1,30 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Compare_lexicographically_d { +public: + +/// \name See Also +/// @{ + +/*! +Compares the Cartesian coordinates of +points `p` and `q` lexicographically in ascending +order of its Cartesian components `p[i]` and `q[i]` for \f$ i = +0,\ldots,d-1\f$. + +\pre The objects are of the same dimension. +*/ +Comparison_result operator()(const Kernel_d::Point_d& +p, const Kernel_d::Point_d& q); + +/// @} + +}; /* end Kernel_d::Compare_lexicographically_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Component_accessor_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Component_accessor_d.h new file mode 100644 index 00000000000..8912679c44a --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Component_accessor_d.h @@ -0,0 +1,41 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Component_accessor_d { +public: + +/// \name See Also +/// @{ + +/*! +returns +the dimension of \f$ p\f$. +*/ +int dimension(const Kernel_d::Point_d& p); + +/*! +returns the ith homogeneous coordinate of \f$ p\f$. + +\pre `0 <= i <= dimension(p)`. +*/ +Kernel_d::RT homogeneous(const Kernel_d::Point_d& p, +int i); + +/*! +returns the ith Cartesian coordinate of \f$ p\f$. + +\pre `0 <= i < dimension(p)`. +*/ +Kernel_d::FT cartesian(const Kernel_d::Point_d& p, int +i); + +/// @} + +}; /* end Kernel_d::Component_accessor_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Compute_coordinate_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Compute_coordinate_d.h new file mode 100644 index 00000000000..b1ce460c8d9 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Compute_coordinate_d.h @@ -0,0 +1,25 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Compute_coordinate_d { +public: + +/// \name See Also +/// @{ + +/*! +returns the \f$ i\f$th cartesian coordinate of \f$ p\f$ +*/ +Kernel_d::FT operator()(const Kernel_d::Point_d& +p, int i); + +/// @} + +}; /* end Kernel_d::Compute_coordinate_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--ConstructCartesianConstIterator_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--ConstructCartesianConstIterator_d.h new file mode 100644 index 00000000000..d9ea3a0da9d --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--ConstructCartesianConstIterator_d.h @@ -0,0 +1,28 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +\refines `AdaptableFunctor` (with one argument) + +\sa `Kernel_d::CartesianConstIterator_d` + +*/ +class Kernel_d::ConstructCartesianConstIterator_d { +public: +/*! +returns an iterator on the 0'th Cartesian coordinate of `p`. +*/ +Kernel_d::Cartesian_const_iterator_d operator()(const Kernel_d::Point_d +&p); + +/*! +returns the past the end iterator of the Cartesian coordinates of `p`. +*/ +Kernel_d::Cartesian_const_iterator_d operator()(const Kernel_d::Point_d +&p, int); + +}; /* end Kernel_d::ConstructCartesianConstIterator_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_affine_hull_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_affine_hull_d.h new file mode 100644 index 00000000000..f4dfe81a7d8 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_affine_hull_d.h @@ -0,0 +1,30 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Contained_in_affine_hull_d { +public: + +/// \name See Also +/// @{ + +/*! +determines whether \f$ p\f$ is contained in the +affine hull of the points in `A = tuple [first,last)`. +\pre The objects are of the same dimension. + +\requires The value type of `ForwardIterator` is `Kernel_d::Point_d`. +*/ +template Bounded_side +operator()( ForwardIterator first, ForwardIterator last, const +Kernel_d::Point_d& p); + +/// @} + +}; /* end Kernel_d::Contained_in_affine_hull_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_linear_hull_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_linear_hull_d.h new file mode 100644 index 00000000000..7fd9f862b73 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_linear_hull_d.h @@ -0,0 +1,29 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Contained_in_linear_hull_d { +public: + +/// \name See Also +/// @{ + +/*! +determines whether \f$ v\f$ is contained in the +linear hull of the vectors in `A = tuple [first,last)`. +\pre The objects are of the same dimension. +\requires The value type of `ForwardIterator` is `Kernel_d::Vector_d`. +*/ +template Bounded_side +operator()( ForwardIterator first, ForwardIterator last, const +Kernel_d::Vector_d& v); + +/// @} + +}; /* end Kernel_d::Contained_in_linear_hull_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_simplex_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_simplex_d.h new file mode 100644 index 00000000000..6c41caa753e --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Contained_in_simplex_d.h @@ -0,0 +1,30 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Contained_in_simplex_d { +public: + +/// \name See Also +/// @{ + +/*! +determines whether \f$ p\f$ is contained in the +simplex of the points in `A = tuple [first,last)`. + +\pre The objects in \f$ A\f$ are of the same dimension and affinely independent. +\requires The value type of `ForwardIterator` is `Kernel_d::Point_d`. +*/ +template Bounded_side +operator()( ForwardIterator first, ForwardIterator last, const +Kernel_d::Point_d& p); + +/// @} + +}; /* end Kernel_d::Contained_in_simplex_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Equal_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Equal_d.h new file mode 100644 index 00000000000..5119ffb5dfa --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Equal_d.h @@ -0,0 +1,28 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Equal_d { +public: + +/// \name See Also +/// @{ + +/*! +returns true iff \f$ p\f$ and \f$ q\f$ are equal (as +\f$ d\f$-dimensional points). + +\pre `p` and `q` have the same dimension. +*/ +bool operator()(const Kernel_d::Point_d&p, const +Kernel_d::Point_d&q); + +/// @} + +}; /* end Kernel_d::Equal_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Has_on_positive_side_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Has_on_positive_side_d.h new file mode 100644 index 00000000000..a286afb7d7f --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Has_on_positive_side_d.h @@ -0,0 +1,27 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Has_on_positive_side_d { +public: + +/// \name See Also +/// @{ + +/*! +returns true iff \f$ p\f$ +is on the positive side of \f$ o\f$. `Kernel_object` may be any of +`Kernel_d::Sphere_d`, `Kernel_d::Hyperplane_d`.\pre `p` and `o` have the same dimension. +*/ +template bool operator()(const +Kernel_object& o, const Kernel_d::Point_d& p); + +/// @} + +}; /* end Kernel_d::Has_on_positive_side_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Intersect_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Intersect_d.h new file mode 100644 index 00000000000..d526866d857 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Intersect_d.h @@ -0,0 +1,30 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Intersect_d { +public: + +/// \name See Also +/// @{ + +/*! +returns the result of the intersection of \f$ p\f$ and \f$ q\f$ in form of a +polymorphic object. `Kernel_object` may be any of +`Kernel_d::Segment_d`, `Kernel_d::Ray_d`, `Kernel_d::Line_d`, +`Kernel_d::Hyperplane_d`. + +\pre `p` and `q` have the same dimension. +*/ +template Object +operator()(const Kernel_object& p, const Kernel_object& q); + +/// @} + +}; /* end Kernel_d::Intersect_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_coordinate_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_coordinate_d.h new file mode 100644 index 00000000000..ab26065a9af --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_coordinate_d.h @@ -0,0 +1,30 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Less_coordinate_d { +public: + +/// \name See Also +/// @{ + +/*! +returns `true` iff the \f$ i\f$th Cartesian coordinate +of `p` is +smaller than the \f$ i\f$th Cartesian coordinate of `q`. + +\pre `p` and `q` have the same dimension. +*/ +bool operator()(const Kernel_d::Point_d& +p,const Kernel_d::Point_d& +q, int i); + +/// @} + +}; /* end Kernel_d::Less_coordinate_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_lexicographically_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_lexicographically_d.h new file mode 100644 index 00000000000..794dc433d7b --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_lexicographically_d.h @@ -0,0 +1,29 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Less_lexicographically_d { +public: + +/// \name See Also +/// @{ + +/*! +returns `true` iff `p` is +lexicographically smaller than `q` with respect to Cartesian +lexicographic order of points. + +\pre `p` and `q` have the same dimension. +*/ +bool operator()(const Kernel_d::Point_d&p, const +Kernel_d::Point_d&q); + +/// @} + +}; /* end Kernel_d::Less_lexicographically_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_or_equal_lexicographically_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_or_equal_lexicographically_d.h new file mode 100644 index 00000000000..9605e646af6 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Less_or_equal_lexicographically_d.h @@ -0,0 +1,29 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Less_or_equal_lexicographically_d { +public: + +/// \name See Also +/// @{ + +/*! +returns `true` iff \f$ p\f$ is +lexicographically smaller than \f$ q\f$ with respect to Cartesian +lexicographic order of points or equal to \f$ q\f$. + +\pre `p` and `q` have the same dimension. +*/ +bool operator()(const Kernel_d::Point_d& p, const +Kernel_d::Point_d& q); + +/// @} + +}; /* end Kernel_d::Less_or_equal_lexicographically_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Lift_to_paraboloid_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Lift_to_paraboloid_d.h new file mode 100644 index 00000000000..f9dcf71262c --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Lift_to_paraboloid_d.h @@ -0,0 +1,27 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Lift_to_paraboloid_d { +public: + +/// \name See Also +/// @{ + +/*! +returns \f$ p = (x_0,\ldots,x_{d-1})\f$ lifted to the paraboloid of +revolution which is the point \f$ (p_0, \ldots,p_{d-1},\sum_{0 \le i < +d}p_i^2)\f$ in \f$ (d+1)\f$-space. +*/ +Kernel_d::Point_d operator()(const Kernel_d::Point_d& +p); + +/// @} + +}; /* end Kernel_d::Lift_to_paraboloid_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Linear_base_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Linear_base_d.h new file mode 100644 index 00000000000..f89fbf42658 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Linear_base_d.h @@ -0,0 +1,33 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Linear_base_d { +public: + +/// \name See Also +/// @{ + +/*! +computes a basis of the linear space +spanned by the vectors in `A = tuple [first,last)` and returns +it via an iterator range starting in `result`. The returned +iterator marks the end of the output. + +\pre \f$ A\f$ contains vectors of the same dimension \f$ d\f$. +\requires The value type of `ForwardIterator` and `OutputIterator` is `Kernel_d::Vector_d`. +*/ +template int +operator()(ForwardIterator first, ForwardIterator last, +OutputIterator result); + +/// @} + +}; /* end Kernel_d::Linear_base_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Linear_rank_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Linear_rank_d.h new file mode 100644 index 00000000000..8e0de1b2eae --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Linear_rank_d.h @@ -0,0 +1,29 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Linear_rank_d { +public: + +/// \name See Also +/// @{ + +/*! +computes +the linear rank of the vectors in `A = tuple [first,last)`. +\pre \f$ A\f$ contains vectors of the same dimension \f$ d\f$. + +\requires The value type of `ForwardIterator` is `Kernel_d::Vector_d`. +*/ +template int +operator()(ForwardIterator first, ForwardIterator last); + +/// @} + +}; /* end Kernel_d::Linear_rank_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Linearly_independent_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Linearly_independent_d.h new file mode 100644 index 00000000000..fc8ae440801 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Linearly_independent_d.h @@ -0,0 +1,30 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Linearly_independent_d { +public: + +/// \name See Also +/// @{ + +/*! +decides +whether the vectors in `A = tuple [first,last)` are linearly +independent. + +\pre The objects in `A` are of the same dimension. +\requires The value type of `ForwardIterator` is `Kernel_d::Vector_d`. +*/ +template bool +operator()(ForwardIterator first, ForwardIterator last); + +/// @} + +}; /* end Kernel_d::Linearly_independent_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Midpoint_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Midpoint_d.h new file mode 100644 index 00000000000..246ea20ac5b --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Midpoint_d.h @@ -0,0 +1,26 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Midpoint_d { +public: + +/// \name See Also +/// @{ + +/*! +computes the midpoint of the segment +\f$ pq\f$.\pre `p` and `q` have the same dimension. +*/ +Kernel_d::Point_d operator()(const Kernel_d::Point_d& +p, const Kernel_d::Point_d& q); + +/// @} + +}; /* end Kernel_d::Midpoint_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Orientation_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Orientation_d.h new file mode 100644 index 00000000000..ea2cb92f437 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Orientation_d.h @@ -0,0 +1,36 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Orientation_d { +public: + +/// \name See Also +/// @{ + +/*! +determines the orientation of the points of the tuple +`A = tuple [first,last)` where \f$ A\f$ consists of \f$ d + 1\f$ points in +\f$ d\f$-space. This is the sign of the determinant +\f[ \left| \begin{array}{cccc} +1 & 1 & 1 & 1 \\ +A[0] & A[1] & \dots& A[d] +\end{array} \right| \f] +where `A[i]` denotes the Cartesian coordinate vector of +the \f$ i\f$-th point in \f$ A\f$. +\pre `size [first,last) == d+1` and `A[i].dimension() == d` \f$ \forall0 \leq i \leq d\f$. + +\requires The value type of `ForwardIterator` is `Kernel_d::Point_d`. +*/ +template +Orientation operator()(ForwardIterator first, ForwardIterator last); + +/// @} + +}; /* end Kernel_d::Orientation_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Oriented_side_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Oriented_side_d.h new file mode 100644 index 00000000000..653128d03c4 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Oriented_side_d.h @@ -0,0 +1,27 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Oriented_side_d { +public: + +/// \name See Also +/// @{ + +/*! +returns the side of \f$ p\f$ with respect to \f$ o\f$. `Kernel_object` +may be any of `Kernel_d::Sphere_d` or `Kernel_d::Hyperplane_d`. +\pre `p` and `o` have the same dimension. +*/ +template Oriented_side +operator()(const Kernel_object& o, const Kernel_d::Point_d& p); + +/// @} + +}; /* end Kernel_d::Oriented_side_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Orthogonal_vector_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Orthogonal_vector_d.h new file mode 100644 index 00000000000..1047c76d2da --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Orthogonal_vector_d.h @@ -0,0 +1,24 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Orthogonal_vector_d { +public: + +/// \name See Also +/// @{ + +/*! +computes an orthogonal vector to \f$ h\f$. +*/ +Kernel_d::Vector_d operator()(const Kernel_d::Hyperplane_d& h); + +/// @} + +}; /* end Kernel_d::Orthogonal_vector_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_dimension_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_dimension_d.h new file mode 100644 index 00000000000..61d493c710b --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_dimension_d.h @@ -0,0 +1,25 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Point_dimension_d { +public: + +/// \name See Also +/// @{ + +/*! +returns the dimension of \f$ p\f$. +*/ +int operator()(const Kernel_d::Point_d& +p); + +/// @} + +}; /* end Kernel_d::Point_dimension_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_of_sphere_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_of_sphere_d.h new file mode 100644 index 00000000000..294284dfd3c --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_of_sphere_d.h @@ -0,0 +1,24 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Point_of_sphere_d { +public: + +/// \name See Also +/// @{ + +/*! +returns the ith point defining the sphere \f$ s\f$. +*/ +bool operator()(const Kernel_d::Sphere_d& s, int i); + +/// @} + +}; /* end Kernel_d::Point_of_sphere_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_to_vector_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_to_vector_d.h new file mode 100644 index 00000000000..df8d7eafb6a --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Point_to_vector_d.h @@ -0,0 +1,24 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Point_to_vector_d { +public: + +/// \name See Also +/// @{ + +/*! +converts \f$ p\f$ to its geometric vector. +*/ +Kernel_d::Vector_d operator()(const Kernel_d::Point_d& p); + +/// @} + +}; /* end Kernel_d::Point_to_vector_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Project_along_d_axis_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Project_along_d_axis_d.h new file mode 100644 index 00000000000..337c4f922aa --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Project_along_d_axis_d.h @@ -0,0 +1,25 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Project_along_d_axis_d { +public: + +/// \name See Also +/// @{ + +/*! +returns \f$ p\f$ projected along the \f$ d\f$-axis onto the hyperspace +spanned by the first \f$ d-1\f$ standard base vectors. +*/ +Kernel_d::Point_d operator()(const Kernel_d::Point_d& p); + +/// @} + +}; /* end Kernel_d::Project_along_d_axis_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Side_of_bounded_sphere_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Side_of_bounded_sphere_d.h new file mode 100644 index 00000000000..b4171123ea0 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Side_of_bounded_sphere_d.h @@ -0,0 +1,31 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Side_of_bounded_sphere_d { +public: + +/// \name See Also +/// @{ + +/*! +returns the relative position of point +`p` to the sphere defined by `A = tuple [first,last)`. The +order of the points of \f$ A\f$ does not matter. + +\pre `orientation(first,last)` is not `ZERO`. +\requires The value type of `ForwardIterator` is `Kernel_d::Point_d`. +*/ +template Bounded_side +operator()( ForwardIterator first, ForwardIterator last, const +Kernel_d::Point_d& p); + +/// @} + +}; /* end Kernel_d::Side_of_bounded_sphere_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Side_of_oriented_sphere_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Side_of_oriented_sphere_d.h new file mode 100644 index 00000000000..7b733a7e956 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Side_of_oriented_sphere_d.h @@ -0,0 +1,33 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Side_of_oriented_sphere_d { +public: + +/// \name See Also +/// @{ + +/*! +returns the relative position of point +`p` to the oriented sphere defined by the points in `A = tuple [first,last)` The order of the points in \f$ A\f$ is important, +since it determines the orientation of the implicitly constructed +sphere. If the points in \f$ A\f$ are positively oriented, the positive +side is the bounded interior of the sphere. + +\pre `A` contains \f$ d+1\f$ points in \f$ d\f$-space. +\requires The value type of `ForwardIterator` is `Kernel_d::Point_d`. +*/ +template Bounded_side +operator()( ForwardIterator first, ForwardIterator last, const +Kernel_d::Point_d& p); + +/// @} + +}; /* end Kernel_d::Side_of_oriented_sphere_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Squared_distance_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Squared_distance_d.h new file mode 100644 index 00000000000..02ff2e4144f --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Squared_distance_d.h @@ -0,0 +1,28 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Squared_distance_d { +public: + +/// \name See Also +/// @{ + +/*! +computes the square of the Euclidean +distance between the two points \f$ p\f$ and \f$ q\f$. + +\pre The dimensions of \f$ p\f$ and \f$ q\f$ are the same. +*/ +Kernel_d::FT operator()(const Kernel_d::Point_d& p, +const Kernel_d::Point_d& q); + +/// @} + +}; /* end Kernel_d::Squared_distance_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Value_at_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Value_at_d.h new file mode 100644 index 00000000000..5635a34c120 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Value_at_d.h @@ -0,0 +1,28 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Value_at_d { +public: + +/// \name See Also +/// @{ + +/*! +computes the value of \f$ h\f$ evaluated +at \f$ p\f$. + +\pre `p` and `h` have the same dimension. +*/ +Kernel_d::FT operator()(const Kernel_d::Hyperplane_d& +h, const Kernel_d::Point_d& p); + +/// @} + +}; /* end Kernel_d::Value_at_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel--Vector_to_point_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Vector_to_point_d.h new file mode 100644 index 00000000000..83131184997 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel--Vector_to_point_d.h @@ -0,0 +1,24 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +A model for this must provide: + +*/ + +class Kernel_d::Vector_to_point_d { +public: + +/// \name See Also +/// @{ + +/*! +converts \f$ v\f$ to the affine point \f$ 0+v\f$. +*/ +Kernel_d::Point_d operator()(const Kernel_d::Vector_d& v); + +/// @} + +}; /* end Kernel_d::Vector_to_point_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Kernel_d.h b/Kernel_d/doc/Kernel_d/Concepts/Kernel_d.h new file mode 100644 index 00000000000..974753909b1 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Kernel_d.h @@ -0,0 +1,365 @@ + +/*! +\ingroup PkgKernelDKernelConcept +\cgalconcept + +The concept of a kernel is defined by a set of requirements on +the provision of certain types and access member functions to create +objects of these types. The types are function object classes to be used +within the algorithms and data structures in the basic library of \cgal. +This allows you to use any model of a kernel as a traits class in +the \cgal algorithms and data structures, unless they require types +beyond those provided by a kernel. + +`Kernel_d` subsumes the concept of a \f$ d\f$-dimensional kernel. + +A kernel provides types, construction objects, and generalized +predicates. The former replace constructors of the kernel classes and +constructive procedures in the kernel. There are also function objects +replacing operators, especially for equality testing. + +\hasModel `Cartesian_d` +\hasModel `Homogeneous_d` +*/ +class Kernel_d { +public: + +/// \name Types +/// @{ + +/*! +a number type that is a model for `FieldNumberType` +*/ +typedef Hidden_type FT; + +/*! +a number type that is a model for `RingNumberType` +*/ +typedef Hidden_type RT; + +/// @} + +/// \name Coordinate Access +/// @{ + +/*! +a type that allows to iterate over +the Cartesian coordinates +*/ +typedef Hidden_type Cartesian_const_iterator_d; + +/// @} + +/// \name Geometric Objects +/// @{ + +/*! + +*/ +typedef Hidden_type Point_d; + +/*! + +*/ +typedef Hidden_type Vector_d; + +/*! + +*/ +typedef Hidden_type Direction_d; + +/*! + +*/ +typedef Hidden_type Hyperplane_d; + +/*! + +*/ +typedef Hidden_type Line_d; + +/*! + +*/ +typedef Hidden_type Ray_d; + +/*! + +*/ +typedef Hidden_type Segment_d; + +/*! + +*/ +typedef Hidden_type Iso_box_d; + +/*! + +*/ +typedef Hidden_type Sphere_d; + +/*! + +*/ +typedef Hidden_type Aff_transformation_d; + +/// @} + +/// \name Constructions +/// @{ + +/*! + +*/ +typedef Hidden_type Barycentric_coordinates_d; + +/*! +a model of `Kernel_d::Center_of_sphere_d` +*/ +typedef Hidden_type Center_of_sphere_d; + +/*! +a model of `Kernel_d::Compute_coordinate_d` +*/ +typedef Hidden_type Compute_coordinate_d; + +/*! + +*/ +typedef Hidden_type Construct_point_d; + +/*! + +*/ +typedef Hidden_type Construct_vector_d; + +/*! + +*/ +typedef Hidden_type Construct_direction_d; + +/*! + +*/ +typedef Hidden_type Construct_hyperplane_d; + +/*! + +*/ +typedef Hidden_type Construct_segment_d; + +/*! + +*/ +typedef Hidden_type Construct_iso_box_d; + +/*! + +*/ +typedef Hidden_type Construct_line_d; + +/*! + +*/ +typedef Hidden_type Construct_ray_d; + +/*! + +*/ +typedef Hidden_type Construct_sphere_d; + +/*! + +*/ +typedef Hidden_type Construct_aff_transformation_d; + +/*! +a model of `Kernel_d::ConstructCartesianConstIterator_d` +*/ +typedef Hidden_type Construct_cartesian_const_iterator_d; + +/*! +a model of `Kernel_d::Intersect_d` +*/ +typedef Hidden_type Intersect_d; + +/*! +a model of `Kernel_d::Lift_to_paraboloid_d` +*/ +typedef Hidden_type Lift_to_paraboloid_d; + +/*! +a model of `Kernel_d::Linear_base_d` +*/ +typedef Hidden_type Linear_base_d; + +/*! +a model of `Kernel_d::Midpoint_d` +*/ +typedef Hidden_type Midpoint_d; + +/*! +a model of `Kernel_d::Orthogonal_vector_d` +*/ +typedef Hidden_type Orthogonal_vector_d; + +/*! +a model of `Kernel_d::Point_of_sphere_d` +*/ +typedef Hidden_type Point_of_sphere_d; + +/*! +a model of `Kernel_d::Point_to_vector_d` +*/ +typedef Hidden_type Point_to_vector_d; + +/*! +a model of `Kernel_d::Project_along_d_axis_d` +*/ +typedef Hidden_type Project_along_d_axis_d; + +/*! +a model of `Kernel_d::Squared_distance_d` +*/ +typedef Hidden_type Squared_distance_d; + +/*! +a model of `Kernel_d::Value_at_d` +*/ +typedef Hidden_type Value_at_d; + +/*! +a model of `Kernel_d::Vector_to_point_d` +*/ +typedef Hidden_type Vector_to_point_d; + +/// @} + +/// \name Generalized Predicates +/// @{ + +/*! +a model of `Kernel_d::Affine_rank_d` +*/ +typedef Hidden_type Affine_rank_d; + +/*! +a model of `Kernel_d::Affinely_independent_d` +*/ +typedef Hidden_type Affinely_independent_d; + +/*! +a model of `Kernel_d::Compare_lexicographically_d` +*/ +typedef Hidden_type Compare_lexicographically_d; + +/*! +a model of `Kernel_d::Component_accessor_d` +*/ +typedef Hidden_type Component_accessor_d; + +/*! +a model of `Kernel_d::Contained_in_affine_hull_d` +*/ +typedef Hidden_type Contained_in_affine_hull_d; + +/*! +a model of `Kernel_d::Contained_in_linear_hull_d` +*/ +typedef Hidden_type Contained_in_linear_hull_d; + +/*! +a model of `Kernel_d::Contained_in_simplex_d` +*/ +typedef Hidden_type Contained_in_simplex_d; + +/*! +a model of `Kernel_d::Equal_d` +*/ +typedef Hidden_type Equal_d; + +/*! +a model of `Kernel_d::Has_on_positive_side_d` +*/ +typedef Hidden_type Has_on_positive_side_d; + +/*! +a model of `Kernel_d::Less_coordinate_d` +*/ +typedef Hidden_type Less_coordinate_d; + +/*! +a model of `Kernel_d::Less_lexicographically_d` +*/ +typedef Hidden_type Less_lexicographically_d; + +/*! +a model of `Kernel_d::Less_or_equal_lexicographically_d` +*/ +typedef Hidden_type Less_or_equal_lexicographically_d; + +/*! +a model of `Kernel_d::Linear_rank_d` +*/ +typedef Hidden_type Linear_rank_d; + +/*! +a model of `Kernel_d::Linearly_independent_d` +*/ +typedef Hidden_type Linearly_independent_d; + +/*! +a model of `Kernel_d::Orientation_d` +*/ +typedef Hidden_type Orientation_d; + +/*! +a model of `Kernel_d::Oriented_side_d` +*/ +typedef Hidden_type Oriented_side_d; + +/*! +a model of `Kernel_d::Point_dimension_d` +*/ +typedef Hidden_type Point_dimension_d; + +/*! + +*/ +typedef Hidden_type Position_on_line_d; + +/*! +a model of `Kernel_d::Side_of_bounded_sphere_d` +*/ +typedef Hidden_type Side_of_bounded_sphere_d; + +/*! +a model of `Kernel_d::Side_of_oriented_sphere_d` +*/ +typedef Hidden_type Side_of_oriented_sphere_d; + +/// @} + +/// \name Operations +/// The following member functions return function objects of the +/// types listed above. The name of the access function is the name of +/// the type returned with an `_object` suffix and no capital letter +/// at the beginning. We only give two examples to show the +/// scheme. For the functors `Construct_point_d` and `Orientation_d` +/// the corresponding functions are: +/// @{ + +/*! + +*/ +Kernel_d::Construct_point_d construct_point_d_object() const; + +/*! + +*/ +Kernel_d::Orientation_d orientation_d_object() const; + +/// @} + +}; /* end Kernel_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/LinearAlgebraTraits_d.h b/Kernel_d/doc/Kernel_d/Concepts/LinearAlgebraTraits_d.h new file mode 100644 index 00000000000..c24423526af --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/LinearAlgebraTraits_d.h @@ -0,0 +1,183 @@ + +/*! +\ingroup PkgKernelDLinAlgConcepts +\cgalconcept + +The data type `LinearAlgebraTraits_d` encapsulates two classes +`Matrix`, `Vector` and many functions of basic linear algebra. +An instance of data type `Matrix` is a matrix of variables of type +`NT`. Accordingly, `Vector` implements vectors of variables of +type `NT`. Most functions of linear algebra are checkable, +i.e., the programs can be asked for a proof that their output is +correct. For example, if the linear system solver declares a linear +system \f$ A x = b\f$ unsolvable it also returns a vector \f$ c\f$ such that +\f$ c^T A = 0\f$ and \f$ c^T b \neq 0\f$. + +\hasModel `CGAL::Linear_algebraHd` +\hasModel `CGAL::Linear_algebraCd` + +*/ + +class LinearAlgebraTraits_d { +public: + +/// \name Types +/// @{ + +/*! +the number type of the components. +*/ +typedef Hidden_type NT; + +/*! +the vector type. +*/ +typedef Hidden_type Vector; + +/*! +the matrix type. +*/ +typedef Hidden_type Matrix; + +/// @} + +/// \name Operations +/// @{ + +/*! +returns \f$ M^T\f$ +(a `M.column_dimension()` \f$ \times\f$ `M.column_dimension()` - +matrix). +*/ +static Matrix transpose(const Matrix& M); + +/*! +determines whether `M` has an inverse. It also +computes either the inverse as \f$ (1/D) \cdot I\f$ or when no +inverse exists, a vector \f$ c\f$ such that \f$ c^T \cdot M = 0 \f$. +\pre \f$ M\f$ is square. +*/ +static bool inverse(const Matrix& M, Matrix& I, NT& D, +Vector& c); + +/*! +returns the +inverse matrix of `M`. More precisely, \f$ 1/D\f$ times the matrix +returned is the inverse of `M`. +\pre `determinant(M) != 0`. + +\pre \f$ M\f$ is square. +*/ +static Matrix inverse(const Matrix& M, NT& D) ; + +/*! +returns the determinant \f$ D\f$ of +`M` and sufficient information to verify that the value of the +determinant is correct. If the determinant is zero then \f$ c\f$ is a +vector such that \f$ c^T \cdot M = 0\f$. If the determinant is non-zero +then \f$ L\f$ and \f$ U\f$ are lower and upper diagonal matrices respectively +and \f$ q\f$ encodes a permutation matrix \f$ Q\f$ with \f$ Q(i,j) = 1\f$ iff \f$ i = +q(j)\f$ such that \f$ L \cdot M \cdot Q = U\f$, \f$ L(0,0) = 1\f$, \f$ L(i,i) = U(i +- 1,i - 1)\f$ for all \f$ i\f$, \f$ 1 \le i < n\f$, and \f$ D = s \cdot U(n - 1,n - +1)\f$ where \f$ s\f$ is the determinant of \f$ Q\f$. + +\pre `M` is square. +*/ +static NT determinant (const Matrix& M, Matrix& L, Matrix& +U, std::vector& q, Vector& c); + +/*! +verifies the conditions stated above. +*/ +static bool verify_determinant (const Matrix& M, NT D, +Matrix& L, Matrix& U, const std::vector& q, Vector& +c); + +/*! +returns the +determinant of `M`. + +\pre `M` is square. +*/ +static NT determinant (const Matrix& M); + +/*! +returns +the sign of the determinant of `M`. + +\pre `M` is square. +*/ +static int sign_of_determinant (const Matrix& M); + +/*! +determines +the complete solution space of the linear system \f$ M\cdot x = b\f$. If +the system is unsolvable then \f$ c^T \cdot M = 0\f$ and \f$ c^T \cdot b +\not= 0\f$. If the system is solvable then \f$ (1/D) x\f$ is a solution, +and the columns of `spanning_vectors` are a maximal set of +linearly independent solutions to the corresponding homogeneous +system. + +\pre `M.row_dimension() = b.dimension()`. +*/ +static bool linear_solver(const Matrix& M, const Vector& b, +Vector& x, NT& D, Matrix& spanning_vectors, Vector& c); + +/*! +determines whether the linear +system \f$ M\cdot x = b\f$ is solvable. If yes, then \f$ (1/D) x\f$ is a +solution, if not then \f$ c^T \cdot M = 0\f$ and \f$ c^T \cdot b \not= 0\f$. +\pre `M.row_dimension() = b.dimension()`. +*/ +static bool linear_solver(const Matrix& M, const Vector& b, +Vector& x, NT& D, Vector& c) ; + +/*! +as above, but without the witness \f$ c\f$ +\pre `M.row_dimension() = b.dimension()`. +*/ +static bool linear_solver(const Matrix& M, const Vector& b, +Vector& x, NT& D) ; + +/*! +determines whether the system \f$ M \cdot x = b\f$ is solvable + +\pre `M.row_dimension() = b.dimension()`. +*/ +static bool is_solvable(const Matrix& M, const Vector& b) +; + +/*! +determines whether the homogeneous linear system +\f$ M\cdot x = 0\f$ has a non - trivial solution. If yes, then \f$ x\f$ is +such a solution. +*/ +static bool homogeneous_linear_solver (const Matrix& M, +Vector& x); + +/*! +determines the solution space of the +homogeneous linear system \f$ M\cdot x = 0\f$. It returns the dimension +of the solution space. Moreover the columns of `spanning_vecs` +span the solution space. +*/ +static int homogeneous_linear_solver (const Matrix& M, +Matrix& spanning_vecs); + +/*! +returns the indices of a maximal subset +of independent columns of `M`. +*/ +static int independent_columns (const Matrix& M, +std::vector& columns); + +/*! +returns the rank of +matrix `M` +*/ +static int rank (const Matrix & M); + +/// @} + +}; /* end LinearAlgebraTraits_d */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Matrix.h b/Kernel_d/doc/Kernel_d/Concepts/Matrix.h new file mode 100644 index 00000000000..5a812395839 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Matrix.h @@ -0,0 +1,354 @@ + +/*! +\ingroup PkgKernelDLinAlgConcepts +\cgalconcept + +An instance of data type `Matrix` is a matrix of +variables of number type `NT`. The types `Matrix` and `Vector` +together realize many functions of basic linear algebra. + +*/ + +class Matrix { +public: + +/// \name Types +/// @{ + +/*! +the ring type of the components. +*/ +typedef Hidden_type NT; + +/*! +bidirectional iterator for accessing +all components row-wise. +*/ +typedef Hidden_type iterator; + +/*! +bidirectional iterator for accessing +all components row-wise. +*/ +typedef Hidden_type const_iterator; + + +/*! +random access iterator for accessing row +entries. +*/ +typedef Hidden_type row_iterator; + +/*! +random access iterator for accessing row +entries. +*/ +typedef Hidden_type const_row_iterator; + +/*! +random access iterator for accessing +column entries. +*/ +typedef Hidden_type column_iterator; + +/*! +random access iterator for accessing +column entries. +*/ +typedef Hidden_type const_column_iterator; + +/*! +a tag class for identity initialization +*/ +typedef Hidden_type Identity; + +/*! +the vector type used. +*/ +typedef Hidden_type Vector; + +/// @} + +/// \name Creation +/// @{ + +/*! +creates an instance `M` of type +`Matrix`. +*/ +Matrix(); + +/*! +creates an instance `M` of type +`Matrix` of dimension \f$ n \times n\f$ initialized to the zero matrix. + +*/ +Matrix(int n); + +/*! +creates an instance `M` of +type `Matrix` of dimension \f$ m \times n\f$ initialized to the zero +matrix. +*/ +Matrix(int m, int n); + +/*! +creates an instance +`M` of type `Matrix` of dimension +`p.first`\f$ \times\f$`p.second` initialized to the zero matrix. +*/ +Matrix(std::pair p); + +/*! +creates an +instance `M` of type `Matrix` of dimension \f$ n \times n\f$ +initialized to the identity matrix (times `x`). +*/ +Matrix(int n, Identity, NT x = NT(1)); + +/*! +creates an instance `M` +of type `Matrix` of dimension \f$ m \times n\f$ initialized to the +matrix with `x` entries. +*/ +Matrix(int m, int n, NT x); + +/*! +creates an +instance `M` of type `Matrix`. Let \f$ S\f$ be the ordered set of +\f$ n\f$ column-vectors of common dimension \f$ m\f$ as given by the iterator +range `[first,last)`. `M` is initialized to an \f$ m \times n\f$ +matrix with the columns as specified by \f$ S\f$. + +\pre `Forward_iterator` has a value type `V` from which we require to provide a iterator type `V::const_iterator`, to have `V::value_type == NT`. + +Note that `Vector` or `std::vector` fulfill these requirements. +*/ +template +Matrix(Forward_iterator first, Forward_iterator last); + +/*! +creates an instance +`M` of type `Matrix`. Let \f$ A\f$ be an array of \f$ n\f$ +column-vectors of common dimension \f$ m\f$. `M` is initialized to an +\f$ m \times n\f$ matrix with the columns as specified by \f$ A\f$. +*/ +Matrix(std::vector< Vector > A); + +/// @} + +/// \name Operations +/// @{ + +/*! +returns \f$ n\f$, the number of rows of +`M`. +*/ +int row_dimension() ; + +/*! +returns \f$ m\f$, the number of columns +of `M`. +*/ +int column_dimension() ; + +/*! +returns \f$ (m,n)\f$, the +dimension pair of `M`. +*/ +std::pair dimension() ; + +/*! +returns the \f$ i\f$-th row of `M` (an +\f$ m\f$ - vector). + +\pre \f$ 0 \le i \le m - 1\f$. +*/ +Vector row(int i) ; + +/*! +returns the \f$ i\f$-th column of `M` +(an \f$ n\f$ - vector). + +\pre \f$ 0 \le i \le n - 1\f$. +*/ +Vector column(int i) ; + +/*! +returns \f$ M_{i,j}\f$. +\pre \f$ 0\le i\le m-1\f$ and \f$ 0\le j\le n-1\f$. +*/ +NT& operator()(int i, int j) ; + +/*! +swaps rows \f$ i\f$ and \f$ j\f$. +\pre \f$ 0\le i\le m-1\f$ and \f$ 0\le j\le m-1\f$. + +*/ +void swap_rows(int i, int j) ; + +/*! +swaps columns \f$ i\f$ and +\f$ j\f$. + +\pre \f$ 0\le i\le n-1\f$ and \f$ 0\le j\le n-1\f$. +*/ +void swap_columns(int i, int j) ; + +/*! +an iterator pointing to the +first entry of the \f$ i\f$th row. + +\pre \f$ 0\le i\le m-1\f$. +*/ +row_iterator row_begin(int i) ; + +/*! +an iterator pointing beyond +the last entry of the \f$ i\f$th row. + +\pre \f$ 0\le i\le m-1\f$. +*/ +row_iterator row_end(int i) ; + +/*! +an iterator pointing to the +first entry of the \f$ i\f$th row. + +\pre \f$ 0\le i\le m-1\f$. +*/ +const_row_iterator row_begin(int i) const; + +/*! +an iterator pointing beyond +the last entry of the \f$ i\f$th row. + +\pre \f$ 0\le i\le m-1\f$. +*/ +const_row_iterator row_end(int i) const; + +/*! +an iterator pointing +to the first entry of the \f$ i\f$th column. + +\pre \f$ 0\le i\le n-1\f$. + +*/ +column_iterator column_begin(int i) ; + +/*! +an iterator pointing +beyond the last entry of the \f$ i\f$th column. + +\pre \f$ 0\le i\le n-1\f$. +*/ +column_iterator column_end(int i) ; + +/*! +an iterator pointing +to the first entry of the \f$ i\f$th column. + +\pre \f$ 0\le i\le n-1\f$. + +*/ +const_column_iterator column_begin(int i) const; + +/*! +an iterator pointing +beyond the last entry of the \f$ i\f$th column. + +\pre \f$ 0\le i\le n-1\f$. +*/ +const_column_iterator column_end(int i) const; + + +/*! +an iterator pointing to the first entry +of \f$ M\f$. +*/ +iterator begin(); + +/*! +an iterator pointing beyond the last entry +of \f$ M\f$. +*/ +terator end(); + +/*! +an iterator pointing to the first entry +of \f$ M\f$. +*/ +const_iterator begin() const; + +/*! +an iterator pointing beyond the last entry +of \f$ M\f$. +*/ +const_terator end() const; + + +/*! +Test for equality. +*/ +bool operator==(const Matrix& M1) ; + +/*! +Test for inequality. +*/ +bool operator!=(const Matrix& M1) ; + +/// @} + +/// \name Arithmetic Operators +/// @{ + +/*! +Addition. +\pre `M.row_dimension() == M1.row_dimension()` +\pre `M.column_dimension() == M1.column_dimension()` +*/ +Matrix operator+ (const Matrix& M1); + +/*! + +Subtraction. +\pre `M.row_dimension() == M1.row_dimension()` +\pre `M.column_dimension() == M1.column_dimension()` +*/ +Matrix operator- (const Matrix& M1); + +/*! +Negation. +*/ +Matrix operator-(); + +/*! +Multiplication. + +\pre `M.column_dimension() = M1.row_dimension()` +*/ +Matrix operator*(const Matrix& M1) +; + +/*! +Multiplication with +vector. + +\pre `M.column_dimension() = vec.dimension()` +*/ +Vector operator*(const Vector& vec) ; + +/*! +Multiplication of every entry with `x`. +*/ +Matrix operator*(const NT& x, const Matrix& M); + +/*! +Multiplication of every entry with `x`. +*/ +Matrix operator*(const Matrix& M, const NT& x) ; + +/// @} + +}; /* end Matrix */ + diff --git a/Kernel_d/doc/Kernel_d/Concepts/Vector.h b/Kernel_d/doc/Kernel_d/Concepts/Vector.h new file mode 100644 index 00000000000..a7259795fb2 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Concepts/Vector.h @@ -0,0 +1,172 @@ + +/*! +\ingroup PkgKernelDLinAlgConcepts +\cgalconcept + +An instance of data type `Vector` is a vector of variables of +number type `NT`. Together with the type `Matrix` it realizes +the basic operations of linear algebra. + +Operations +-------------- + +The same operations `begin()`, `end()` exist for +`const_iterator`. + +*/ + +class Vector { +public: + +/// \name Types +/// @{ + +/*! +the ring type of the components. +*/ +typedef Hidden_type NT; + +/*! +the iterator type for accessing components. +*/ +typedef Hidden_type iterator; + +/*! +the const iterator type for accessing +components. +*/ +typedef Hidden_type const_iterator; + +/// @} + +/// \name Creation +/// @{ + +/*! +creates an instance `v` of type +`Vector`. +*/ +Vector(); + +/*! +creates an instance `v` of type +`Vector`. `v` is initialized to a vector of dimension \f$ d\f$. + +*/ +Vector(int d); + +/*! +creates an instance `v` of +type `Vector`. `v` is initialized to a vector of dimension +\f$ d\f$ with entries `x`. +*/ +Vector(int d, NT x); + +/*! +creates an +instance `v` of type `Vector`; `v` is initialized to the +vector with entries `set [first,last)`. +\requires `Forward_iterator` has value type `NT`. +*/ +template +Vector(Forward_iterator first, Forward_iterator last); + +/// @} + +/// \name Operations +/// @{ + +/*! +returns the dimension of `v`. +*/ +int dimension() ; + +/*! +returns true iff `v` is the zero +vector. +*/ +bool is_zero() ; + +/*! +returns the \f$ i\f$-th component of `v`. + +\pre \f$ 0\le i \le v.dimension()-1\f$. +*/ +NT& operator[](int i) ; + +/*! +iterator to the first component. +*/ +iterator begin() ; + +/*! +iterator beyond the last component. +*/ +iterator end() ; + +/*! +Addition. + +\pre `v.dimension() == v1.dimension()`. +*/ +Vector operator+(const Vector& v1) ; + +/*! +Subtraction. + +\pre `v.dimension() = v1.dimension()`. +*/ +Vector operator-(const Vector& v1) ; + +/*! +Inner Product. + +\pre `v.dimension() = v1.dimension()`. +*/ +NT operator*(const Vector& v1) ; + +/*! +Negation. +*/ +Vector operator-() ; + +/*! +Addition plus assignment. + +\pre `v.dimension() == v1.dimension()`. +*/ +Vector& operator+=(const Vector& v1); + +/*! +Subtraction plus assignment. + +\pre `v.dimension() == v1.dimension()`. +*/ +Vector& operator-=(const Vector& v1); + +/*! +Scalar multiplication plus +assignment. +*/ +Vector& operator*=(const NT& s); + +/*! +Scalar division plus assignment. + +*/ +Vector& operator/=(const NT& s); + +/*! +Component-wise multiplication with number \f$ r\f$. +*/ +Vector operator*(const NT& r, const Vector& v); + +/*! +Component-wise multiplication with number \f$ r\f$. +*/ +Vector operator*(const Vector& v, const NT& r); + +/// @} + +}; /* end Vector */ + diff --git a/Kernel_d/doc/Kernel_d/Kernel_d.txt b/Kernel_d/doc/Kernel_d/Kernel_d.txt new file mode 100644 index 00000000000..01fba7e24db --- /dev/null +++ b/Kernel_d/doc/Kernel_d/Kernel_d.txt @@ -0,0 +1,516 @@ +namespace CGAL { +/*! + +\mainpage dD Geometry Kernel +\autotoc +\authors Michael Seel + +# Introduction # + +This part of the reference manual covers the higher-dimensional +kernel. The kernel contains objects of constant size, such as point, +vector, direction, line, ray, segment, circle. With each type comes a +set of functions which can be applied to an object of this type. You +will typically find access functions (e.g. to the coordinates of a +point), tests of the position of a point relative to the object, a +function returning the bounding box, the length, or the area of an +object, and so on. The \cgal kernel further contains basic +operations such as affine transformations, detection and computation +of intersections, and distance computations. Note that this section +partly recapitulates facts already mentioned for the lower-dimensional +kernel. + +## Robustness ## + +The correctness proof of nearly all geometric algorithms presented in +theory papers assumes exact computation with real numbers. This leads +to a fundamental problem with the implementation of geometric +algorithms. Naively, often the exact real arithmetic is replaced by +inexact floating-point arithmetic in the implementation. This often +leads to acceptable results for many input data. However, even for +the implementation of the simplest geometric algorithms this +simplification occasionally does not work. Rounding errors introduced +by inaccurate arithmetic may lead to inconsistent decisions, causing +unexpected failures for some correct input data. There are many +approaches to this problem, one of them is to compute exactly (compute +so accurate that all decisions made by the algorithm are exact) which +is possible in many cases but more expensive than standard +floating-point arithmetic. C. M. Hoffmann \cite h-gsm-89, \cite h-pargc-89 +illustrates some of the problems arising in the implementation of +geometric algorithms and discusses some approaches to solve them. A +more recent overview is given in \cite s-rpigc-00. The exact +computation paradigm is discussed by Yap and Dubé \cite yd-ecp-95 +and Yap \cite y-tegc-97. + +In \cgal you can choose the underlying number types and arithmetic. +You can use different types of arithmetic simultaneously and the +choice can be easily changed, e.g. for testing. So you can choose +between implementations with fast but occasionally inexact arithmetic +and implementations guaranteeing exact computation and exact results. +Of course you have to pay for the exactness in terms of execution time +and storage space. See the dedicated chapter for more details +on number types and their capabilities and performance. + +## Genericity ## + +To increase generic usage of objects and predicates the +higher-dimensional kernel makes heavy use of iterator ranges as +defined in the STL for modeling tuples. Iterators conceptualize C++ +pointers. + +For an iterator range `[first,last)` we define `T = tuple [first,last)` as the ordered tuple \f$ (T[0],T[1], \ldots T[d-1])\f$ +where \f$ S[i] = *++^{(i)}\mathit{first}\f$ (the element obtained by \f$ i\f$ +times forwarding the iterator by operator `++` and then +dereferencing it to get the value to which it points). We write `d = size [first,last)` and `S = set [first,last)` to denote the +unordered set of elements of the corresponding tuple. + +This extends the syntax of random access iterators to input iterators. +If we index the tuple as above then we require that +\f$ ++^{(d+1)}\mathit{first} = \mathit{last}\f$. + +# Kernel Representations # + +Our object of study is the \f$ d\f$-dimensional affine Euclidean space, +where \f$ d\f$ is a parameter of our geometry. Objects in that space are +sets of points. A common way to represent the points is the use of +Cartesian coordinates, which assumes a reference +frame (an origin and \f$ d\f$ orthogonal axes). In that framework, a point +is represented by a \f$ d\f$-tuple \f$ (c_0,c_1,\ldots,c_{d-1})\f$, +and so are vectors in the underlying linear space. Each point is +represented uniquely by such Cartesian +coordinates. + +Another way to represent points is by homogeneous coordinates. In that +framework, a point is represented by a \f$ (d+1)\f$-tuple \f$ (h_0,h_1,\ldots,h_d)\f$. +Via the formulae \f$ c_i = h_i/h_d\f$, +the corresponding point with Cartesian coordinates +\f$ (c_0,c_1,\ldots,c_{d-1})\f$ +can be computed. Note that homogeneous coordinates are not unique. +For \f$ \lambda\ne 0\f$, the tuples \f$ (h_0,h_1,\ldots,h_d)\f$ and +\f$ (\lambda\cdot h_0,\lambda\cdot h_1,\ldots,\lambda\cdot h_d)\f$ +represent the same point. +For a point with Cartesian coordinates +\f$ (c_0,c_1,\ldots,c_{d-1})\f$ a +possible homogeneous representation is +\f$ (c_0,c_1,\ldots,c_{d-1},1)\f$. +Homogeneous coordinates in fact allow to represent +objects in a more general space, the projective space \f$ \mathbb{P}^d\f$. +In \cgal, we do not compute in projective geometry. Rather, we use +homogeneous coordinates to avoid division operations, +since the additional coordinate can serve as a common denominator. + +## Genericity through Parameterization ## + +Almost all the kernel objects (and the corresponding functions) are +templates with a parameter that allows the user to choose the +representation of the kernel objects. A type that is used as an +argument for this parameter must fulfill certain requirements on +syntax and semantics. The list of requirements defines an abstract +kernel concept. In \cgal such a kernel concept is often also called a +representation class and denoted by `R`. A representation +class provides the actual implementations of the kernel objects. For +all kernel objects `Kernel_object`, the types +`CGAL::Kernel_object` and `R::Kernel_object` are identical. + +\cgal offers two families of concrete models for the concept +representation class, one based on the Cartesian +representation of points and one based on the homogeneous +representation of points. The interface of the kernel objects is +designed such that it works well with both +Cartesian and homogeneous representation, for +example, points have a constructor with a range of coordinates plus a +common denominator (the \f$ d+1\f$ homogeneous coordinates of the point). +The common interfaces parameterized with a representation class allow +one to develop code independent of the chosen representation. We said +"families" of models, because both families are parameterized too. +A user can choose the number type used to represent the coordinates +and the linear algebra module used to calculate the result of +predicates and constructions. + +For reasons that will become evident later, a representation class +provides two typenames for number types, +namely `R::FT` and `R::RT` and one typename for the linear +algebra module `R::LA`. +The type `R::FT` must fulfill the +requirements on what is called a field type in \cgal. This +roughly means that `R::FT` is a type for which operations \f$ +\f$, +\f$ -\f$, \f$ *\f$ and \f$ /\f$ are defined with semantics (approximately) +corresponding to those of a field in a mathematical sense. Note that, +strictly speaking, the built-in type `int` does not fulfill the +requirements on a field type, since `int`s correspond to elements +of a ring rather than a field, especially operation \f$ /\f$ is not the +inverse of \f$ *\f$. The requirements on the type `R::RT` are +weaker. This type must fulfill the requirements on what is called an +Euclidean ring type in \cgal. This roughly means that +`R::RT` is a type for which operations \f$ +\f$, \f$ -\f$, \f$ *\f$ are +defined with semantics (approximately) corresponding to those of a +ring in a mathematical sense. A very limited division operation \f$ /\f$ +must be available as well. It must work for exact (i.e., no +remainder) integer divisions only. Furthermore, both number types +should fulfill \cgal's requirements on a number type. + +## Cartesian Kernel ## + +With `Cartesian_d` you can choose +Cartesian representation of coordinates. The type +`LinearAlgebra` must me a linear algebra module working on numbers +of type `FieldNumberType`. The second parameter defaults to module +delivered with the kernel so for short a user can just write +`Cartesian_d` when not providing her own linear +algebra. + +When you choose Cartesian representation you have +to declare at least the type of the coordinates. A number type used +with the `Cartesian_d` representation class should be a field +type as described above. Both `Cartesian::FT` +and `Cartesian::RT` are mapped to number type +`FieldNumberType`. +`Cartesian_d::LA` is mapped to the +type `LinearAlgebra`. `Cartesian` uses +reference counting internally to save copying costs. + +## Homogeneous Kernel ## + +As we mentioned before, homogeneous coordinates permit to avoid +division operations in numerical computations, since the additional +coordinate can serve as a common denominator. Avoiding divisions can +be useful for exact geometric computation. With +`Homogeneous_d` you can choose +homogeneous representation of coordinates with the kernel objects. +As for Cartesian representation you have to declare +at the same time the type used to store the homogeneous coordinates. +Since the homogeneous representation allows one to avoid the +divisions, the number type associated with a homogeneous +representation class must be a model for the weaker concept Euclidean +ring type only. + +The type `LinearAlgebra` must me a linear algebra module working +on numbers of type `RingNumberType`. Again the second parameter +defaults to module delivered with the kernel so for short one can just +write `Homogeneous_d` when replacing the default +is no issue. + +However, some operations provided by this kernel involve division +operations, for example computing squared distances or returning a +Cartesian coordinate. To keep the requirements on +the number type parameter of `Homogeneous` low, the number type +`Quotient` is used instead. This number type +turns a ring type into a field type. It maintains numbers as +quotients, i.e. a numerator and a denominator. Thereby, divisions are +circumvented. With `Homogeneous_d`, +`Homogeneous_d::FT` is equal to +`Quotient` while +`Homogeneous_d::RT` is equal to +`RingNumberType`. +`Homogeneous_d::LA` is mapped to the +type `LinearAlgebra`. + +## Naming conventions ## + +The use of representation classes not only avoids problems, it also +makes all \cgal classes very uniform. They always consist of: +
    + +
  1. The capitalized base name of the geometric object, such as +`Point`, `Segment`, `Triangle`. + +
  2. Followed by `_d`. + +
  3. A representation class as parameter, which itself is +parameterized with a number type, such as +`Cartesian_d` or `Homogeneous_d`. +
+ +## Kernel as a Traits Class ## + +Algorithms and data structures in the basic library of \cgal are +parameterized by a traits class that subsumes the objects on which the +algorithm or data structure operates as well as the operations to do +so. For most of the algorithms and data structures in the basic +library you can use a kernel as a traits class. For some algorithms +you even do not have to specify the kernel; it is detected +automatically using the types of the geometric objects passed to the +algorithm. In some other cases, the algorithms or data structures +needs more than is provided by a kernel. In these cases, a kernel can +not be used as a traits class. + +## Choosing a Kernel ## + +If you start with integral Cartesian coordinates, +many geometric computations will involve integral numerical values +only. Especially, this is true for geometric computations that +evaluate only predicates, which are tantamount to determinant +computations. Examples are triangulation of point sets and convex hull +computation. + +The dimension \f$ d\f$ of our affine space determines the dimension of the +matrix computations in the mathematical evaluation of predicates. As +rounding errors accumulate fast the homogeneous representation used +with multi-precision integers is the kernel of choice for well-behaved +algorithms. Note, that unless you use an arbitrary precision integer +type, incorrect results might arise due to overflow. + +If new points are to be constructed, for example the +intersection point of two lines, computation of +Cartesian coordinates usually involves divisions, +so you need to use a field type with Cartesian +representation or have to switch to homogeneous representation. +`double` is a possible, but imprecise field type. You can also +put any ring type into `Quotient` to get a field type and put it +into `Cartesian`, but you better put the ring type into +`Homogeneous`. `leda_rational` and `leda_real` are valid +field types, too. + +Still other people will prefer the built-in type double, because +they need speed and can live with approximate results, or even +algorithms that, from time to time, crash or compute incorrect results +due to accumulated rounding errors. + +## Inclusion of Header Files ## + +You need just to include a representation class to obtain the +geometric objects of the kernel that you would like to use with the +representation class, i.e., `CGAL/Cartesian_d.h` or +`CGAL/Homogeneous_d.h` + +# Kernel Geometry # + +## Points and Vectors ## + +In \cgal, we strictly distinguish between points, vectors and +directions. A point is a point in the Euclidean space \f$ \E^d\f$, a +vector is the difference of two points \f$ p_2\f$, \f$ p_1\f$ and denotes +the direction and the distance from \f$ p_1\f$ to \f$ p_2\f$ in the vector space +\f$ \R^d\f$, and a direction is a vector where we forget about its +length. They are different mathematical concepts. For example, they +behave different under affine transformations and an addition of two +points is meaningless in affine geometry. By putting them in +different classes we not only get cleaner code, but also type checking +by the compiler which avoids ambiguous expressions. Hence, it pays +twice to make this distinction. + +\cgal defines a symbolic constant `ORIGIN` of type +`Origin` which denotes the point at the origin. This constant is +used in the conversion between points and vectors. Subtracting it from +a point \f$ p\f$ results in the locus vector of \f$ p\f$. + +\code{.cpp} +double coord[] = {1.0, 1.0, 1.0, 1.0}; +Point_d< Cartesian_d > p(4,coord,coord+4), q(4); +Vector_d< Cartesian_d > v(4); +v = p - ORIGIN; +q = ORIGIN + v; +assert( p == q ); +\endcode + +In order to obtain the point corresponding to a vector \f$ v\f$ you simply +have to add \f$ v\f$ to `ORIGIN`. If you want to determine +the point \f$ q\f$ in the middle between two points \f$ p_1\f$ and \f$ p_2\f$, you can +write\footnote{you might call `midpoint(p_1,p_2)` instead} + +\code{.cpp} +q = p_1 + (p_2 - p_1) / 2.0; +\endcode + +Note that these constructions do not involve any performance overhead +for the conversion with the currently available representation +classes. + +## Kernel Objects ## + +Besides points (`Point_d`), vectors (`Vector_d`), and +directions (`Direction_d`), \cgal provides lines, rays, +segments, hyperplanes, and spheres. + +Lines (`Line_d`) in \cgal are oriented. A ray +(`Ray_d`) is a semi-infinite interval on a line, and this line +is oriented from the finite endpoint of this interval towards any +other point in this interval. A segment (`Segment_d`) is a +bounded interval on a directed line, and the endpoints are ordered so +that they induce the same direction as that of the line. + +Hyperplanes are affine subspaces of dimension \f$ d-1\f$ in \f$ \E^d\f$, passing +through \f$ d\f$ points. Hyperplanes are oriented and partition space into +a positive side and a negative side. In \cgal, there are no special +classes for halfspaces. Halfspaces are supposed to be represented by +oriented hyperplanes. All kernel objects are equality comparable via +`operator==` and `operator!=`. For those oriented objects +whose orientation can be reversed (segments, lines, hyperplanes, +spheres) there is also a global function `weak_equality` that +allows to test for point set equality disregarding the orientation. + +## Orientation and Relative Position ## + +Geometric objects in \cgal have member functions that test the +position of a point relative to the object. Full dimensional objects +and their boundaries are represented by the same type, e.g. +halfspaces and hyperplanes are not distinguished, neither are balls +and spheres. Such objects split the ambient space into two +full-dimensional parts, a bounded part and an unbounded part (e.g. +spheres), or two unbounded parts (e.g. hyperplanes). By default these +objects are oriented, i.e., one of the resulting parts is called the +positive side, the other one is called the negative side. Both of +these may be unbounded. + +For these objects there is a function `oriented_side()` that +determines whether a test point is on the positive side, the negative +side, or on the oriented boundary. These function returns a value of +type `Oriented_side`. + +Those objects that split the space in a bounded and an unbounded part, +have a member function `bounded_side()` with return type +`Bounded_side`. + +If an object is lower dimensional, e.g. a segment in \f$ d\f$-dimensional +space, there is only a test whether a point belongs to the object or +not. This member function, which takes a point as an argument and +returns a Boolean value, is called `has_on()` + +# Predicates and Constructions # + +## Predicates ## + +Predicates are at the heart of a geometry kernel. They are basic units +for the composition of geometric algorithms and encapsulate +decisions. Hence their correctness is crucial for the control flow +and hence for the correctness of an implementation of a geometric +algorithm. \cgal uses the term predicate in a generalized sense. Not +only components returning a Boolean value are called predicates but +also components returning an enumeration type like a +`Comparison_result` or an `Orientation`. We say components, +because predicates are implemented both as functions and function +objects (also called functors and provided by a kernel class). + +\cgal provides predicates for the orientation of +point sets (`orientation`), for comparing points according to some +given order, especially for comparing Cartesian coordinates +(e.g. `lexicographically_xy_smaller`), in-sphere tests, and +predicates to compare distances. + +## Constructions ## + +Functions and function objects that generate objects that are neither +of type `bool` nor enum types are called constructions. +Constructions involve computation of new numerical values and may be +imprecise due to rounding errors unless a kernel with an exact number +type is used. + +Affine transformations (`Aff_transformation_d`) allow to +generate new object instances under arbitrary affine transformations. +These transformations include translations, rotations (within planes) +and scaling. Most of the geometric objects in a kernel have a member +function `transform(Aff_transformation t)` which applies the +transformation to the object instance. + +\cgal also provides a set of functions that detect or compute the +intersection between objects +and functions to calculate their squared +distance. Moreover, some +member functions of kernel objects are constructions. + +So there are routines that compute the square of the Euclidean +distance, but no routines that compute the distance itself. Why? +First of all, the two values can be derived from each other quite +easily (by taking the square root or taking the square). So, supplying +only the one and not the other is only a minor inconvenience for the +user. Second, often either value can be used. This is for example the +case when (squared) distances are compared. Third, the library wants +to stimulate the use of the squared distance instead of the distance. +The squared distance can be computed in more cases and the computation +is cheaper. We do this by not providing the perhaps more natural +routine, The problem of a distance routine is that it needs the +`sqrt` operation. This has two drawbacks: +
    +
  • The `sqrt` operation can be costly. Even if it is not +very costly for a specific number type and platform, avoiding it is +always cheaper. +
  • There are number types on which no `sqrt` operation is +defined, especially integer types and rationals. +
+ +## Intersection and Polymorphic Return Values ## + +Intersections on kernel objects currently cover only those objects +that are part of flats (`Segment_d`, `Ray_d`, +`Line_c`, and `Hyperplane_d`). For any pair of objects +\f$ o1\f$, \f$ o2\f$ of these types the operation `intersection(o1,o2)` +returns a polymorphic object that wraps the result of the intersection +operation. + +The class `Object` provides the polymorphic abstraction. An +object `obj` of type `Object` can represent an arbitrary +class. The only operations it provides is to make copies and +assignments, so that you can put them in lists or arrays. Note that +`Object` is NOT a common base class for the elementary classes. +Therefore, there is no automatic conversion from these classes to +`Object` Rather this is done with the global function +`make_object()`. This encapsulation mechanism requires the use of +`object_cast` to unwrap the encapsulated class. + +### Example ### + +In the following example, the object type is used as a return value for +the intersection computation, as there are +possibly different return values. + +\code{.cpp} +typedef Point_d< Cartesian_d > Point; +typedef Segment_d< Cartesian_d > Segment; +Segment s1, s2; +std::cin >> s1 >> s2; +Object obj = intersection(s1, s2); +if (const Point *p = object_cast(&obj) ) { +// do something with *p +} else if (const Segment *s = object_cast(&obj) ) { +// do something with *s +} +// there was no intersection +\endcode + +## Constructive Predicates ## + +For testing where a point \f$ p\f$ lies with respect to a hyperplane +defined by an array \f$ P\f$ of points \f$ p_1\f$, ... , \f$ p_d\f$, one may be +tempted to construct the hyperplane `Hyperplane_d(d,P,P+d)` and +use the method `oriented_side(p)`. This may pay off if many tests +with respect to the plane are made. Nevertheless, unless the number +type is exact, the constructed plane is only approximated, and +round-off errors may lead `oriented_side(p)` to return an +orientation which is different from the +orientation of \f$ p_1\f$, ... , \f$ p_d\f$, \f$ p\f$. + +In \cgal, we provide predicates in which such geometric decisions +are made directly with a reference to the input points in \f$ P\f$ without +an intermediary object like a plane. For the above test, the +recommended way to get the result is to use +`orientation(P',P'+d)`, where \f$ P'\f$ is an array containing the +points \f$ p_1\f$, ... , \f$ p_d\f$, \f$ p\f$. + +For exact number types like `leda_real`, the situation is +different. If several tests are to be made with the same plane, it +pays off to construct the plane and to use `oriented_side(p)`. + +# Design and Implementation History # + +This higher-dimensional kernel is the result of a long evolving +development. A first version of the kernel was offered as a LEDA +extension package ddgeo by Kurt Mehlhorn and Michael Seel. The +original design was driven by the realization of a d-dimensional +convex hull data type developed at the +Max-Planck Institut für Informatik. + +The code base was discussed and reviewed within the \cgal kernel group +(of the low-dimensional kernel). This led to the identification of +the concept interfaces and in parallel to adaptations according to the +evolution of the low-dimensional kernel. The kernel was revised +based on suggestions by Hervé Brönnimann, Michael Hoffmann, and +Stefan Schirra. + +## Acknowledgments ## + +This work was supported by ESPRIT IV Long Term Research Projects +No. 21957 (CGAL) and No. 28155 (GALIA). + +*/ +} /* namespace CGAL */ + diff --git a/Kernel_d/doc/Kernel_d/PackageDescription.txt b/Kernel_d/doc/Kernel_d/PackageDescription.txt new file mode 100644 index 00000000000..3aa1180ab89 --- /dev/null +++ b/Kernel_d/doc/Kernel_d/PackageDescription.txt @@ -0,0 +1,34 @@ +/// \defgroup PkgKernelD dD Geometry Kernel + +/// \defgroup PkgKernelDLinAlgConcepts Linear Algebra Concepts +/// \ingroup PkgKernelD + +/// \defgroup PkgKernelDLinAlgClasses Linear Algebra Classes +/// \ingroup PkgKernelD + +/// \defgroup PkgKernelDKernels Kernels +/// \ingroup PkgKernelD + +/// \defgroup PkgKernelDKernelObjs Kernel Objects +/// \ingroup PkgKernelD + +/// \defgroup PkgKernelDFunctions Global Kernel Functions +/// \ingroup PkgKernelD + +/// \defgroup PkgKernelDKernelConcept Kernel Concept +/// \ingroup PkgKernelD + + +/*! +\addtogroup PkgKernelD +\todo check generated documentation +\PkgDescriptionBegin{dD Geometry Kernel} +\PkgPicture{hypercube.png} +\PkgAuthor{Michael Seel} +\PkgDesc{The dD Kernel contains objects of constant size, such as point, vector, direction, line, ray, segment, circle in d dimensional Euclidean space, as well as predicates and constructions for these objects.} +\PkgSince{1.1} +\cgalbib{cgal:s-gkd} +\license{\ref licensesLGPL "LGPL"} +\PkgDescriptionEnd +*/ + diff --git a/Kernel_d/doc/Kernel_d/fig/hypercube.png b/Kernel_d/doc/Kernel_d/fig/hypercube.png new file mode 100644 index 0000000000000000000000000000000000000000..02b7f6bb1c096aca18c25e7869634893ce7d338b GIT binary patch literal 18676 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 z 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