diff --git a/CMakeLists.txt b/CMakeLists.txt
index d0fa70ba..61b243a4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,11 @@ option(BUILD_AS_SHARED_LIBRARY "Build the project as shared libraries?" OFF)
#message("gotools: BUILD_AS_SHARED_LIBRARY: " ${BUILD_AS_SHARED_LIBRARY})
option(GoTools_COPY_DATA "Copy data?" ON)
+IF(GoTools_COPY_DATA)
+ FILE(COPY gotools-data
+ DESTINATION ${GoTools_BINARY_DIR}
+ PATTERN .git EXCLUDE)
+ENDIF()
OPTION(GoTools_ENABLE_OPENMP "Include OPENMP?" OFF)
IF(GoTools_ENABLE_OPENMP)
diff --git a/Doxyfile b/Doxyfile
index 5b076797..7d942725 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -750,13 +750,15 @@ EXCLUDE_SYMBOLS =
EXAMPLE_PATH = ttl/examples/hesimplest \
compositemodel/examples \
+ lrsplines2D/examples \
+ lrsplines3D/examples \
trivariate/examples \
trivariatemodel/examples \
qualitymodule/examples \
parameterization/examples \
sisl/examples \
implicitization/examples \
- gotools-core/examples\
+ gotools-core/examples \
igeslib/examples
@@ -782,6 +784,8 @@ IMAGE_PATH = gotools-core/doc/images \
compositemodel/doc/images \
trivariate/doc/images \
trivariatemodel/doc/images \
+ lrsplines2D/doc/images \
+ lrsplines3D/doc/images \
ttl/doc/images
# The INPUT_FILTER tag can be used to specify a program that doxygen should
@@ -1234,7 +1238,8 @@ FORMULA_TRANSPARENT = YES
# output. When enabled you may also need to install MathJax separately and
# configure the path to it using the MATHJAX_RELPATH option.
-USE_MATHJAX = NO
+EXTRA_PACKAGES = mathtools amsmath
+USE_MATHJAX = YES
# When MathJax is enabled you can set the default output format to be used for
# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
@@ -1253,7 +1258,8 @@ MATHJAX_FORMAT = HTML-CSS
# However, it is strongly recommended to install a local
# copy of MathJax from http://www.mathjax.org before deployment.
-MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_HTMLorMML
+#../../../programs/node_modules/mathjax
# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
# names that should be enabled during MathJax rendering.
@@ -1333,7 +1339,7 @@ GENERATE_LATEX = NO
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
-LATEX_OUTPUT =
+LATEX_OUTPUT =
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
diff --git a/compositemodel/Doxyfile b/compositemodel/Doxyfile
index af8d0414..29ed3c5b 100644
--- a/compositemodel/Doxyfile
+++ b/compositemodel/Doxyfile
@@ -1349,6 +1349,11 @@ GENERATE_LEGEND = YES
DOT_CLEANUP = YES
+EXTRA_PACKAGES = mathtools amsmath
+USE_MATHJAX = YES
+MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_HTMLorMML
+#../../../../programs/node_modules/mathjax
+
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
diff --git a/compositemodel/include/GoTools/compositemodel/CompositeModelFileHandler.h b/compositemodel/include/GoTools/compositemodel/CompositeModelFileHandler.h
index 6354b11e..dd363089 100644
--- a/compositemodel/include/GoTools/compositemodel/CompositeModelFileHandler.h
+++ b/compositemodel/include/GoTools/compositemodel/CompositeModelFileHandler.h
@@ -57,8 +57,8 @@ namespace Go
{
-// Writing to and reading from the g22 file format.
-// Supports topology information (as opposed to the g2 format for geometries only).
+/// Writing to and reading from the g22 file format.
+/// Supports topology information (as opposed to the g2 format for geometries only).
class ParamSurface;
class CompositeModelFileHandler
diff --git a/compositemodel/include/GoTools/compositemodel/compositemodel-doxymain.h b/compositemodel/include/GoTools/compositemodel/compositemodel-doxymain.h
index d1365cf1..863f2999 100644
--- a/compositemodel/include/GoTools/compositemodel/compositemodel-doxymain.h
+++ b/compositemodel/include/GoTools/compositemodel/compositemodel-doxymain.h
@@ -71,21 +71,21 @@ A CAD model can normally not be represented by one geometry entity like
the ones in gotools-core. The need for sets of entities, adjacency analysis and
representation of adjacency arises. There is a need for topological structures.
-\link Go::Body \endlink is a boundary represented solid model. It is a virtual volume limited
+\link Go::Body Body \endlink is a boundary represented solid model. It is a virtual volume limited
by one or more shells, one outer and possibly a number of inner ones. The
shells are represented by the class SurfaceModel which is also the entity used
-to represent a face set. In addition to being a topological entity, \link Go::SurfaceModel \endlink
+to represent a face set. In addition to being a topological entity, \link Go::SurfaceModel SurfaceModel \endlink
provides an interface which views the set of surfaces as one entity. Thus, an
operation like closest point computation can be performed without caring
about which surface is closest to the point.
The surface model consists of a set of faces represented by the class
- \link Go::ftSurface \endlink. The face represents the abstract idea of a bounded surface, but it also
+ \link Go::ftSurface ftSurface \endlink. The face represents the abstract idea of a bounded surface, but it also
has a pointer to the geometric representation of this surface. The geometric
-surface is a \link Go::ParamSurface \endlink, it may be a NURBS surface, an elementary surface
+surface is a \link Go::ParamSurface ParamSurface \endlink, it may be a NURBS surface, an elementary surface
or a trimmed version thereof. The face is bounded by one or more loops,
one outer and possibly a number of inner ones. The inner loops represents
-holes in the surface. Then the geometric surface will always be a \link Go::BoundedSurface \endlink. All
+holes in the surface. Then the geometric surface will always be a \link Go::BoundedSurface BoundedSurface \endlink. All
faces have an outer loop which either represents an outer trimming curve in
the case of a BoundedSurface or the surface boundary.
@@ -106,7 +106,7 @@ as a point. A vertex has knowledge about all edges meeting in this point.
\section comp_sec2 CompositeModel
SurfaceModel represents the shell in a boundary represented geometry model,
but it is also the entity that is used to view a surface set as one unity. In
-this context, it inherits the abstract superclass \link Go::CompositeModel \endlink that defines
+this context, it inherits the abstract superclass \link Go::CompositeModel CompositeModel \endlink that defines
an interface for a unity of geometry entities of the same type. All composite
models can
Report how many entities it consist of
@@ -128,12 +128,12 @@ be specified. The resolution is defined from the composite model. This can
either be done setting a resolution for all entities or by a density parameter
that governs the resolution. The composite model tesselation routines return
a vector of shared pointers to a GeneralMesh. The type of meshes used for the
-concrete tesselation results are \link Go::LineStrip \endlink,
- \link Go::RegularMesh \endlink and \link Go::GenericTriMesh \endlink.
+concrete tesselation results are \link Go::LineStrip LineStrip \endlink,
+ \link Go::RegularMesh RegularMesh \endlink and \link Go::GenericTriMeshGenericTriMesh GenericTriMeshGenericTriMesh \endlink.
The control polygon of the composite model or a selected subset of the
model may be tesselated. In that case the output mesh is represented as a
- \link Go::LineCloud \endlink. LineCloud is an entity in gotools-core/geometry.
+ \link Go::LineCloud LineCloud \endlink. LineCloud is an entity in gotools-core/geometry.
\subsection comp_sec2_2 CompositeCurve
A \link Go::CompositeCurve composite curve \endlink
@@ -141,7 +141,7 @@ is an ordered collection of curves. The class expects a set
of curves and will orient them order them in a sequence. The curve set should
preferably be continuous, but also discontinuous set may be represented.
-A composite curve will contain a number of \link Go::ParamCurves \endlink, ordering
+A composite curve will contain a number of \link Go::ParamCurve ParamCurves \endlink, ordering
information and continuity information. The curve sequence will be parameterized as a
unity. Curve indices follow the indices for the curves given as
input to the object. The class has the following type specific functionality:
@@ -237,6 +237,92 @@ size of the model. An upper bound of the tesselation size exists, but a large
model combined with a small density will still lead to a heavy visualization
model.
+\subsection comp_sec2_5 Tolerances
+The constructor of subclasses of \link Go::CompositeModel compositemodel \endlink requires a set of tolerances to be defined. With the exception of approxtol, these tolerances are used to compute adjacency between entities and to check the continuity between adjacent entities.
+
+\subsection comp_sec2_6 Intersection results
+
+Intersections performed in the composite model class either return the intersection results in a format particular to the concrete composite model subclass, or the intersection results are stored in a subclass of \link Go::IntResultsModel IntResultsModel \endlink. In the latter case, intersections can be performed without caring about the composite model type.
+
+IntResultsModel stores the intersection results and the entities involved in the intersection and has the following functionality:
+
+\li Report upon the existence and number of intersection points and intersection curve segments
+\li Tesselate itself
+
+The actual geometry of the intersection results must be fetched from the subclasses
+\link Go::IntResultsSfModel IntResultsSfModel\endlink and \link Go::IntResultsCompCv IntResultsCompCv \endlink. The intersection results classes are very lean, but have the potential to get a rich set of functionality operating on intersection results.
+
+SurfaceModel returns intersection results either as IntResultsSfModel or as
+\link Go::ftCurve ftCurve \endlink and a vector of \link Go::ftPoints ftPoints \endlink. It is also possible to fetch intersection results from IntResultSfModel as ftCurve and ftPoint.
+
+An ftCurve is composed of a number of ftCurveSegments. An ftCurveSegment represents a piece of an intersection curve. The segment is represented by a spatial curve and a curve in the parameter domain of the parametric entities involved in the intersection, which will be one or two. Thus, the curve segments distinguish between the individual surfaces in a surface set while ftCurve itself does not. ftCurve keeps track of the continuity between the segments it is composed of. An ftCurve is able to tesselate itself.
+
+An ftPoint relates to one face, i.e., an \link Go::ftSurface ftSurface\endlink,
+and has a geometric representation and a parameter domain representation. Each intersection point, for instance in an intersection between a surface model and a line, is represented as an ftPoint. The application has access to the position of this point, to the face with which it is associated and the parameter values in this face.
+
+A composite curve represents its intersection results as an instance of
+\link Go::IntResultsCompCv IntResultsCompCv\endlink. Intersection points, which are the expected result in this case, are represented as \link Go::PointOnCurve PointOnCurve\endlink. Intersection curve segments are represented as pairs of PointOnCurves. The two points limit the extension of the intersection curve segment. The class
+PointOnCurve lies in the gotools-core/geometry submodule and holds a parametric curve, a parameter value and the geometric representation of the point. This content is accessible from the public user interface.
+
+\subsection comp_sec2_7 The topological face
+The topological face (\link Go::ftSurface ftSurface\endlink)
+has access to the geometric representation of this face and information about neighbouring faces. In addition, it has knowledge about the solid (\link Go::Body Body\endlink) it belongs to, if any.
+
+The geometric surface is of type ParamSurface and described in the documentation of the gotools-core/geometry submodule.
+
+The face is limited by a number of \link Go::Loop Loops\endlink. The geometric surface corresponding to a face corresponds to the trimmed face, so the information present in the boundary loops of the face does also exist in the surface description.
+
+ftSurface has a rich set of functionality of different types:
+
+ - Access functionality
+ - Fetch the corresponding surface
+ - Fetch boundary loops
+ - Fetch edges belonging to the boundary loops
+ - Fetch neighbouring faces
+ - Fetch all vertices or subsets of vertices
+ - Fetch the body owning this face
+ - Fetch all bodies meeting in this face, maximum 2
+ - Fetch the coincident face in a volume model
+ .
+ - Quality checking
+ - Check for discontinuities in the surface
+ - Check the distance between a face and corresponding edges and vertices
+ - Check the orientation of loops belonging to the face
+ - Check if the face has a narrow region
+ - Check for acute angles in the boundary loops
+ .
+ - Functionality related to an isogeometric model
+ - Check if the corresponding surface is a spline
+ - Check if this face and the neighbouring face have corresponding spline spaces
+ - Ensure that this face and the neighbouring face have corresponding spline spaces
+ - Check if this face and the neighbouring face satisfy a corner-to-corner condition
+ - Ensure that this face and the neighbouring face satisfy a corner-to-corner condition
+ - Fetch adjacency information between this face and a neighbouring face
+ - Fetch information about boundaries where the face has no neighbouring face
+ - Fetch information about coefficient enumerations for spline surface belonging to adjacent faces and free boundaries
+ .
+ - Other queries
+ - Evaluations
+ - Closest point computations
+ - Perform smoothing on the current face
+ - Compute bounding box
+
+\subsection comp_sec2_8 The topological edge
+The topological edge is implemented in the class \link Go::ftEdge ftEdge\endlink
+and it is a half-edge. Thus, it contains information related to one face only. However, it has access to the corresponding half-edge when the edge represents a boundary between two adjacent faces. The topological edge has a geometric representation as a ParamCurve. The edge may represent a restriction of the curve. This restriction is implemented using limiting parameters in the parameter interval of the curve.
+
+The main functionality is:
+
+\li Fetch the curve representing the geometry description of the edge
+\li Fetch the parameters limiting the edge compared to the corresponding curve
+\li Fetch the face to which the edge belongs
+\li Given an edge parameter, compute the corresponding face parameter
+\li Access to geometry information like bounding box, results of evaluation, closest point computations and an estimate of the curve length
+\li Information about the vertices limiting the edge, i.e., access to vertices and the edge parameter corresponding to a vertex
+\li Access to the radial edge if this entity exist. A radial edge is defined in volume model and the entity is described in the [[documentation of the trivariatemodel module|Module TrivariateModel]].
+\li Get all surfaces meeting in this edge, with a maximum of two
+
+
\section comp_sec3 Reverse engineering
The aim is to go from a triangulated point cloud to a boundary represented
CAD model. See \link reverseengineering_doc the reverse engineering page\endlink
diff --git a/compositemodel/include/GoTools/compositemodel/streamable_g22_doxymain.h b/compositemodel/include/GoTools/compositemodel/streamable_g22_doxymain.h
new file mode 100644
index 00000000..a7fa865a
--- /dev/null
+++ b/compositemodel/include/GoTools/compositemodel/streamable_g22_doxymain.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#ifndef _STREAMABLE_G22_DOXYMAIN_H
+#define _STREAMABLE_G22_DOXYMAIN_H
+
+/**
+\page streamable_g22_doc The g22-format, GoTools file format for surface and volume models.
+
+The g22-format is xml-based and extends the
+link Go::streamable_doxygen g2-format \endlink with
+tolerances and topological entities. The storage for the geometry entities
+follows the g2 format.
+
+Surface models are handled by \link Go::CompositeModelFileHandler.C
+CompositeModelFileHandler \endlink and volume models be
+\link Go::VolumeModelFileHandler.C VolumeModelFileHandler\endlink.
+
+
+*/
+#endif
diff --git a/gotools-core/Doxyfile b/gotools-core/Doxyfile
index aef39af9..7a5616ce 100644
--- a/gotools-core/Doxyfile
+++ b/gotools-core/Doxyfile
@@ -1553,3 +1553,8 @@ GENERATE_LEGEND = YES
# the various graphs.
DOT_CLEANUP = YES
+
+EXTRA_PACKAGES = mathtools amsmath
+USE_MATHJAX = YES
+MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_HTMLorMML
+#../../../../programs/node_modules/mathjax
diff --git a/gotools-core/include/GoTools/geometry/streamable_doxymain.h b/gotools-core/include/GoTools/geometry/streamable_doxymain.h
index 1795bd0d..bc12057c 100644
--- a/gotools-core/include/GoTools/geometry/streamable_doxymain.h
+++ b/gotools-core/include/GoTools/geometry/streamable_doxymain.h
@@ -46,6 +46,7 @@
The following geometry entities have read and write functionality using the
g2-format:
+\subsection Curves Curves
\arg \c \em SplineCurve, entity code = 100,
\arg \c \em CurveOnSurface, entity code = 110,
\arg \c \em Line, entity code = 120,
@@ -54,6 +55,7 @@ g2-format:
\arg \c \em BoundedCurve, entity code = 150,
\arg \c \em Hyperbola, entity code = 160,
\arg \c \em Parabola, entity code = 170,
+\subsection Surfaces Surfaces
\arg \c \em SplineSurface, entity code = 200,
\arg \c \em BoundedSurface, entity code = 210,
\arg \c \em SurfaceOnVolume, entity code = 211,
@@ -69,6 +71,7 @@ g2-format:
\arg \c \em Disc, entity code = 292,
\arg \c \em LRSplineSurface, entity code = 293,
\arg \c \em TSplineSurface, entity code = 294,
+\subsection Misc Discrete and miscellaneous
\arg \c \em Go3dsObject, entity code = 300,
\arg \c \em GoHeTriang, entity code = 310,
\arg \c \em GoSdTriang, entity code = 320,
@@ -80,6 +83,7 @@ g2-format:
\arg \c \em LineCloud, entity code = 410,
\arg \c \em GoTriangleSets, entity code = 500,
\arg \c \em RectGrid, entity code = 510,
+\subsection Volumes Volumes
\arg \c \em SplineVolume, entity code = 700,
\arg \c \em Parallelepiped, entity code = 720,
\arg \c \em SphereVolume, entity code = 721,
@@ -94,7 +98,7 @@ does not support pointers. Thus, duplication of information may occur.
\section g2_sec_objectHeader The object header
All geometry entities are preceeded by the object
-\beginlink \link Go::ObjectHeader ObjectHeader\endlink in a stream.
+\link Go::ObjectHeader ObjectHeader\endlink in a stream.
ObjectHeader contains information about the class type of the
geometry object to folow and the version number of the file format.
The format of the header
@@ -104,11 +108,17 @@ is as follows:
\arg \c minor version . Always 0.
\arg \c auxillerary data . 0 if the default colour is chosen, 4 if the
rgb-colour code is chosen. In the latter case, the entity is followed by 4 integer
-digits between 0 and 255 giving the colours red, green and blue and the xxx.
+digits between 0 and 255 giving the colours red, green and blue and the
+alpha (blending) value.
+
+An example of an object header for a circle with default colour:
+\verbatim
+130 1 0 0
+\endverbatim
\section g2_sec_splineCurve SplineCurve
The entity code 100 is given in the header.
-\beginlink \link Go::SplineCurve SplineCurve \endlink
+\link Go::SplineCurve SplineCurve \endlink
continues with the following information
- dimension of geometry space, whether or not the curve is rational: 1=rational,
0=non-rational
@@ -139,7 +149,7 @@ A linear non-rational spline curve with no inner knots in the parameter interval
\endverbatim
\section g2_sec_curveOnSurface CurveOnSurface
-The entity enumeration of a \beginlink \link Go::CurveOnSurface CurveOnSurface \endlink
+The entity enumeration of a \link Go::CurveOnSurface CurveOnSurface \endlink
is 110. The remaining file format is as follows:
- whether or not the parameter space curve is the master information (1=parameter
curve is master, 0=space curve is master), the entity type of the parameter curve
@@ -154,12 +164,12 @@ regarding constant parameter information for the curve on surface is not covered
by the file format.
Note that the CurveOnSurface entity does also contain information about a
-\beginlink \link Go::ParamSurface ParamSurface\endlink. Thus, the g2-representation
+\link Go::ParamSurface ParamSurface\endlink. Thus, the g2-representation
of a CurveOnSurface is not stand alone. It needs to be combined with a \ref g2_sec_boundedSurface. That section gives an example of how the CurveOnSurface entity is used
in this context.
\section g2_sec_line Line
-The \beginlink \link Go::Line line \endlink is given by the following
+The \link Go::Line line \endlink is given by the following
information:
- the dimension of the geometry space
- a point on the line
@@ -170,7 +180,7 @@ The \beginlink \link Go::Line line \endlink is given by the following
The entity enumeration for a line is 120.
\section g2_sec_circle Circle
-The \beginlink \link Go::Circle circle\endlink is given by:
+The \link Go::Circle circle\endlink is given by:
- the dimension of the geometry space
- the radius of the circle
- the centre of the circle
@@ -194,7 +204,7 @@ v_x v_y v_z
\endverbatim
\section g2_sec_ellipse Ellipse
-The \beginlink \link Go::Ellipse ellipse \endlink is given by:
+The \link Go::Ellipse ellipse \endlink is given by:
- the dimension of the geometry space
- the major radius of the ellipse
- the minor radius of the ellipse
@@ -206,7 +216,7 @@ start point of the default parametrization
The entity enumeration for an ellipse is 130.
\section g2_sec_boundedCurve Bounded Curve
-A \beginlink \link Go::BoundedCurve bounded curve\endlink are expected to be bounded
+A \link Go::BoundedCurve bounded curve\endlink are expected to be bounded
both parametrically and geometrically. Thus, a parameter on whether or not
the limitation in the
parameter space or in geometry space is preffered is included in the format. The
@@ -237,8 +247,27 @@ is the master regarding the bounding points is expressed as
120 is the entity number for a line and the dimension of the geometry
space is 3.
+\section g2_sec_hyperbola Hyperbola
+The \link Go::Hyperbola Hyperbola \endlink is represented
+parametrically with sinh and cosh and has the storage format:
+\li Spatial dimension
+\li The factor corresponding to cosh
+\li The factor corresponding to sinh
+\li Centre
+\li Plane normal (only relevant for spatial dimension equal to three)
+\li First semi axis
+
+\section g2_sec_parabola Parabola
+The \link Go::Parabola Parabola \endlink has the storage format:
+\li Spatial dimension
+\li Focal distance
+\li Centre
+\li Plane normal (only relevant for spatial dimension equal to three)
+\li First semi axis
+
+
\section g2_sec_splineSurface SplineSurface
-The entity enumeration for a \beginlink \link Go::SplineSurface spline surface \endlink
+The entity enumeration for a \link Go::SplineSurface spline surface \endlink
is 200. The body of a spline surface is as follows:
- dimension of geometry space, whether or not the surface is rational: 1=rational,
0=non-rational
@@ -251,8 +280,9 @@ the polynomial order in this direction (i.e. degree+1)
- the knot vector in the second parameter direction
- the surface coefficients
-The surface coefficients are given continuously and the 1. parameter direction
-runs fastest. The sequence is
+The surface coefficients are provided in a sequence: row-wise, starting from
+the coefficient corresponding to the lower left corner of the parameter domain
+and ending with the coefficient corresponding to the upper right corner.
\f$ (x_{(1,1)}, y_{(1,1)}, z_{(1,1)}), (x_{(2,1)}, y_{(2,1)}, z_{(2,1)}),
\ldots, (x_{(n,1)}, y_{(n,1)}, z_{(n,1)}), (x_{(1,2)}, y_{(1,2)}, z_{(1,2)}),
\ldots, (x_{(n,2)}, y_{(n,2)}, z_{(n,2)}), \ldots, (x_{(1,m)}, y_{(1,m)}, z_{(1,m)}),
@@ -277,7 +307,7 @@ A simple non-rational, bilinear surface with no inner knots is represented as:
\endverbatim
\section g2_sec_boundedSurface BoundedSurface
-\beginlink \link Go::BoundedSurface BoundedSurface\endlink has entity enumeration 210.
+\link Go::BoundedSurface BoundedSurface\endlink has entity enumeration 210.
A bounded surface consists of an underlying rectangular parametric surface and one
or more trimming loops. The file format body consists of the following information:
@@ -290,7 +320,7 @@ or more trimming loops. The file format body consists of the following informati
- The curves in the trimming loop, one by one
-The trimming curves are of type \beginlink \link Go::ParamCurve ParamCurve\endlink,
+The trimming curves are of type \link Go::ParamCurve ParamCurve\endlink,
but it most cases they will be represented as \ref g2_sec_curveOnSurface.
The following example illustrates the format a bounded surface. The underlying
@@ -345,9 +375,25 @@ In this case the two first trimming curves are linear spline curves while
the last one is of order 3 (degree 2) and has one inner knot. All the curves
are non-rational.
+\section g2_sec_surfaceOnVolume SurfaceOnVolume
+Similar to CurveOnSurface is \link Go::SurfaceOnVolume SurfaceOnVolume \endlink
+not a stand alone entity. The format is similar to CurveOnSurface:
+a flag on whether the parametric or spatial representation of the surface
+is master is followed by the type of the parametric and spatial surface and
+the corresponding surface description. Only the preferred surface is
+required to exist. Finally, flags for constant parameter surfaces and
+boundary surfaces are given as well as the orientation of this surface
+with respect to the corresponding volume.
+
+\section g2_sec_CompositeSurface CompositeSurface
+A \link Go::CompositeSurface CompositeSurface \endlink consists of a
+collection of spline surfaces, and the file format contains one large
+SplineSurface followed by a sequence of spline surfaces from which the
+first is composed.
\section g2_sec_plane Plane
-A \beginlink \link Go::Plane Plane\endlink has entity enumeration 250 and the body
+
+A \link Go::Plane Plane\endlink has entity enumeration 250 and the body
related to the g2-formation contains:
- The dimension of the geometry space
- A point in the plane
@@ -374,7 +420,7 @@ the format:
\section g2_sec_cylinder Cylinder
-A \beginlink \link Go::Cylinder Cylinder\endlink has entity enumeration 260 and the body
+A \link Go::Cylinder Cylinder\endlink has entity enumeration 260 and the body
related to the g2-formation contains:
- The dimension of the geometry space
- The cylinder radius
@@ -389,7 +435,7 @@ start point of the default parametrization
directions are swapped
\section g2_sec_sphere Sphere
-A \beginlink \link Go::Sphere Sphere\endlink has entity enumeration 270 and the body
+A \link Go::Sphere Sphere\endlink has entity enumeration 270 and the body
related to the g2-formation contains:
- The dimension of the geometry space
- The radius of the sphere
@@ -417,7 +463,7 @@ represented in the g2-format is
\endverbatim
\section g2_sec_cone Cone
-A \beginlink \link Go::Cone Cone\endlink has entity enumeration 280 and the body
+A \link Go::Cone Cone\endlink has entity enumeration 280 and the body
related to the g2-formation contains:
- The dimension of the geometry space
- The cone radius at the position of the point on the cone axis
@@ -433,7 +479,7 @@ start point of the default parametrization
directions are swapped
\section g2_sec_torus Torus
-A \beginlink \link Go::Torus Torus\endlink has entity enumeration 290 and the body
+A \link Go::Torus Torus\endlink has entity enumeration 290 and the body
related to the g2-formation contains:
- The dimension of the geometry space
- The major radius of the torus
@@ -451,7 +497,7 @@ cases.
directions are swapped
\section g2_sec_surfaceOfRevolution SurfaceOfRevolution
-A \beginlink \link Go::SurfaceOfRevolution SurfaceOfRevolution\endlink has entity
+A \link Go::SurfaceOfRevolution SurfaceOfRevolution\endlink has entity
enumeration 291 and the body contains:
- The dimension of the geometry space
- A point of the axis of revolution
@@ -473,7 +519,7 @@ A surface of revolution is
\endverbatim
\section g2_sec_disc Disc
-The entity number for \beginlink \link Go::Disc Disc\endlink is 292. The g2 body
+The entity number for \link Go::Disc Disc\endlink is 292. The g2 body
contains:
- The dimension of the geometry space
- The centre of the disc
@@ -486,8 +532,232 @@ have degenerate corners (=0)
- The angles giving the four degeneracy points at the boundary. Not used if the
flag for centre degeneracy is false.
+\section g2_sec_lrsplineSurface LRSplineSurface
+Below is an example of an \link Go::LRSplineSurface LR spline surface \endlink with three inner knot lines traversing
+the entire parameter domain in the first parameter direction, and two inner
+knot lines traversing the entire domain and two knot lines traversing only
+parts of the domain in the second parameter direction. The surfaces is
+biquadratic, non-rational and embedded in 3D space.
+\verbatim
+293 1 0 0
+0 1e-06
+ 5 0 1 2 3 4
+6 0 0.5 1 1.5 2 3
+5 1 0 3
+1 0 1
+1 0 1
+1 0 1
+1 0 3
+
+6 1 0 3
+2 0 1 3 0
+1 0 1
+2 0 1 3 0
+1 0 1
+1 0 3
+
+ 36
+ 3 0
+ 0 0 0 1 1
+ 4 0 0 0 1
+4 0 0 0 1
+
+ 3 0
+ 1 0 0 1 1
+ 4 0 0 1 2
+4 0 0 0 1
+
+ 3 0
+ 2 0 0 1 1
+ 4 0 1 2 3
+4 0 0 0 1
+
+ 3 0
+ 3 0 0 1 1
+ 4 1 2 3 4
+4 0 0 0 2
+
+ 3 0
+ 4 0 0 1 1
+ 4 2 3 4 4
+4 0 0 0 2
+
+ 3 0
+ 5 0 0 1 1
+ 4 3 4 4 4
+4 0 0 0 2
+
+ 3 0
+ 0 0.5 0 1 1
+ 4 0 0 0 1
+4 0 0 1 2
+
+ 3 0
+ 1 0.5 0 1 1
+ 4 0 0 1 2
+4 0 0 1 2
+
+ 3 0
+ 2 0.5 0 1 1
+ 4 0 1 2 3
+4 0 0 1 2
+
+ 3 0
+ 3 1 0 1 1
+ 4 1 2 3 4
+4 0 0 2 4
+
+ 3 0
+ 4 1 0 1 1
+ 4 2 3 4 4
+4 0 0 2 4
+
+ 3 0
+ 5 1 0 1 1
+ 4 3 4 4 4
+4 0 0 2 4
+
+ 3 0
+ 0 1.25 0 1 1
+ 4 0 0 0 1
+4 0 1 2 3
+
+ 3 0
+ 1 1.25 0 1 1
+ 4 0 0 1 2
+4 0 1 2 3
+
+ 3 0
+ 2 1.25 0 1 1
+ 4 0 1 2 3
+4 0 1 2 3
+
+ 3 0
+ 3 2 2 1 1
+ 4 1 2 3 4
+4 0 2 4 5
+
+ 3 0
+ 4 2 2 1 1
+ 4 2 3 4 4
+4 0 2 4 5
+
+ 3 0
+ 5 2 0 1 1
+ 4 3 4 4 4
+4 0 2 4 5
+
+ 3 0
+ 0 1.75 0 1 1
+ 4 0 0 0 1
+4 1 2 3 4
+
+ 3 0
+ 1 1.75 0 1 1
+ 4 0 0 1 2
+4 1 2 3 4
+
+ 3 0
+ 2 1.75 0 1 1
+ 4 0 1 2 3
+4 1 2 3 4
+
+ 3 0
+ 0 2.25 0 1 1
+ 4 0 0 0 1
+4 2 3 4 5
+
+ 3 0
+ 1 2.25 0 1 1
+ 4 0 0 1 2
+4 2 3 4 5
+
+ 3 0
+ 2 2.25 0.75 1 1
+ 4 0 1 2 3
+4 2 3 4 5
+
+ 3 0
+ 3 3 3 1 1
+ 4 1 2 3 4
+4 2 4 5 5
+
+ 3 0
+ 4 3 0 1 1
+ 4 2 3 4 4
+4 2 4 5 5
+
+ 3 0
+ 5 3 0 1 1
+ 4 3 4 4 4
+4 2 4 5 5
+
+ 3 0
+ 0 3 0 1 1
+ 4 0 0 0 1
+4 3 4 5 5
+
+ 3 0
+ 1 3 0 1 1
+ 4 0 0 1 2
+4 3 4 5 5
+
+ 3 0
+ 2 3 3 1 1
+ 4 0 1 2 3
+4 3 4 5 5
+
+ 3 0
+ 0 4 0 1 1
+ 4 0 0 0 1
+4 4 5 5 5
+
+ 3 0
+ 1 4 0 1 1
+ 4 0 0 1 2
+4 4 5 5 5
+
+ 3 0
+ 2 4 1 1 1
+ 4 0 1 2 3
+4 4 5 5 5
+
+ 3 0
+ 3 4 1 1 1
+ 4 1 2 3 4
+4 4 5 5 5
+
+ 3 0
+ 4 4 0 1 1
+ 4 2 3 4 4
+4 4 5 5 5
+
+ 3 0
+ 5 4 0 1 1
+ 4 3 4 4 4
+4 4 5 5 5
+\endverbatim
+
+The first line after the header contains a flag for whether or not the surface
+is rational followed by a tolerance telling the condition for two knots being regarded as equal.
+The mesh follows next, the two first lines store the knots in the two parameter directions: The number
+of knots followed by their values.
+For each knot an encoding of the knot multiplicity is given, zero multiplicity
+means that the knot is not active in the specified interval. When the
+multiplicity changes, the index of the knot in the opposite parameter
+direction where the change takes place is given together with the new
+multiplicity.
+
+After the mesh, the coefficients follow. The number of coefficients
+are given, then the coefficients follow one by one. First the dimension of the
+geometry space is given along with the flag for a rational surface. The
+coefficient times the scaling value is given followed by the scaling value and
+the rational weight. If the surface is non-rational this weight is equal to one.
+Finally, indices into the knot vector for the active knots of the B-spline
+corresponding to the coefficient is given for the two parameter directions.
+
\section g2_sec_pointCloud PointCloud
-A \beginlink \link Go::PointCloud PointCloud\endlink has enumeration 400. It has the
+A \link Go::PointCloud PointCloud\endlink has enumeration 400. It has the
following body:
- Number of points
- The coordinates of each point. The points are given one by one.
@@ -503,7 +773,7 @@ a point cloud with 3 points is
\endverbatim
\section g2_sec_lineCloud LineCloud
-A \beginlink \link Go::LineCloud LineCloud\endlink has enumeration 410. It has the
+A \link Go::LineCloud LineCloud\endlink has enumeration 410. It has the
following body:
- Number of line segments
- The coordinates of the endpoints of each line segments.
@@ -520,7 +790,7 @@ with 3 lines follow:
\endverbatim
\section g2_sec_splineVolume SplineVolume
-The entity enumeration for a \beginlink \link Go::SplineVolume spline volume \endlink
+The entity enumeration for a \link Go::SplineVolume spline volume \endlink
is 700. The spline volume entity is placed in the module trivariate.
The body of a spline volume is as follows:
- dimension of geometry space, whether or not the volume is rational: 1=rational,
@@ -573,7 +843,7 @@ A simple non-rational, trilinear volume with no inner knots is represented as:
\endverbatim
\section g2_sec_parallelepiped Parallelepiped
-\beginlink \link Go::Parallelepiped Parallelepiped\endlink has enumeration 720 and
+\link Go::Parallelepiped Parallelepiped\endlink has enumeration 720 and
the following g2-format:
- Dimension of geometry space
- Lower right corner
@@ -585,7 +855,7 @@ the following g2-format:
- Length of parallelepiped in the third direction
\section g2_sec_sphereVolume SphereVolume
-\beginlink \link Go::SphereVolume SphereVolume\endlink has enumeration 721 and
+\link Go::SphereVolume SphereVolume\endlink has enumeration 721 and
the following g2-format:
- Dimension of geometry space
- Sphere radius
@@ -596,7 +866,7 @@ representation of the sphere will lie
parametrization
\section g2_sec_cylinderVolume CylinderVolume
-\beginlink \link Go::CylinderVolume CylinderVolume\endlink has enumeration 722 and
+\link Go::CylinderVolume CylinderVolume\endlink has enumeration 722 and
the following g2-format:
- Dimension of geometry space
- Cylinder centre
@@ -617,7 +887,7 @@ have degenerate corners (=0)
flag for centre degeneracy is false.
\section g2_sec_coneVolume ConeVolume
-\beginlink \link Go::ConeVolume ConeVolume\endlink has enumeration 723 and
+\link Go::ConeVolume ConeVolume\endlink has enumeration 723 and
the following g2-format:
- Dimension of geometry space
- Radius of the cone at the centre
@@ -636,7 +906,7 @@ have degenerate corners (=0)
flag for centre degeneracy is false.
\section g2_sec_torusVolume TorusVolume
-\beginlink \link Go::TorusVolume TorusVolume\endlink has enumeration 724 and
+\link Go::TorusVolume TorusVolume\endlink has enumeration 724 and
the following g2-format:
- Dimension of geometry space
- The torus centre
@@ -650,6 +920,29 @@ the following g2-format:
have degenerate corners (=0)
- The angles giving the four degeneracy points at the boundary. Not used if the
flag for centre degeneracy is false.
+
+\section g2_sec_lrsplineVolume LRSplineVolume
+The storage format for an \link Go::LRSplineVolume LR spline volume \endlink broadly follows that of an
+LR spline surface. The main difference is that mesh and the B-splines relate
+to three parameter directions. In addition, the encoding of the mesh
+rectangles, describing the knot multiplicity and which knots are active in
+a domain, differs somewhat.
+
+\section g2_sec_deprecated Deprecated entities
+The following entities are not currently active:
+\li GoHBSplineParamSurface
+\li GoBaryPolSurface
+\li TSplineSurface
+\li Go3dsObject
+\li GoHeTriang
+\li GoSdTriang
+\li GoQuadMesh
+\li GoHybridMesh
+\li ParamTriang
+\li GoVrmlGeometry
+\li GoTriangleSets
+\li RectGrid
+
*/
#endif // _STREAMABLE_DOXYMAIN_H
diff --git a/gotools-data b/gotools-data
index 50cf659d..2f08c26b 160000
--- a/gotools-data
+++ b/gotools-data
@@ -1 +1 @@
-Subproject commit 50cf659dc358cc77ad8a02456a6d67f90c7dc7cf
+Subproject commit 2f08c26b4999fb35b06079764a5ad4bdf9558dac
diff --git a/igeslib/include/GoTools/igeslib/example_igeslib_doxymain.h b/igeslib/include/GoTools/igeslib/example_igeslib_doxymain.h
new file mode 100644
index 00000000..38e075e2
--- /dev/null
+++ b/igeslib/include/GoTools/igeslib/example_igeslib_doxymain.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+#ifndef _EXAMPLES_IGESLIB_DOXYMAIN_H
+#define _EXAMPLES_IGESLIB_DOXYMAIN_H
+/**
+\page examples_igeslib Example program related to igeslib
+
+intersect_with_plane.C
+
+This program shows how to fetch geometry entities from the IGES converter,
+compute the
+bounding box of a surface and compute the intersection between a surface and
+a plane using functionality in the namespace BoundedUtils.
+
+\example intersect_with_plane intersect_with_plane.C
+\verbatim
+\endverbatim
+
+This program shows how to fetch geometry entities from the IGES converter,
+compute the
+bounding box of a surface and compute the intersection between a surface and
+a plane using functionality in the namespace BoundedUtils.
+
+*/
+#endif
diff --git a/igeslib/include/GoTools/igeslib/examples_igeslib_doxygen.h b/igeslib/include/GoTools/igeslib/examples_igeslib_doxygen.h
index 6c0394d7..a2c2c35d 100644
--- a/igeslib/include/GoTools/igeslib/examples_igeslib_doxygen.h
+++ b/igeslib/include/GoTools/igeslib/examples_igeslib_doxygen.h
@@ -41,9 +41,21 @@
#define _EXAMPLES_IGESLIB_DOXYMAIN_H
/**
+\page examples_igeslib Example program related to igeslib
+
+An example related to interacting with the IGES file format.
+
+intersect_with_plane.C
+
+This program demonstrates how to read from and write to IGES files.
+It shows how to fetch geometry entities from the IGES converter, compute the
+bounding box of a surface and compute the intersection between a surface and
+a plane using functionality in the namespace BoundedUtils.
+
\example intersect_with_plane intersect_with_plane.C
\verbatim
\endverbatim
+
This program demonstrates how to read from and write to IGES files.
It shows how to fetch geometry entities from the IGES converter, compute the
bounding box of a surface and compute the intersection between a surface and
diff --git a/igeslib/include/GoTools/igeslib/igeslib_doxymain.h b/igeslib/include/GoTools/igeslib/igeslib_doxymain.h
index 2408fe44..569f957d 100644
--- a/igeslib/include/GoTools/igeslib/igeslib_doxymain.h
+++ b/igeslib/include/GoTools/igeslib/igeslib_doxymain.h
@@ -50,7 +50,8 @@ The \link Go::IGESconverter IGES converter \endlink
read an IGES file and represents its entites in the
internal data structure of GoTools. It can also write a model represented in
GoTools to an IGES file or convert between an IGES file and the
-\link streamable_doc internal file format \endlink of GoTools.
+\link streamable_doc internal file format \endlink of GoTools. An example
+program is found in \link examples_igeslib examples_igeslib\endlink.
GoTools core represent only geometric entities. Thus, IGES entities like annotation,
structure, property, associativity, view, drawing
diff --git a/lrsplines2D/CMakeLists.txt b/lrsplines2D/CMakeLists.txt
index fcb42142..6a450fbe 100644
--- a/lrsplines2D/CMakeLists.txt
+++ b/lrsplines2D/CMakeLists.txt
@@ -95,6 +95,9 @@ ENDIF()
# Create a tmp directory.
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tmp)
+# Create the output data directory for the examples.
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/data)
+
# Copy data
if (GoTools_COPY_DATA)
FILE(COPY ${CMAKE_CURRENT_SOURCE_DIR}/../gotools-data/lrsplines2D/data DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/lrsplines2D/Doxyfile b/lrsplines2D/Doxyfile
index 914eab25..4a846a31 100644
--- a/lrsplines2D/Doxyfile
+++ b/lrsplines2D/Doxyfile
@@ -25,7 +25,7 @@ DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
-PROJECT_NAME = "GoTools Trivariate"
+PROJECT_NAME = "GoTools LRspline2D"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
@@ -592,7 +592,8 @@ EXAMPLE_RECURSIVE = NO
# directories that contain image that are included in the documentation (see
# the \image command).
-IMAGE_PATH = doc/images
+IMAGE_PATH = ../ttl/doc/images \
+ doc/images
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -872,7 +873,7 @@ MAKEINDEX_CMD_NAME = makeindex
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
-COMPACT_LATEX = NO
+COMPACT_LATEX = YES
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
@@ -1203,7 +1204,7 @@ MSCGEN_PATH =
# inheritance and usage relations if the target is undocumented
# or is not a class.
-HIDE_UNDOC_RELATIONS = NO
+HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
@@ -1262,7 +1263,7 @@ INCLUDED_BY_GRAPH = YES
# the time of a run. So in most cases it will be better to enable call graphs
# for selected functions only using the \callgraph command.
-CALL_GRAPH = YES
+CALL_GRAPH = NO
# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
# doxygen will generate a caller dependency graph for every global function
@@ -1270,7 +1271,7 @@ CALL_GRAPH = YES
# the time of a run. So in most cases it will be better to enable caller
# graphs for selected functions only using the \callergraph command.
-CALLER_GRAPH = YES
+CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
@@ -1334,7 +1335,7 @@ DOT_TRANSPARENT = NO
# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.
-DOT_MULTI_TARGETS = YES
+DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
@@ -1348,6 +1349,11 @@ GENERATE_LEGEND = YES
DOT_CLEANUP = YES
+EXTRA_PACKAGES = mathtools amsmath
+USE_MATHJAX = YES
+MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_HTMLorMML
+#../../../../programs/node_modules/mathjax
+
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
diff --git a/lrsplines2D/app/PointCloud2LR.C b/lrsplines2D/app/PointCloud2LR.C
index 48327701..f7622f90 100644
--- a/lrsplines2D/app/PointCloud2LR.C
+++ b/lrsplines2D/app/PointCloud2LR.C
@@ -63,6 +63,7 @@
//#define DEBUG
//#define DEBUG_EL
//#define DEBUG2
+#define DEBUG_PAR
using namespace Go;
@@ -71,8 +72,8 @@ using std::string;
void print_help_text()
{
- std::cout << "Purpose: Approximate a point cloud by an LR B-spline surface. \n";
- std::cout << "Mandatory parameters: input point cloud (.txt, .xyz or .g2), output surface (.g2), tolerance, number of iterations. \n";
+ std::cout << "Purpose: Approximate a point cloud by an LR B-spline surface. \n \n";
+ std::cout << "Mandatory parameters: input point cloud (.txt, .xyz or .g2), output surface (.g2), tolerance, number of iterations. \n \n";
std::cout << "An adaptive approximation procedure is applied which for the";
std::cout << " specified number of iterations: \n";
std::cout << " - Approximates the points with a surface in the current spline space \n";
@@ -82,7 +83,7 @@ void print_help_text()
std::cout << " specified number of iterations is exceeded.";
std::cout << "The number of iterations is recommended to lie in the interval [4:7]. \n";
std::cout << "The points are expected to be given as x, y, z and be parameterized on x and y, but 3D parameterized points are accepted.\n";
- std::cout << "Then the points are given as u, v, x, y, z. \n";
+ std::cout << "Then the points are given as u, v, x, y, z. \n \n";
std::cout << "Optional input parameters: \n";
std::cout << "-par <0/1> : True (1) if parameterized points are given. Default value is 0.\n";
std::cout << "-dist : Write distance field to file (x, y, z, distance) \n";
@@ -243,7 +244,7 @@ int main(int argc, char *argv[])
char *AIC_file = 0;
int initncoef = 10;
- int distribute_ncoef = 0;
+ int distribute_ncoef = 1;
int refcat1=1, refcat2=0, threshold1=2, threshold2=-1, alter=1;
double swap = -100.0;
@@ -614,6 +615,18 @@ int main(int argc, char *argv[])
else
FileUtils::readTxtPointFile(pointsin, del, data, nmb_pts, extent);
+#ifdef DEBUG_PAR
+ if (del == 5)
+ {
+ std::ofstream ofg("geom_pts.g2");
+ ofg << "400 1 0 0" << std::endl;
+ ofg << data.size()/del << std::endl;
+ for (int ki=0; ki<(int)data.size(); ki+=del)
+ ofg << data[ki+2] << " " << data[ki+3] << " " << data[ki+4] << std::endl;
+ }
+
+#endif
+
int nmb_sign = 0;
vector sign_data;
vector sign_extent(2*del);
diff --git a/lrsplines2D/app/isoContours.C b/lrsplines2D/app/isoContours.C
index 8c66f43e..0fd0508e 100644
--- a/lrsplines2D/app/isoContours.C
+++ b/lrsplines2D/app/isoContours.C
@@ -244,13 +244,6 @@ int main(int argc, char* argv[])
threshold_missing,
tol);
- // const auto ssurf = lrsurf.asSplineSurface();
- // const vector curves = SSurfTraceIsocontours(*ssurf,
- // isovals,
- // 1e-5 * span,
- // include_3D,
- // use_sisl_marching);
-
auto t2 = chrono::high_resolution_clock::now();
cout << "Curves found in " << chrono::duration_cast(t2-t1).count() << " milliseconds." << endl;
diff --git a/lrsplines2D/examples/approximateParPointsWithLRSurf.C b/lrsplines2D/examples/approximateParPointsWithLRSurf.C
new file mode 100644
index 00000000..a4b689b4
--- /dev/null
+++ b/lrsplines2D/examples/approximateParPointsWithLRSurf.C
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines2D/LRSplineSurface.h"
+#include "GoTools/lrsplines2D/LRSurfApprox.h"
+#include "GoTools/lrsplines2D/LRApproxApp.h"
+#include "GoTools/geometry/PointCloud.h"
+#include "GoTools/geometry/ObjectHeader.h"
+#include "GoTools/utils/BoundingBox.h"
+#include "GoTools/geometry/FileUtils.h"
+#include "GoTools/lrsplines2D/LRSplinePlotUtils.h"
+#include
+
+using namespace Go;
+using std::vector;
+
+//===========================================================================
+//
+/// Description:
+/// Read point cloud from file. The given point cloud represents a function
+/// with diagonal steep area and a local elevation. Each points is
+/// equipped with a parameter pair.
+/// Set appropriate parameters and approximate the points with an LR surface
+/// in 3D).
+/// The input data set is the parameterized version of the data set
+/// given as input to approximateWithLRFunc.C
+///
+/// The app PointCloud2LR performs the same operations taking a point cloud
+/// as input. Several parameters are also given as input (mandatory and
+/// optional). The optional parameter -par must be set to 1. This choice
+/// requires a parameterized point cloud. Use -h to get an explanation of
+/// all parameters.
+///
+/// Input to the example is read from
+/// gotools/gotools-data/lrsplines2D/examples/data. The path is hardcoded.
+/// Note that the example must be run from a build directory directly
+/// placed under gotools to find the data. With another location, modify
+/// the path.
+/// The resulting surface and corresponding mesh is written to
+/// data/approx_lrsurf.g2 and data/approx_mesh2.eps.
+//
+//===========================================================================
+
+int main(int argc, char *argv[])
+{
+ // Prepare for reading the point file
+ std::string infile("../../gotools-data/lrsplines2D/examples/data/param_pointcloud.txt");
+ std::ifstream pointsin(infile.c_str());
+
+ // Prepare for output
+ std::string outfile1("data/approx_lrsurf.g2");
+ std::string outfile2("data/approx_mesh2.eps");
+ std::ofstream of1(outfile1.c_str());
+ std::ofstream of2(outfile2.c_str());
+
+ // Only txt files are allowed for input. The file contains u-, and
+ // v-parameters and x-, y- and z-values in this sequence. The values
+ // are separated by comma or space
+ // Read point cloud
+ vector data; // Data points (x, y, z)
+ int del = 5; // Number of values given for each data point
+ vector extent(2*del); // Limits for points in all coordinates
+ int nmb_pts = 0;
+ FileUtils::readTxtPointFile(pointsin, del, data, nmb_pts, extent);
+
+ std::cout << "Parameter domain: [" << extent[0] << ", " << extent[1] << "] x [" << extent[2];
+
+ // Move point cloud to origo. This operation stabilizes the approximation
+ // operation given large values for the x- and y- coordinates. This
+ // frequently occurs when dealing with geographic point clouds
+ Point mid(0.5*(extent[2*(del-3)] + extent[2*(del-3)+1]),
+ 0.5*(extent[2*(del-2)] + extent[2*(del-2)+1]), 0.0);
+ for (int ki=0; ki approx(new LRSurfApprox(nmb_coef, degree+1,
+ nmb_coef, degree+1,
+ data, dim,
+ eps, init_mba, close_dist,
+ repar));
+
+ // Apply multilevel B-spline approximation (MBA) from the start
+ approx->setUseMBA(true);
+
+ // Several approaches exists in refinement. Set strategy
+ int refcat = 1; // Full span
+ int alter = 0; // Do not change strategy during approximation
+ int threshold = 0; // Do not limit the collection of new knot line segments
+ // from the ones defined by the choosen strategy
+ double swap = -100.0; // Default value when alter = 0
+ approx->setRefinementStrategy(refcat, alter, threshold, swap,
+ refcat, threshold);
+
+ // Write current approximation accuracy to standard out for each iteration
+ approx->setVerbose(true);
+
+ // Perform approxatimation
+ // Accuracy information to be set by LRSurfApprox
+ double maxdist; // Maximum distance between points and surface.
+ double avdist_high; // Average distance between points and surface for
+ // the point where the distance exceeds to the tolerance.
+ double avdist; // Average distance between points and surface.
+ int nmb_out; // Number of points with a distance larger than the tolerance.
+
+ shared_ptr surf;
+ try {
+ surf = approx->getApproxSurf(maxdist, avdist, avdist_high,
+ nmb_out, num_iter);
+ }
+ catch (...)
+ {
+ std::cout << "ERROR: Surface approximation failed" << std::endl;
+ return 1;
+ }
+
+ // Approximation accuracy
+ std::cout << std::endl;
+ std::cout << "Total number of points: " << nmb_pts << std::endl;
+ std::cout << "Number of elements: " << surf->numElements() << std::endl;
+ std::cout << "Number of coefficients: " << surf->numBasisFunctions() << std::endl;
+ std::cout << "Maximum distance: " << maxdist << std::endl;
+ std::cout << "Average distance: " << avdist << std::endl;
+ std::cout << "Average distance for points outside of the tolerance: " << avdist_high << std::endl;
+ std::cout << "Number of points outside the tolerance: " << nmb_out << std::endl;
+
+
+ // Update parameter domain of surface to fit with the x- and y-coordinates
+ // of the given point cloud
+ // First enquire the parameter domain of the surface
+ double umin = surf->paramMin(XFIXED);
+ double umax = surf->paramMax(XFIXED);
+ double vmin = surf->paramMin(YFIXED);
+ double vmax = surf->paramMax(YFIXED);
+
+ // Translate surface back to original position of the point cloud
+ surf->translate(mid);
+
+ // Write surface to file
+ // The file can be visualized by goview_vol_and_lr
+ // Note that the surface quality is reduced in the steep area. This might
+ // be the result of problems with the parameterization. The surface is highly
+ // refine in the area, but the diagonal configuartion of this feature
+ // contradicts the properties of the spline surface.
+
+ surf->writeStandardHeader(of1);
+ surf->write(of1);
+
+ // Write mesh to file
+ writePostscriptMesh(*surf, of2);
+
+ return 0;
+}
diff --git a/lrsplines2D/examples/approximateWithLRFunc.C b/lrsplines2D/examples/approximateWithLRFunc.C
new file mode 100644
index 00000000..947f4461
--- /dev/null
+++ b/lrsplines2D/examples/approximateWithLRFunc.C
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines2D/LRSplineSurface.h"
+#include "GoTools/lrsplines2D/LRSurfApprox.h"
+#include "GoTools/geometry/PointCloud.h"
+#include "GoTools/geometry/ObjectHeader.h"
+#include "GoTools/utils/BoundingBox.h"
+#include "GoTools/geometry/FileUtils.h"
+#include "GoTools/lrsplines2D/LRSplinePlotUtils.h"
+#include
+
+using namespace Go;
+using std::vector;
+
+//===========================================================================
+//
+/// Description:
+/// Read point cloud from file. The given point cloud represents a function
+/// with diagonal steep area and a local elevation.
+/// Set appropriate parameters and approximate the points with an LR surface
+/// in 1D (function). The point cloud is parameterized on its
+/// x- and y-parameters.
+///
+/// The app PointCloud2LR performs the same operations taking a point cloud
+/// as input. Several parameters are also given as input (mandatory and
+/// optional). Use -h to get an explanation of all parameters.
+///
+/// Input to the example is read from
+/// gotools/gotools-data/lrsplines2D/examples/data. The path is hardcoded.
+/// Note that the example must be run from a build directory directly
+/// placed under gotools to find the data. With another location, modify
+/// the path.
+/// The resulting surface and corresponding mesh is written to
+/// data/approx_lrfunc.g2 and data/approx_mesh.eps. The point cloud in
+/// g2-format (for visualization) is written to data/pointcloud.g2
+//
+//===========================================================================
+
+int main(int argc, char *argv[])
+{
+ // Prepare for reading the point file
+ std::string infile("../../gotools-data/lrsplines2D/examples/data/pointcloud.txt");
+ std::ifstream pointsin(infile.c_str());
+
+ // Prepare for output
+ std::string outfile0("data/pointcloud.g2");
+ std::string outfile1("data/approx_lrfunc.g2");
+ std::string outfile2("data/approx_mesh.eps");
+ std::ofstream of0(outfile0.c_str());
+ std::ofstream of1(outfile1.c_str());
+ std::ofstream of2(outfile2.c_str());
+
+ // Possible types of input files
+ // The g2 file format is described in the documentation. See under
+ // "Related Pages". The txt file contains x-, y- and z-values separated
+ // by comma or space
+ char keys[2][8] = {"g2", "txt"};
+ int ptstype = FileUtils::fileType((char*)infile.c_str(), keys, 6);
+ if (ptstype < 0)
+ {
+ std::cout << "ERROR: File type not recognized" << std::endl;
+ return 1;
+ }
+
+ // Read point cloud
+ vector data; // Data points (x, y, z)
+ int del = 3; // Number of values given for each data point
+ vector extent(2*del); // Limits for points in all coordinates
+ int nmb_pts = 0;
+ if (ptstype == 0)
+ {
+ // Read g2 file
+ ObjectHeader header;
+ PointCloud3D points;
+ try {
+ header.read(pointsin);
+ points.read(pointsin);
+ }
+ catch (...)
+ {
+ std::cout << "ERROR: Not a valid point file" << std::endl;
+ return 1;
+ }
+
+ // Compute point extent from a box containing all points
+ BoundingBox box = points.boundingBox();
+ Point low = box.low();
+ Point high = box.high();
+ nmb_pts = points.numPoints();
+ data.insert(data.end(), points.rawData(), points.rawData()+3*nmb_pts);
+ for (int ki=0; ki<3; ++ki)
+ {
+ extent[2*ki] = low[ki];
+ extent[2*ki+1] = high[ki];
+ }
+ }
+ else
+ FileUtils::readTxtPointFile(pointsin, del, data, nmb_pts, extent);
+
+ std::cout << "Domain in x and y: [" << extent[0] << ", " << extent[1] << "] x [" << extent[2];
+ std::cout << ", " << extent[3] << "]" << std::endl;
+ std::cout << "Height range: " << extent[4] << " - " << extent[5] << std::endl;
+
+ // Write point cloud to g2 file. The point cloud can be visualized in
+ // goview or goview_vol_and_lr
+ PointCloud3D cloud(data.begin(), nmb_pts);
+ cloud.writeStandardHeader(of0);
+ cloud.write(of0);
+
+ // Move point cloud to origo. This operation stabilizes the approximation
+ // operation given large values for the x- and y- coordinates. This
+ // frequently occurs when dealing with geographic point clouds
+ Point mid(0.5*(extent[2*(del-3)] + extent[2*(del-3)+1]),
+ 0.5*(extent[2*(del-2)] + extent[2*(del-2)+1]), 0.0);
+ for (int ki=0; ki approx(new LRSurfApprox(nmb_coef, degree+1,
+ nmb_coef, degree+1,
+ data, dim,
+ eps, init_mba, close_dist,
+ repar));
+
+ int tomba = 2; // Use least square approximation with a smoothing term (LS)
+ // for the first iteration, then switch to multilevel B-spline
+ // approximation (MBA)
+ approx->setSwitchToMBA(tomba);
+
+ // In LS, apply larger smoothing weigth at the surface boundaries
+ approx->setSmoothBoundary(true);
+
+ // Several approaches exists in refinement. Set strategy
+ int refcat = 1; // Full span
+ int alter = 0; // Do not change strategy during approximation
+ int threshold = 0; // Do not limit the collection of new knot line segments
+ // from the ones defined by the choosen strategy
+ double swap = -100.0; // Default value when alter = 0
+ approx->setRefinementStrategy(refcat, alter, threshold, swap,
+ refcat, threshold);
+
+ // Ensure that the approximating surface does not overshoot with relation
+ // to the point heights. This can be a problem with high variation in the
+ // points and a point domain that does not cover the entire surface domain.
+ double zrange = extent[5] - extent[4];
+ double zfac = std::max(eps, 0.005*zrange);
+ approx->addLowerConstraint(extent[4] - zfac);
+ approx->addUpperConstraint(extent[5] + zfac);
+ approx->setLocalConstraint(zfac);
+
+ // Write current approximation accuracy to standard out for each iteration
+ approx->setVerbose(true);
+
+ // Perform approxatimation
+ // Accuracy information to be set by LRSurfApprox
+ double maxdist; // Maximum distance between points and surface.
+ double avdist_high; // Average distance between points and surface for
+ // the point where the distance exceeds to the tolerance.
+ double avdist; // Average distance between points and surface.
+ int nmb_out; // Number of points with a distance larger than the tolerance.
+
+ shared_ptr surf;
+ try {
+ surf = approx->getApproxSurf(maxdist, avdist, avdist_high,
+ nmb_out, num_iter);
+ }
+ catch (...)
+ {
+ std::cout << "ERROR: Surface approximation failed" << std::endl;
+ return 1;
+ }
+
+ // Approximation accuracy
+ std::cout << std::endl;
+ std::cout << "Total number of points: " << nmb_pts << std::endl;
+ std::cout << "Number of elements: " << surf->numElements() << std::endl;
+ std::cout << "Number of coefficients: " << surf->numBasisFunctions() << std::endl;
+ std::cout << "Maximum distance: " << maxdist << std::endl;
+ std::cout << "Average distance: " << avdist << std::endl;
+ std::cout << "Average distance for points outside of the tolerance: " << avdist_high << std::endl;
+ std::cout << "Number of points outside the tolerance: " << nmb_out << std::endl;
+
+
+ // Update parameter domain of surface to fit with the x- and y-coordinates
+ // of the given point cloud
+ // First enquire the parameter domain of the surface
+ double umin = surf->paramMin(XFIXED);
+ double umax = surf->paramMax(XFIXED);
+ double vmin = surf->paramMin(YFIXED);
+ double vmax = surf->paramMax(YFIXED);
+
+ // Set updated parameter domain
+ surf->setParameterDomain(umin + mid[0], umax + mid[0],
+ vmin + mid[1], vmax + mid[1]);
+
+ // Write surface to file
+ // The file can be visualized by goview_vol_and_lr
+ // Note that the surface quality is reduced in the steep area. A function
+ // typically has problems handing this steepness. The function is highly
+ // refine in the area, but the diagonal configuartion of this feature
+ // contradicts the properties of the spline function.
+ surf->writeStandardHeader(of1);
+ surf->write(of1);
+
+ // Write mesh to file
+ writePostscriptMesh(*surf, of2);
+
+ return 0;
+}
diff --git a/lrsplines2D/examples/comparePointsLRSurf3D.C b/lrsplines2D/examples/comparePointsLRSurf3D.C
new file mode 100644
index 00000000..f0beca72
--- /dev/null
+++ b/lrsplines2D/examples/comparePointsLRSurf3D.C
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines2D/LRSplineSurface.h"
+#include "GoTools/lrsplines2D/LRSurfApprox.h"
+#include "GoTools/lrsplines2D/LRApproxApp.h"
+#include "GoTools/geometry/PointCloud.h"
+#include "GoTools/geometry/ObjectHeader.h"
+#include "GoTools/utils/BoundingBox.h"
+#include "GoTools/geometry/FileUtils.h"
+#include
+
+using namespace Go;
+using std::vector;
+
+//===========================================================================
+//
+/// Description:
+/// Read parameterized point cloud and corresponding surface from file.
+/// Compute distances between points and surface. Prepare for visualization.
+///
+/// The input point cloud is read from
+/// gotools/gotools-data/lrsplines2D/examples/data. The path is hardcoded.
+/// Note that the example must be run from a build directory directly
+/// placed under gotools to find the data. With another location, modify
+/// the path.
+/// The input surface is computed by the example program
+/// approximateParPointsWithLRSurf and expected to be found in data/approx_lrsurf.g2
+/// Average distance and largest negative and positive distance between the
+/// surface and the point cloud is written to standard output.
+/// The points are grouped and assigned a colour according to the distance
+/// to the surface. The grouped points are written do data/coloured_points.g2
+/// and can be visualized in goview_vol_and_lr.
+//
+//===========================================================================
+
+// rgb colours: Largest distance below, distance zero, Largest distance above
+int colors[3][3] = {
+ {0, 255, 0},
+ {255, 255, 255},
+ {255, 0, 0},
+};
+
+
+int main(int argc, char *argv[])
+{
+ // Prepare for reading the point file
+ std::string infile1("../../gotools-data/lrsplines2D/examples/data/param_pointcloud.txt");
+ std::string infile2("data/approx_lrsurf.g2");
+ std::ifstream pointsin(infile1.c_str());
+ std::ifstream sfin(infile2.c_str());
+
+ // Prepare for output
+ std::string outfile("data/coloured_points.g2");
+ std::ofstream of(outfile.c_str());
+
+ // Read point file. The file contains u-, and
+ // v-parameters and x-, y- and z-values in this sequence. The values
+ // are separated by comma or space
+ // Read point cloud
+ vector data; // Data points (x, y, z)
+ int n_val = 5; // Number of values given for each data point
+ vector extent(2*n_val); // Limits for points in all coordinates
+ int nmb_pts = 0;
+ FileUtils::readTxtPointFile(pointsin, n_val, data, nmb_pts, extent);
+
+ std::cout << "Parameter domain: [" << extent[0] << ", " << extent[1] << "] x [" << extent[2] << ", " << extent[3] << "]" << std::endl;;
+
+ // Read header specifying the type of geometry entity
+ ObjectHeader header;
+ try {
+ header.read(sfin);
+ }
+ catch (...)
+ {
+ std::cerr << "File empty or corrupt. Exiting" << std::endl;
+ exit(1);
+ }
+
+ // Read surface
+ // The following assumes that the specified file contains an LR B-spline
+ // surface
+ // Create empty surface
+ shared_ptr surf(new LRSplineSurface());
+ surf->read(sfin);
+ if (!surf.get())
+ {
+ std::cerr << "The file contains no LR B-spline surface" << std::endl;
+ exit(1);
+ }
+
+ // Dimension of geometry space
+ int dim = surf->dimension();
+ if (dim != 3)
+ exit(1); // Unexpected geometry space dimension
+
+ int nmb_points; // Number of points
+ double max_above, max_below, avdist, avdist_abs; // Maximum and average
+ // distance between surface and point cloud
+ vector pointsdist; // For each point: x, y, z, distance to surface
+ bool close_dist = true; // Compute closest point in surface to given
+ // point and examine the distance
+
+ // Compute distances and statistics
+ LRApproxApp::computeDistPointSpline3D(data, surf, max_above, max_below,
+ avdist, avdist_abs, nmb_points,
+ pointsdist, close_dist);
+
+ std::cout << "Number of points: " << nmb_points << std::endl;
+ std::cout << "Maximum distance below the surface: " << max_below << std::endl;
+ std::cout << "Maximum distance above the surface: " << max_above << std::endl;
+ std::cout << "Average distance: " << avdist << std::endl;
+ std::cout << "Average absolute distance: " << avdist_abs << std::endl;
+
+ // Classify points according to distance
+ int nmb_level = 4; // Number of positive distance levels
+ double max_level = std::max(fabs(max_below), max_above);
+ double del = max_level/(double)(nmb_level+1);
+
+ vector limits(2*nmb_level+1); // Limit distance between groups
+ vector > level_points(2*nmb_level+2); // x, y, z-values
+ // for each group
+
+ // Set distance levels
+ limits[nmb_level] = 0;
+ for (int ki=1; ki<=nmb_level; ++ki)
+ {
+ limits[nmb_level-ki] = -ki*del;
+ limits[nmb_level+ki] = ki*del;
+ }
+
+ int nval = 4; // Number of value for each entry in pointsdist
+ for (size_t ki=0; ki.
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines2D/LRSplineSurface.h"
+#include "GoTools/lrsplines2D/LRSplineUtils.h"
+#include "GoTools/lrsplines2D/Element2D.h" // Not really needed as it is
+// included in LRSplineSurface.h
+#include "GoTools/lrsplines2D/LRBSpline2D.h" // As for Element2D
+#include "GoTools/geometry/PointCloud.h"
+#include "GoTools/geometry/ObjectHeader.h"
+#include
+
+using namespace Go;
+using std::vector;
+
+//===========================================================================
+//
+/// Description:
+/// Demonstrates the various evaluation possibilities for an LR B-spline
+/// surface
+///
+/// Input to the example is the surface constructed in the example
+/// program refine_surface.
+/// Evaluation results are written to standard output.
+/// Result of grid evaluation is written to the file data/grid_on_surf.g2.
+//
+//===========================================================================
+
+int main(int argc, char *argv[])
+{
+ // Read LR B-spline surface from file
+ std::string infile("data/lrsurf_fin.g2");
+ std::ifstream input(infile.c_str());
+
+ // Prepare for output
+ std::string outfile("data/grid_on_surf.g2");
+ std::ofstream of(outfile.c_str());
+
+ // Read header specifying the type of geometry entity
+ ObjectHeader header;
+ try {
+ header.read(input);
+ }
+ catch (...)
+ {
+ std::cerr << "File empty or corrupt. Exiting" << std::endl;
+ exit(-1);
+ }
+
+ // The following assumes that the specified file contains an LR B-spline
+ // surface
+ // Create empty surface
+ shared_ptr surf(new LRSplineSurface());
+ surf->read(input);
+ if (!surf.get())
+ {
+ std::cerr << "The file contains no LR B-spline surface" << std::endl;
+ exit(-1);
+ }
+
+ // Dimension of geometry space
+ int dim = surf->dimension();
+
+ // Fetch parameter domain of surface
+ double umin = surf->paramMin(XFIXED); // First parameter direction
+ double umax = surf->paramMax(XFIXED); // First parameter direction
+ double vmin = surf->paramMin(YFIXED); // Second parameter direction
+ double vmax = surf->paramMax(YFIXED); // Second parameter direction
+
+ // Alternative enquiry
+ double umin2 = surf->startparam_u();
+ double umax2 = surf->endparam_u();
+ double vmin2 = surf->startparam_v();
+ double vmax2 = surf->endparam_v();
+
+ // Parameter in which to evaluate
+ double upar = 0.3*umin + 0.7*umax;
+ double vpar = 0.5*(vmin + vmax);
+ std::cout << "Parameter pair in which to evaluate: " << upar << ", " << vpar << std::endl;
+
+ // Evaluate without information of the element in which the parameter is
+ // situated
+ // Only position
+ Point pos1;
+ surf->point(pos1, upar, vpar);
+ std::cout << "Position at specified parameter: " << pos1 << std::endl;
+
+ // Alternative interface
+ Point pos2 = surf->ParamSurface::point(upar, vpar);
+
+ // Position and first derivatives
+ // Given the surface S, the sequence is: S, Su, and Sv. If more derivatives
+ // are requested the sequence continues: Suu, Suv, Svv, Suuu, Suuv, Suvv,
+ // Svvv, ....
+ vector pts1(3);
+ int no_derivs = 1; // Number of derivatives to evaluate, = 0 means only
+ // position
+ bool upar_from_right = false; // True only if the parameter is placed
+ // at the upper boundary in the first parameter direction
+ bool vpar_from_right = false; // True only if the parameter is placed
+ // at the upper boundary in the second parameter direction
+ surf->point(pts1, upar, vpar, no_derivs, upar_from_right, vpar_from_right);
+ std::cout << "Position and first derivatives: " << pts1[0] << std::endl;
+ std::cout << pts1[1] << std::endl;
+ std::cout << pts1[2] << std::endl;
+
+ // If the element corresponding to the parameter pair is known
+ // Identify element. Note that this call may be time consuming if the
+ // surface is large. If more than one evaluation is performed, the
+ // positioning of the previous parameter pair will be used to speed up
+ // the search of the current
+ Element2D *elem = surf->coveringElement(upar, vpar);
+
+ // Only position
+ Point pos3;
+ surf->point(pos3, upar, vpar, elem);
+
+ vector pts2(3);
+ surf->point(pts2, upar, vpar, no_derivs, elem, upar_from_right,
+ vpar_from_right);
+
+
+ // Evaluate surface normal with and without specified element
+ Point norm1, norm2;
+ surf->normal(norm1, upar, vpar);
+ surf->normal(norm2, upar, vpar, elem);
+
+ // Fetch all Bsplines with the specified elemnt in its support
+ const vector Bsplines = elem->getSupport();
+
+ // Evaluate all identified B-splines in the given parameter pair
+ vector Bval;
+ LRSplineUtils::evalAllBSplines(Bsplines, upar, vpar, upar_from_right,
+ vpar_from_right, Bval);
+
+ // Evaluate all identified B-splines in the given parameter pair and
+ // multiply with the corresponding coefficient and scaling factor
+ vector Bvalpos;
+ LRSplineUtils::evalAllBSplinePos(Bsplines, upar, vpar, upar_from_right,
+ vpar_from_right, Bvalpos);
+
+ // Sum up the contribution from all B-splines to compute position
+ Point pos4(dim), pos5(dim);
+ pos4.setValue(0.0); // Initialize
+ pos5.setValue(0.0);
+ for (size_t ki=0; kicoefTimesGamma();
+
+ // Compute contribution to position
+ pos4 += Bval[ki]*scaled_coef;
+ }
+
+ for (size_t ki=0; ki points; // The points are stored consecutive. The geometry
+ // dimension runs fastest, then the first parameter direction and finally
+ // the second direction. That is: p(0,0,x), p(0,0,y), p(0,0,z), p(1,0,x),
+ // ... p(num_u-1, num_v-1, z)
+ // The domain of the grid can be reduced compared to the surface
+ surf->evalGrid(num_u, num_v, umin, umax, vmin, vmax, points, nodata);
+
+ // Write points to file as a PointCloud.
+ // NB! The current surface is a 3D surface, for a function the
+ // points needs to be represented in 3D before defining the
+ // PointCloud.
+ PointCloud3D point_cloud(&points[0], points.size()/3);
+ point_cloud.writeStandardHeader(of);
+ point_cloud.write(of);
+
+}
diff --git a/lrsplines2D/examples/identify_and_resolve_linear_dependence.C b/lrsplines2D/examples/identify_and_resolve_linear_dependence.C
new file mode 100644
index 00000000..3429163a
--- /dev/null
+++ b/lrsplines2D/examples/identify_and_resolve_linear_dependence.C
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines2D/LRSplineSurface.h"
+#include "GoTools/lrsplines2D/LRBSpline2D.h"
+#include "GoTools/lrsplines2D/LinDepUtils.h"
+#include "GoTools/lrsplines2D/DefineRefs2D.h"
+#include "GoTools/lrsplines2D/LRSplinePlotUtils.h"
+#include "GoTools/geometry/SplineSurface.h"
+#include "GoTools/geometry/ObjectHeader.h"
+#include
+
+using namespace Go;
+using std::vector;
+
+//===========================================================================
+//
+/// Description:
+/// Read LR B-spline surface from file.
+/// Identify B-splines involved in a linear dependence situation.
+/// Remove the dependence by applying structured mesh refinement to the
+/// main B-splines in the dependence relation.
+/// The support of the identified B-splines are written to file along
+/// with the LR mesh. The output can be visualized with
+/// gotools/viewlib/app/goview_vol_and_lr or gotools/viewlib/app/goview.
+/// The refined surface and the corresponding mesh is written to file and can
+/// be visualized with gotools/viewlib/app/goview_vol_and_lr as well as the
+/// input surface.
+//
+//===========================================================================
+
+int main(int argc, char *argv[])
+{
+ std::string outfile("data/lin_dep.g2");
+ std::ofstream lin_out(outfile.c_str());
+ std::string outsurf("data/lrsurf_resolved.g2");
+ std::ofstream surf_out(outsurf.c_str());
+ std::string outmesh("data/lrmesh_resolved.g2");
+ std::ofstream mesh_out(outmesh.c_str());
+
+ // Read LR B-spline surface from file
+ std::string infile("../../gotools-data/lrsplines2D/examples/data/lrsurf_lindep.g2");
+ std::ifstream input(infile.c_str());
+
+ // Read header specifying the type of geometry entity
+ ObjectHeader header;
+ try {
+ header.read(input);
+ }
+ catch (...)
+ {
+ std::cerr << "File empty or corrupt. Exiting" << std::endl;
+ exit(-1);
+ }
+
+ // The following assumes that the specified file contains an LR B-spline
+ // surface
+ // Create empty surface
+ shared_ptr surf(new LRSplineSurface());
+ surf->read(input);
+ if (!surf.get())
+ {
+ std::cerr << "The file contains no LR B-spline surface" << std::endl;
+ exit(-1);
+ }
+
+ // Fetch candidates for a linear dependence relationship
+ int deplin_lim = 8; // Minimum number of B-splines involved
+ vector funs = LinDepUtils::fetchUnpeelable(*surf, deplin_lim);
+ std::cout << "Number of unpeelable functions: " << funs.size() << std::endl;
+
+ vector > lindep;
+ if (funs.size() >= deplin_lim)
+ {
+ // A possibility for a linear dependence relationship. Check if there
+ // really is such a situation
+ LinDepUtils::checkOverloaded(deplin_lim, funs, lindep);
+ if (lindep.size() > 0)
+ {
+ std::cout << "Number linear dependence situations: " << lindep.size() << std::endl;
+ // A linear dependency relation requires at least seven B-splines situated
+ // entirely within the domain of one large B-splines
+ // Write the support of the large B-spline to file
+ for (size_t kr=0; krumin() << " " << cb->vmin() << " 0 ";
+ lin_out << cb->umax() << " " << cb->vmin() << " 0" << std::endl;
+ lin_out << cb->umin() << " " << cb->vmin() << " 0 ";
+ lin_out << cb->umin() << " " << cb->vmax() << " 0" << std::endl;
+ lin_out << cb->umax() << " " << cb->vmin() << " 0 ";
+ lin_out << cb->umax() << " " << cb->vmax() << " 0" << std::endl;
+ lin_out << cb->umin() << " " << cb->vmax() << " 0 ";
+ lin_out << cb->umax() << " " << cb->vmax() << " 0" << std::endl;
+ }
+ }
+ }
+
+ // Write LR mesh to file.
+ int colour = 1;
+ writeg2Mesh(*surf, lin_out, colour);
+
+ if (lindep.size() > 0)
+ {
+ // Resolve the linear dependence by applying structured mesh refinement
+ // to the main B-spline in the dependence relation
+
+ int nmb_iter = 10; // The refinement is intended to resolve the linear
+ // dependence situation but might create new ones. Thus, more than one
+ // refinement iteration might be required.
+ for (int ka=0; ka source;
+ for (size_t kr=0; kr refs_x, refs_y;
+ bool adjust = true; // Prefer elongation of existing mesh lines
+ // if possible
+ bool reduced = true; // Avoid dense mesh lines if a sufficient
+ // number of refinements are defined otherwise (deviates from
+ // structured mesh)
+ DefineRefs2D::refineStructuredMesh(*surf, source, refs_x, refs_y,
+ adjust, reduced);
+ std::cout << "Number of new mesh lines: " << refs_x.size() + refs_y.size() << std::endl;
+
+ // Perform refinement
+ for (size_t kr=0; krrefine(refs_x[kr], true);
+
+ for (size_t kr=0; krrefine(refs_y[kr], true);
+
+ // Check again for linear independence
+ vector funs2 = LinDepUtils::fetchUnpeelable(*surf, deplin_lim);
+ std::cout << "Number of unpeelable functions after extra refinement: " << funs2.size() << std::endl;
+ if (funs2.size() < 8)
+ break;
+ vector > lindep2;
+ LinDepUtils::checkOverloaded(deplin_lim, funs2, lindep2);
+ std::cout << "Number of linear dependence relations: " << lindep2.size() << std::endl;
+
+ if (lindep2.size() > 0)
+ lindep = lindep2;
+ else
+ break;
+ }
+ }
+
+ // Write final surface and to file
+ surf->writeStandardHeader(surf_out);
+ surf->write(surf_out);
+
+ writeg2Mesh(*surf, mesh_out, colour);
+
+}
+
diff --git a/lrsplines2D/examples/investigate_Element2D.C b/lrsplines2D/examples/investigate_Element2D.C
new file mode 100644
index 00000000..05190145
--- /dev/null
+++ b/lrsplines2D/examples/investigate_Element2D.C
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines2D/LRSplineSurface.h"
+#include "GoTools/lrsplines2D/Element2D.h"
+#include "GoTools/geometry/RectDomain.h"
+#include "GoTools/geometry/PointCloud.h"
+#include "GoTools/geometry/SplineCurve.h"
+#include "GoTools/geometry/SplineSurface.h"
+#include "GoTools/geometry/ObjectHeader.h"
+#include "GoTools/geometry/Factory.h"
+#include "GoTools/geometry/GoTools.h"
+#include
+
+using namespace Go;
+using std::vector;
+
+//===========================================================================
+//
+/// Description:
+/// Read LR B-spline surface from file.
+/// Iterate through all elements in a surface and demonstrate available
+/// enquiries excluding those connected to scattered data approximation.
+///
+/// Input to the example is the surface constructed in the example
+/// program refine_lrsurf.
+/// For each element, the Bezier coefs of the corresponding patch are computed
+/// and stored in the file data/Bezier_coefs.g2. The corresponding patches
+/// are represented as spline surfaces and written to data/Bezier_patches.g2.
+//
+//===========================================================================
+
+int main(int argc, char *argv[])
+{
+ // Read LR B-spline surface from file
+ std::string infile("data/lrsurf_fin.g2");
+ std::ifstream input1(infile.c_str());
+ std::ifstream input2(infile.c_str());
+
+ // Prepare for output
+ std::string outfile1("data/Bezier_coefs.g2");
+ std::string outfile2("data/Bezier_patches.g2");
+ std::ofstream of1(outfile1.c_str());
+ std::ofstream of2(outfile2.c_str());
+
+ // Read header specifying the type of geometry entity
+ // The function throws if the entity header is invalid
+ ObjectHeader header1;
+ try {
+ header1.read(input1);
+ }
+ catch (...)
+ {
+ std::cerr << "File empty or corrupt. Exiting" << std::endl;
+ exit(-1);
+ }
+
+ // The following assumes that the specified file contains an LR spline
+ // surface
+ // Create empty surface
+ shared_ptr surf1(new LRSplineSurface());
+ surf1->read(input1);
+ if (!surf1.get())
+ {
+ std::cerr << "The file contains no LR B-spline surface" << std::endl;
+ exit(-1);
+ }
+
+ // Alternative reading procedure if we don't know that the file contains
+ // an LR spline surface
+ // Create the default factory
+ GoTools::init();
+ Registrator r293;
+
+ // Read the geometry object specified in the header
+ ObjectHeader header2;
+ try {
+ header2.read(input2);
+ }
+ catch (...)
+ {
+ std::cerr << "File empty or corrupt. Exiting" << std::endl;
+ exit(-1);
+ }
+
+ // Read specified entity
+ shared_ptr geom_obj(Factory::createObject(header2.classType()));
+ geom_obj->read(input2);
+
+ // Safe cast to LRSplineSurface
+ shared_ptr surf2 =
+ dynamic_pointer_cast(geom_obj);
+ if (!surf2.get())
+ {
+ std::cerr << "The file contains no LR spline surface" << std::endl;
+ exit(-1);
+ }
+
+ // Fetch parameter domain of surface
+ RectDomain dom = surf1->containingDomain();
+
+ // Mid point of parameter domain
+ double umid = 0.5*(dom.umin() + dom.umax());
+ double vmid = 0.5*(dom.vmin() + dom.vmax());
+
+ // Fetch degrees and dimension of geometry space for the
+ // surface
+ int deg1 = surf1->degree(XFIXED);
+ int deg2 = surf1->degree(YFIXED);
+ int dim = surf1->dimension();
+
+ // Knot vector for Bezier patch
+ vector knots1(2*(deg1+1));
+ vector knots2(2*(deg2+1));
+ for (int ki=0; ki<=deg1; ++ki)
+ {
+ knots1[ki] = 0.0;
+ knots1[deg1+1+ki] = 1.0;
+ }
+ for (int ki=0; ki<=deg2; ++ki)
+ {
+ knots2[ki] = 0.0;
+ knots2[deg2+1+ki] = 1.0;
+ }
+
+ // Iterate through all elements
+ for (LRSplineSurface::ElementMap::const_iterator el = surf1->elementsBegin();
+ el != surf1->elementsEnd(); ++el)
+ {
+ // Enquire parameter domain of the current element
+ double umin = el->second->umin();
+ double umax = el->second->umax();
+ double vmin = el->second->vmin();
+ double vmax = el->second->vmax();
+
+ // Parameter domain area of element
+ double area = el->second->area();
+
+ // Number of B-splines having this element in its support
+ int num_Bspline = el->second->nmbBasisFunctions(); // Alternative nmbSupport()
+
+ // Fetch all B-splines having this element in its support
+ // Iterators are also available
+ const vector Bsplines = el->second->getSupport();
+
+ // Fetch first B-spline
+ LRBSpline2D* curr_bspline = 0;
+ if (num_Bspline > 0)
+ {
+ curr_bspline = el->second->supportFunction(0);
+ }
+
+ // Check if the mid parameter belongs to this element
+ bool is_inside = el->second->contains(umid, vmid);
+
+ // Get all neighbouring elements to this one
+ vector neighbours;
+ el->second->fetchNeighbours(neighbours);
+
+ // Translate the surface patch corresponding to the current element
+ // to a Bezier surface and fetch the associated coefficients
+ vector Bezier_coefs = el->second->unitSquareBernsteinBasis();
+
+ // Write coefficients to file as a PointCloud.
+ // NB! The current surface is a 3D surface, for a function the
+ // coefficients needs to be represented in 3D before defining the
+ // PointCloud.
+ PointCloud3D coef_cloud(&Bezier_coefs[0], Bezier_coefs.size()/3);
+ coef_cloud.writeStandardHeader(of1);
+ coef_cloud.write(of1);
+
+ // Define Bezier patch as spline surface
+ shared_ptr Bezier_patch(new SplineSurface(deg1+1, deg2+1,
+ deg1+1, deg2+1,
+ &knots1[0],
+ &knots2[0],
+ &Bezier_coefs[0],
+ dim));
+ Bezier_patch->writeStandardHeader(of2);
+ Bezier_patch->write(of2);
+
+ }
+
+}
+
diff --git a/lrsplines2D/examples/investigate_LRSplineSurface.C b/lrsplines2D/examples/investigate_LRSplineSurface.C
new file mode 100644
index 00000000..f1e9e3e5
--- /dev/null
+++ b/lrsplines2D/examples/investigate_LRSplineSurface.C
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines2D/LRSplineSurface.h"
+#include "GoTools/lrsplines2D/Element2D.h"
+#include "GoTools/lrsplines2D/LRBSpline2D.h"
+#include "GoTools/geometry/RectDomain.h"
+#include "GoTools/geometry/PointCloud.h"
+#include "GoTools/geometry/SplineCurve.h"
+#include "GoTools/geometry/SplineSurface.h"
+#include "GoTools/geometry/ObjectHeader.h"
+#include "GoTools/geometry/Factory.h"
+#include "GoTools/geometry/GoTools.h"
+#include
+
+using namespace Go;
+using std::vector;
+using std::pair;
+
+//===========================================================================
+//
+/// Description:
+/// Read LR spline surface from file.
+/// Iterate trough all elements and B-splines in the surface.
+/// Enquire various information about the surface and represent the
+/// surface as a tensor product surface and as a collection of simpler
+/// LR B-spline surfaces.
+/// The purpose is to demonstrate various functionaliy.
+/// Parts of this example is similar to investigate_Element2D.
+/// For evaluation, see the example evaluateLRSurface.
+/// More functionality can be found in LRSplineSurface.h
+///
+/// The input surface is computed by the example program
+/// approximateParPointsWithLRSurf and expected to be found in
+/// data/approx_lrsurf.g2
+/// The tensor product surface is written to data/TP_surface.g2 and
+/// the collection of simpler surfaces to data/sub_surfs.g2.
+//
+//===========================================================================
+
+int main(int argc, char *argv[])
+{
+ // Read LR B-spline surface from file
+ std::string infile("data/lrsurf_ref1.g2"); //approx_lrsurf.g2");
+ std::ifstream input1(infile.c_str());
+ std::ifstream input2(infile.c_str());
+
+ // Prepare for output
+ std::string outfile1("data/TP_surface.g2");
+ std::string outfile2("data/sub_surf.g2");
+ std::ofstream of1(outfile1.c_str());
+ std::ofstream of2(outfile2.c_str());
+
+ // Two approaches is used to read the surface, one where the type of the
+ // geometric entity in the file is known and one where this is not the case
+
+ // Read header specifying the type of geometry entity
+ ObjectHeader header1;
+ try {
+ header1.read(input1);
+ }
+ catch (...)
+ {
+ std::cerr << "Exiting" << std::endl;
+ exit(-1);
+ }
+
+ // The following assumes that the specified file contains an LR B-spline
+ // surface
+ // Create empty surface
+ shared_ptr surf1(new LRSplineSurface());
+ surf1->read(input1);
+ if (!surf1.get())
+ {
+ std::cerr << "The file contains no LR B-spline surface" << std::endl;
+ exit(-1);
+ }
+
+ // Alternative reading procedure if we don't know that the file contains
+ // an LR B-spline surface
+ // Create the default factory
+ GoTools::init();
+ Registrator r293;
+
+ // Read the geometry object specified in the header
+ ObjectHeader header2;
+ try {
+ header2.read(input2);
+ }
+ catch (...)
+ {
+ std::cerr << "File empty or corrupt. Exiting" << std::endl;
+ exit(-1);
+ }
+
+ // Read specified element
+ shared_ptr geom_obj(Factory::createObject(header2.classType()));
+ geom_obj->read(input2);
+
+ // Safe cast to LRSplineSurface
+ shared_ptr surf2 =
+ dynamic_pointer_cast(geom_obj);
+ if (!surf2.get())
+ {
+ std::cerr << "The file contains no LR spline surface" << std::endl;
+ exit(-1);
+ }
+
+ // Fetch degrees and dimension of geometry space for the
+ // surface
+ int deg1 = surf1->degree(XFIXED);
+ int deg2 = surf1->degree(YFIXED);
+ int dim = surf1->dimension();
+ std::cout << "Dimension: " << dim << ", degree in first parameter direction: ";
+ std::cout << deg1 << ", degree in second parameter direction: " << deg2 << std::endl;
+
+ // Enquire limits of parameter domain
+ double umin = surf1->paramMin(XFIXED); // First parameter direction
+ double umax = surf1->paramMax(XFIXED);
+ double vmin = surf1->paramMin(YFIXED); // Second parameter direction
+ double vmax = surf1->paramMax(YFIXED);
+ std::cout << "Parameter domain: [" << umin << "," << umax << "] x [";
+ std::cout << vmin << "," << vmax << "]" << std::endl;
+
+ int num_elem = surf1->numElements();
+ std::cout << "Number of elements: " << num_elem << std::endl;
+
+ // Iterate through all elements
+ for (LRSplineSurface::ElementMap::const_iterator el = surf1->elementsBegin();
+ el != surf1->elementsEnd(); ++el)
+ {
+ // Example functionality, see investigate_Element2D for more
+ // Enquire parameter domain of the current element
+ double umin_el = el->second->umin();
+ double umax_el = el->second->umax();
+ double vmin_el = el->second->vmin();
+ double vmax_el = el->second->vmax();
+ }
+
+ int num_bspl = surf1->numBasisFunctions();
+ std::cout << "Number of B-splines: " << num_bspl << std::endl;
+
+ // Iterate through all B-splines
+ for (LRSplineSurface::BSplineMap::const_iterator bsp = surf1->basisFunctionsBegin();
+ bsp != surf1->basisFunctionsEnd(); ++bsp)
+ {
+ // Example functionaly
+ // Enquire knot vector in the two parameter directions
+ // First fetch index of knots in the LR Mesh
+ vector kvec1 = bsp->second->kvec(XFIXED);
+ vector kvec2 = bsp->second->kvec(YFIXED);
+
+ // Populate with actual knot values
+ vector knots1(kvec1.size());
+ vector knots2(kvec2.size());
+ for (size_t ki=0; kisecond->knotval(XFIXED, (int)ki);
+ for (size_t ki=0; kisecond->knotval(YFIXED, (int)ki);
+ }
+
+ // Split the surface into simpler pieces
+ int threshold_missing = 100; // Govern requested degree of simplicity
+ double tol = 0.001; // Used in the context of a trimmed surface
+ vector, LRSplineSurface::PatchStatus> > sub_sfs =
+ surf1->subdivideIntoSimpler(threshold_missing, tol);
+ std::cout << "Number of sub surfaces: " << sub_sfs.size() << std::endl;
+ if (sub_sfs.size() > 0)
+ {
+ for (size_t ki=0; kiwriteStandardHeader(of2);
+ sub_sfs[ki].first->write(of2);
+ }
+ }
+
+ // Check if the LR spline surface is a tensor-product surface
+ bool TP = surf1->isFullTensorProduct();
+ std::cout << "Surface is tensor product: " << TP << std::endl;
+
+ // Create tensor product spline surface
+ // First add knots such to obtain a tensor product mesh
+ // NB! This functionality is not reversible
+ surf1->expandToFullTensorProduct();
+
+ // Fetch spline surface
+ shared_ptr tpsurf(surf1->asSplineSurface());
+ if (tpsurf.get())
+ {
+ tpsurf->writeStandardHeader(of1);
+ tpsurf->write(of1);
+ }
+}
+
+
diff --git a/lrsplines2D/examples/isoContoursLRFunc.C b/lrsplines2D/examples/isoContoursLRFunc.C
new file mode 100644
index 00000000..78c421fe
--- /dev/null
+++ b/lrsplines2D/examples/isoContoursLRFunc.C
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines2D/LRSplineSurface.h"
+#include "GoTools/lrsplines2D/LRTraceIsocontours.h"
+#include "GoTools/geometry/ObjectHeader.h"
+#include "GoTools/geometry/Factory.h"
+#include "GoTools/geometry/GoTools.h"
+#include "GoTools/utils/BoundingBox.h"
+
+#include
+
+using namespace Go;
+using std::vector;
+
+//===========================================================================
+//
+/// Description: Read LR spline function or trimmed LR spline function from
+/// file. Compute equally spaced contour curves.
+///
+/// Input to the example is read from
+/// gotools/gotools-data/lrsplines2D/examples/data. The path is hardcoded.
+/// Note that the example must be run from a build directory directly
+/// placed under gotools to find the data. With another location, modify
+/// the path.
+/// The resulting curves in geometry and parameter space is written to
+/// data/iso_cvs_3D.g2 and data/iso_cvs_par.g2, respectively. In the first
+/// case, the two first coordinates are given by the parameter
+/// domain curves while the height value constitutes the last coordinate.
+//
+//===========================================================================
+
+int main(int argc, char *argv[])
+{
+ // Prepare for reading the surface file
+ std::string infile("../../gotools-data/lrsplines2D/examples/data/Fjoloy_surf.g2");
+ std::ifstream sfin(infile.c_str());
+
+ // Prepare for output
+ std::string outfile1("data/iso_cvs_3D.g2");
+ std::string outfile2("data/iso_cvs_par.g2");
+ std::ofstream of1(outfile1.c_str());
+ std::ofstream of2(outfile2.c_str());
+
+ // Create the default factory
+ GoTools::init();
+ Registrator r293;
+
+ // Read surface
+ ObjectHeader header;
+ header.read(sfin);
+ shared_ptr geom_obj(Factory::createObject(header.classType()));
+
+ // The surface is either an LR B-spline surface (current) of a trimmed
+ // version thereof. In both case, the surface is a parametric surface.
+ shared_ptr surf =
+ dynamic_pointer_cast(geom_obj);
+ if (!surf.get())
+ {
+ std::cout << "Object one is not a surface" << std::endl;
+ exit(1);
+ }
+ surf->read(sfin);
+ sfin.close();
+
+ int dim = surf->dimension();
+ if (dim != 1)
+ {
+ std::cout << "The given surface is not in 1D (a function). Exiting" << std::endl;
+ exit(1);
+ }
+
+ // Define height values for the contour curves
+ // Find an upper bound on the extent of the height values by computing
+ // the bounding box of the surface
+ BoundingBox bbox = surf->boundingBox();
+
+ const double minval = bbox.low()[0];
+ const double maxval = bbox.high()[0];
+ double minval2 = 10.0*((int)minval/10);
+ if (minval > 0.0)
+ minval2 += 1.0;
+ double maxval2 = 10.0*((int)maxval/10);
+
+ int num_val = (maxval2 - minval2)/10 + 1;
+ if (num_val <= 2)
+ num_val = 3;
+
+ vector iso_vals(num_val, 0);
+ for (int ki = 0; ki != num_val; ++ki)
+ iso_vals[ki] = minval2 + ((maxval2 - minval2)/(num_val-1)) * ki;
+
+ // Compute iso contours
+ double tol = 0.1; // The tolerance applies to the position in the
+ // x- and y- plane. The height value is excact. As the domain of
+ // the surface is large, a high tolerance is feasible
+ int threshold_missing = 100; // To govern an internal split of the surface
+ // into a set of simpler LR B-spline surfaces
+
+ // CurveVec is defined as
+ //std::vector, std::shared_ptr>>.
+ // The first curve pointer of the pair represents a 2D curve in the parameter
+ // domain of the investigated LR spline function. The second curve pointer
+ // represents the corresponding 3D curve, if requested.
+ const vector curves = LRTraceIsocontours(surf,
+ iso_vals,
+ threshold_missing,
+ tol);
+
+ // Write curves in geometry space, file. The curves can be visualized in
+ // goview or goview_vol_and_lr
+ for (size_t kj=0; kjwriteStandardHeader(of1);
+ curves[kj][kr].second->write(of1);
+ }
+ }
+ }
+
+ // Write parameter space curves to file
+ for (size_t kj=0; kjwriteStandardHeader(of2);
+ curves[kj][kr].first->write(of2);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+
diff --git a/lrsplines2D/examples/refine_lrsurf.C b/lrsplines2D/examples/refine_lrsurf.C
new file mode 100644
index 00000000..0d774c73
--- /dev/null
+++ b/lrsplines2D/examples/refine_lrsurf.C
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines2D/LRSplineSurface.h"
+#include "GoTools/lrsplines2D/LRBSpline2D.h"
+#include "GoTools/geometry/SplineSurface.h"
+#include "GoTools/lrsplines2D/LRSplinePlotUtils.h"
+#include
+
+using namespace Go;
+
+//===========================================================================
+//
+/// Description:
+/// The program defines a quadratic spline surface and represents this
+/// surface as an LR B-spline surface. This surface is refined, first in the
+/// second parameter direction, then in the first parameter direction.
+///
+/// Input to the geometry construction is hardcoded
+/// Current surfaces and meshes are written to g2- and eps-files as we go
+/// along. LR B-spline surfaces are visualized by
+/// gotools/viewlib/app/goview_vol_and_lr. Meshes are visualized by
+/// ghostview (gv). The final surface is written to the file
+/// data/lrsurf_fin.g2. The final mesh can be found at data/lrmesh_fin.eps.
+//
+//===========================================================================
+
+int main(int argc, char *argv[])
+{
+ // Prepare for output files
+ std::string outfile1("data/spline_sf_in.g2");
+ std::string outfile2("data/lrsurf_in.g2");
+ std::string outfile3("data/lrsurf_ref1.g2");
+ std::string outfile4("data/lrsurf_fin.g2");
+ std::string outfile5("data/lrmesh_1.eps");
+ std::string outfile6("data/lrmesh_2.eps");
+ std::string outfile7("data/lrmesh_fin.eps");
+
+ // Define biquadratic spline surface with three inner knots in the first
+ // parameter direction and two in the second direction
+ int dim = 3; // Dimension of geometry space
+ int in1 = 6, in2 = 5; // Number of coefficients in the two parameter directions
+ int deg1 = 2, deg2 = 2; // Polynomial degree
+ double knots1[9] = {0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 4.0};
+ double knots2[8] = {0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0};
+ double coefs[90] = {0.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 2.0, 0.0, 0.0,
+ 3.0, 0.0, 0.0,
+ 4.0, 0.0, 0.0,
+ 5.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 1.0, 1.0, 0.0,
+ 2.0, 1.0, 0.0,
+ 3.0, 1.0, 0.0,
+ 4.0, 1.0, 0.0,
+ 5.0, 1.0, 0.0,
+ 0.0, 2.0, 0.0,
+ 1.0, 2.0, 0.0,
+ 2.0, 2.0, 0.0,
+ 3.0, 2.0, 2.0,
+ 4.0, 2.0, 2.0,
+ 5.0, 2.0, 0.0,
+ 0.0, 3.0, 0.0,
+ 1.0, 3.0, 0.0,
+ 2.0, 3.0, 3.0,
+ 3.0, 3.0, 3.0,
+ 4.0, 3.0, 0.0,
+ 5.0, 3.0, 0.0,
+ 0.0, 4.0, 0.0,
+ 1.0, 4.0, 0.0,
+ 2.0, 4.0, 1.0,
+ 3.0, 4.0, 1.0,
+ 4.0, 4.0, 0.0,
+ 5.0, 4.0, 0.0};
+
+ // Create spline surface
+ shared_ptr spline_init(new SplineSurface(in1, in2,
+ deg1+1, deg2+1,
+ knots1, knots2,
+ coefs, dim));
+ std::ofstream of1(outfile1.c_str());
+ spline_init->writeStandardHeader(of1);
+ spline_init->write(of1);
+
+ // Represent the initial spline surface as an LR B-spline surface
+ // The second parameter indicates when two consequtive knots are
+ // regarded as identical
+ shared_ptr lr_surf(new LRSplineSurface(spline_init.get(),
+ 1.0e-6));
+ std::ofstream of2(outfile2.c_str());
+ lr_surf->writeStandardHeader(of2);
+ lr_surf->write(of2);
+
+ std::ofstream of5(outfile5.c_str());
+ writePostscriptMesh(*lr_surf, of5);
+
+ // Refine in the second parameter direction
+ Direction2D dir = YFIXED; // The constant direction of the new
+ // knot line segment
+ double par_y1 = 0.5; // Position of new knot in the corresponding knot vector
+ double par_y2 = 1.5; // Position of new knot in the corresponding knot vector
+ double start_y = 0.0; // The start value of the new segment
+ double end_y = 3.0; // The end value of the new segment
+ int mult = 1; // Knot multiplicity
+ bool absolute = true; // true = Do not increment multiplicity during
+ // multiple knot insertions,
+ // false = increment multiplicity
+
+ // Perform knot insertion, one knot line segment at the time
+ lr_surf->refine(dir, par_y1, start_y, end_y, mult, absolute);
+
+ // Collect knot insertion information in a structure. This call has the
+ // same effect as the previous
+ LRSplineSurface::Refinement2D ref_y2;
+ ref_y2.setVal(par_y2, start_y, end_y, dir, mult);
+ lr_surf->refine(ref_y2, absolute);
+
+ std::ofstream of3(outfile3.c_str());
+ lr_surf->writeStandardHeader(of3);
+ lr_surf->write(of3);
+
+ std::ofstream of6(outfile6.c_str());
+ writePostscriptMesh(*lr_surf, of6);
+
+ // Refine in the first parameter direction
+ dir = XFIXED;
+ double par_x1 = 1.5, par_x2 = 2.5;
+ double start_x = 0.0;
+ double end_x = 1.5;
+ lr_surf->refine(dir, par_x1, start_x, end_x, mult, absolute);
+ lr_surf->refine(dir, par_x2, start_x, end_x, mult, absolute);
+
+ std::ofstream of4(outfile4.c_str());
+ lr_surf->writeStandardHeader(of4);
+ lr_surf->write(of4);
+
+ std::ofstream of7(outfile7.c_str());
+ writePostscriptMesh(*lr_surf, of7);
+}
+
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/DefineRefs2D.h b/lrsplines2D/include/GoTools/lrsplines2D/DefineRefs2D.h
new file mode 100644
index 00000000..c11dab78
--- /dev/null
+++ b/lrsplines2D/include/GoTools/lrsplines2D/DefineRefs2D.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#ifndef DEFINEREFS2D_H
+#define DEFINEREFS2D_H
+
+#include "GoTools/lrsplines2D/LRSplineSurface.h"
+
+//==============================================================================
+namespace Go
+//==============================================================================
+{
+ /// Given a specifiction for how to refine with respect to an LRBSpline2D
+ /// (or Element2D?), prepare input for LRSplineSurface::refine
+
+ class LRBSpline2D;
+
+ namespace DefineRefs2D
+ {
+ /// For a set of B-splines, return specifiction of new mesh lines to insert
+ /// in order to perform structured mesh refinement
+ /// \param adjust if true: elongate existing mesh lines if possible
+ /// if false: always insert new mesh lines in the middle of
+ /// existing knots
+ /// \param reduced if true: skip some mesh lines if a complete structured mesh
+ /// would lead to close mesh lines
+ void refineStructuredMesh(const LRSplineSurface& surf,
+ std::vector& source,
+ std::vector& refs_x,
+ std::vector& refs_y,
+ bool adjust = true, bool reduced = false);
+
+ /// Add a new mesh line segment to the collection of such. Combine with
+ /// previously defined lines if possible
+ void appendRef(std::vector& refs,
+ LRSplineSurface::Refinement2D& curr_ref, double tol);
+
+
+ } // end namespace DefineRefs2D
+} // end namespace Go
+
+
+#endif
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/Element2D.h b/lrsplines2D/include/GoTools/lrsplines2D/Element2D.h
index 74c6ee55..a5418864 100644
--- a/lrsplines2D/include/GoTools/lrsplines2D/Element2D.h
+++ b/lrsplines2D/include/GoTools/lrsplines2D/Element2D.h
@@ -541,10 +541,41 @@ class Element2D
/// Modify the end of the element domain in the second parameter direction
void setVmax(double v) { stop_v_ = v; };
- bool isOverloaded() const;
- void resetOverloadCount() { overloadCount_ = 0; }
- int incrementOverloadCount() { return overloadCount_++; }
- int getOverloadCount() const { return overloadCount_; }
+ bool isOverloaded();
+ bool isOverloaded(int lowest_nmb);
+ bool initOverload()
+ {
+ if (isOverloaded())
+ overload_ = true;
+ return overload_;
+ }
+
+ bool initOverload(int lowest_nmb)
+ {
+ if (isOverloaded(lowest_nmb))
+ overload_ = true;
+ return overload_;
+ }
+
+ void setOverload(bool overload)
+ {
+ overload_ = overload;
+ }
+ bool getOverload()
+ {
+ return overload_;
+ }
+
+ bool resetOverload();
+ void eraseOverload()
+ {
+ overload_ = false;
+ }
+
+ // bool isOverloaded() const;
+ // void resetOverloadCount() { overloadCount_ = 0; }
+ // int incrementOverloadCount() { return overloadCount_++; }
+ // int getOverloadCount() const { return overloadCount_; }
void updateBasisPointers(std::vector &basis) ;
@@ -924,43 +955,36 @@ class Element2D
/// \return a vector of the coefficients of the control points p_ij in order p_00[0], p_00[1], ..., p_10[0], ..., p_01[0], ...
std::vector unitSquareBernsteinBasis() const;
- /// Get the Bezier curve (as a spline curve) given as the image of a line segment in the parameter space of the spline
- /// surface. The parameter domain of the curve will be [0, 1].
- /// \param start_u The u-value of the start point of the line segment
- /// \param start_v The v-value of the start point of the line segment
- /// \param end_u The u-value of the start point of the line segment
- /// \param end_v The v-value of the start point of the line segment
- /// \return The spline curve
- SplineCurve* curveOnElement(double start_u, double start_v, double end_u, double end_v) const;
// DEBUG
double sumOfScaledBsplines(double upar, double vpar);
private:
- double start_u_;
- double start_v_;
- double stop_u_;
- double stop_v_;
+ double start_u_;
+ double start_v_;
+ double stop_u_;
+ double stop_v_;
- std::vector support_;
+ std::vector support_;
- int overloadCount_ ;
+ //int overloadCount_ ;
- bool is_modified_;
+ bool is_modified_;
- // Information used in the context of least squares approximation
- // with smoothing
- mutable shared_ptr LSdata_;
+ // Information used in the context of least squares approximation
+ // with smoothing
+ mutable shared_ptr LSdata_;
+ mutable bool overload_;
- // Get the evaluations of the Bernstein functions up to given degree.
- // The evaluation of the j-th Bernstein function of degree i will be
- // stored as result[i][j] where 0 <= j <= i <= degree
- void bernsteinEvaluation(int degree, double value, std::vector >& result) const;
+ // Get the evaluations of the Bernstein functions up to given degree.
+ // The evaluation of the j-th Bernstein function of degree i will be
+ // stored as result[i][j] where 0 <= j <= i <= degree
+ void bernsteinEvaluation(int degree, double value, std::vector >& result) const;
- // For the linear function L, where L(0)=start and L(1)=end, we can express B^i_d(L) as
- // sum_{j=0} ^d c_{ij} B^i_d(t) where B^i_d is the i-th Bernstein basis function of degree d.
- // This method returns the c_{ij}-values, multiplied by binomial(d,j)
- void univariateBernsteinEvaluationInLine(int degree, double start, double end, std::vector >& result) const;
+ // For the linear function L, where L(0)=start and L(1)=end, we can express B^i_d(L) as
+ // sum_{j=0} ^d c_{ij} B^i_d(t) where B^i_d is the i-th Bernstein basis function of degree d.
+ // This method returns the c_{ij}-values, multiplied by binomial(d,j)
+ void univariateBernsteinEvaluationInLine(int degree, double start, double end, std::vector >& result) const;
};
} // end namespace Go
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/LRApproxApp.h b/lrsplines2D/include/GoTools/lrsplines2D/LRApproxApp.h
index e489de1c..0a1e31ff 100644
--- a/lrsplines2D/include/GoTools/lrsplines2D/LRApproxApp.h
+++ b/lrsplines2D/include/GoTools/lrsplines2D/LRApproxApp.h
@@ -98,6 +98,14 @@ namespace Go
std::vector& pointsdist,
int use_proj = 0);
+ void computeDistPointSpline3D(std::vector& points,
+ shared_ptr& surf,
+ double& max_above, double& max_below,
+ double& avdist, double& avdist_abs,
+ int& nmb_points,
+ std::vector& pointsdist,
+ bool close_dist);
+
/// Compute point cloud distance with respect to an LR B-spline surface
/// Multi-threaded version
void computeDistPointSpline_omp(std::vector& points,
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/LRBSpline2D.h b/lrsplines2D/include/GoTools/lrsplines2D/LRBSpline2D.h
index c41c5885..cffc5b9b 100644
--- a/lrsplines2D/include/GoTools/lrsplines2D/LRBSpline2D.h
+++ b/lrsplines2D/include/GoTools/lrsplines2D/LRBSpline2D.h
@@ -88,12 +88,13 @@ class LRBSpline2D : public Streamable
double gamma,
bool rational = false)
: coef_times_gamma_(c_g),
- weight_(weight),
- rational_(rational),
- gamma_(gamma),
- bspline_u_(bspline_u),
- bspline_v_(bspline_v),
- coef_fixed_(0)
+ weight_(weight),
+ rational_(rational),
+ gamma_(gamma),
+ bspline_u_(bspline_u),
+ bspline_v_(bspline_v),
+ coef_fixed_(0),
+ overload_(false)
{
bspline_u_->incrCount();
bspline_v_->incrCount();
@@ -112,6 +113,7 @@ class LRBSpline2D : public Streamable
std::swap(bspline_u_, rhs.bspline_u_);
std::swap(bspline_v_, rhs.bspline_v_);
std::swap(coef_fixed_,rhs.coef_fixed_);
+ std::swap(overload_,rhs.overload_);
}
/// Destructor
@@ -368,7 +370,10 @@ class LRBSpline2D : public Streamable
/// Check if the support of this B-spline overlaps the given element
bool overlaps(Element2D *el) const;
/// Check if the support of this B-spline overlaps the given domain: umin, umax, vmin, wmax.
- bool overlaps(double domain[]) const;
+ bool overlaps(double domain[]) const;
+ /// Check if the support of this B-spline cover the given domain: umin, umax, vmin, wmax.
+ bool covers(double domain[]) const;
+ bool covers(LRBSpline2D* bsp) const;
/// Add element to vector of elements in the support
bool addSupport(Element2D *el) ;
/// Remove element from vector of elements in the support
@@ -379,6 +384,17 @@ class LRBSpline2D : public Streamable
support_.clear();
}
+ bool getOverload()
+ {
+ return overload_;
+ }
+
+ bool checkOverload();
+ void eraseOverload()
+ {
+ overload_ = false;
+ }
+
/// Iterator to start of elements in the support
std::vector::iterator supportedElementBegin() ;
/// Iterator to end of elements in the support
@@ -464,6 +480,8 @@ class LRBSpline2D : public Streamable
// Used in least squares approximation with smoothing
int coef_fixed_; // 0=free coefficients, 1=fixed, 2=not affected
+ mutable bool overload_;
+
/// For a given interval inside one of the segments in the knot vector of a given direction, the
/// univariate B-spline in the direction is a polynomial. After transforming the rectangle to the
/// unit square, this polynomial can be expressed by the Bernstein basis.
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/LRSplinePlotUtils.h b/lrsplines2D/include/GoTools/lrsplines2D/LRSplinePlotUtils.h
index 163e03e8..ee8917ce 100644
--- a/lrsplines2D/include/GoTools/lrsplines2D/LRSplinePlotUtils.h
+++ b/lrsplines2D/include/GoTools/lrsplines2D/LRSplinePlotUtils.h
@@ -48,7 +48,11 @@
namespace Go
{
- // Write to file, on PostScript-format, the parametric mesh.
+ // Write mesh to g2 file
+ void writeg2Mesh(const Go::LRSplineSurface& lr_spline_sf,
+ std::ostream &out, int colour);
+
+ // Write to file, on PostScript-format, the parametric mesh.
void writePostscriptMesh(const Go::LRSplineSurface& lr_spline_sf,
std::ostream &out,
const bool close=true);
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/LRSplineSurface.h b/lrsplines2D/include/GoTools/lrsplines2D/LRSplineSurface.h
index 0ac9f3f2..fc7c8e60 100644
--- a/lrsplines2D/include/GoTools/lrsplines2D/LRSplineSurface.h
+++ b/lrsplines2D/include/GoTools/lrsplines2D/LRSplineSurface.h
@@ -642,7 +642,7 @@ namespace Go
bool isFullTensorProduct() const;
/// Tolerance for equality of knots
- double getKnotTol()
+ double getKnotTol() const
{
return knot_tol_;
}
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/LRSplineUtils.h b/lrsplines2D/include/GoTools/lrsplines2D/LRSplineUtils.h
index c47a3633..20a2d495 100644
--- a/lrsplines2D/include/GoTools/lrsplines2D/LRSplineUtils.h
+++ b/lrsplines2D/include/GoTools/lrsplines2D/LRSplineUtils.h
@@ -62,6 +62,9 @@ namespace Go
/// Utility functionality used in computations involving LR B-spline surfaces
namespace LRSplineUtils
{
+ /// In approximation setting, classify data points.
+ /// Most points are regular, significant points get a higher weight in
+ /// the approximation. Ghost points are obsolete.
enum PointType {
UNDEF_POINTS = 0,
REGULAR_POINTS = 1,
@@ -69,6 +72,42 @@ namespace Go
GHOST_POINTS = 3
};
+ /// Given a collection of B-splines (LRBsplines), evaluate the B-splines
+ /// in the given parameter value (upar,vpar). The evaluation results are
+ /// returned in result.
+ /// \param u_at_end True if upar is at the upper end of the parameter domain
+ /// \param v_at_end True if vpar is at the upper end of the parameter domain
+ void evalAllBSplines(const std::vector& bsplines,
+ double upar, double vpar,
+ bool u_at_end, bool v_at_end,
+ std::vector& result);
+
+ /// Given a collection of B-splines (bsplines), evaluate the B-splines
+ /// in the given parameter value (upar,vpar) and multiply this value with
+ /// the corresponding coefficient times the scaling weight.
+ /// The B-splines times scaled coefficients are returned in result.
+ /// \param u_at_end True if upar is at the upper end of the parameter domain
+ /// \param v_at_end True if vpar is at the upper end of the parameter domain
+ void evalAllBSplinePos(const std::vector& bsplines,
+ double upar, double vpar,
+ bool u_at_end, bool v_at_end,
+ std::vector& result);
+
+ /// Lifts a one-dimensional LR-spline function to a three-dimensional function by adding the
+ /// linear functions for the parameter values before the original function.
+ /// I.e. the function is changed
+ ///
+ /// from (u,v) |-> (f(u,v))
+ /// to (u,v) |-> (u, v, f(u,v))
+ void insertParameterFunctions(LRSplineSurface* lr_spline_sf);
+
+ /// Distribute given data points to elements
+ void distributeDataPoints(LRSplineSurface* srf, std::vector& points,
+ bool add_distance_field = false,
+ PointType type = REGULAR_POINTS,
+ bool outlier_flag = false);
+
+ /// Low order functionality related to refinement of an LR B-spline surface
LRSplineSurface::ElementMap identify_elements_from_mesh(const Mesh2D& m);
void update_elements_with_single_bspline(LRBSpline2D* b,
@@ -91,17 +130,6 @@ namespace Go
bool all_meshlines_uniform(Direction2D d, const Mesh2D& m);
- double compute_greville(const std::vector& v_ixs,
- const double* const vals);
-
- // Calculate the greville values for all b-splines in a knotvector
- // - deg is the polynomial degree of the b-splines
- // - knotvals points to the begining of the list of all possible different knot values
- // - k_vec_in holds the entire knot index vector, thus the i'th B-spline has knot vector indices k_vec_in[i]...k_vec_in[i+deg+1]
- // - Returns the greville value of the b-splines, length is k_vec_in.size() - deg - 1
- std::vector compute_greville(int deg, const std::vector& k_vec_in, const double* const knotvals);
-
-
std::vector knots_to_insert(const std::vector& ref,
const std::vector& mults);
@@ -152,16 +180,29 @@ namespace Go
void split_univariate(std::vector >& bsplines,
int& last, int fixed_ix, int mult);
+ void
+ get_affected_bsplines(const std::vector& refs,
+ const LRSplineSurface::ElementMap& emap,
+ double knot_tol, const Mesh2D& mesh,
+ std::vector& affected);
+
+ /// Low order functionality for computing Greville points
+ double compute_greville(const std::vector& v_ixs,
+ const double* const vals);
+
+ // Calculate the greville values for all b-splines in a knotvector
+ // - deg is the polynomial degree of the b-splines
+ // - knotvals points to the begining of the list of all possible different knot values
+ // - k_vec_in holds the entire knot index vector, thus the i'th B-spline has knot vector indices k_vec_in[i]...k_vec_in[i+deg+1]
+ // - Returns the greville value of the b-splines, length is k_vec_in.size() - deg - 1
+ std::vector compute_greville(int deg, const std::vector& k_vec_in, const double* const knotvals);
+
+
+ // Not implemented
bool elementOK(const Element2D* elem, const Mesh2D& m);
- // Lifts a one-dimensional LR-spline function to a three-dimensional function by adding the
- // linear functions for the parameter values before the original function.
- // I.e. the function is changed
- //
- // from (u,v) |-> (f(u,v))
- // to (u,v) |-> (u, v, f(u,v))
- void insertParameterFunctions(LRSplineSurface* lr_spline_sf);
+ /// Other low order functionality
SplineSurface* fullTensorProductSurface(const LRSplineSurface& lr_spline_sf);
// Fetch the B-spline with the coefficient closest to pos
@@ -171,28 +212,6 @@ namespace Go
std::vector > elementLineClouds(const LRSplineSurface& lr_spline_sf);
- // Distribute given data points to elements
- void distributeDataPoints(LRSplineSurface* srf, std::vector& points,
- bool add_distance_field = false,
- PointType type = REGULAR_POINTS,
- bool outlier_flag = false);
-
- void evalAllBSplines(const std::vector& bsplines,
- double upar, double vpar,
- bool u_at_end, bool v_at_end,
- std::vector& result);
-
- void evalAllBSplinePos(const std::vector& bsplines,
- double upar, double vpar,
- bool u_at_end, bool v_at_end,
- std::vector& result);
-
- void
- get_affected_bsplines(const std::vector& refs,
- const LRSplineSurface::ElementMap& emap,
- double knot_tol, const Mesh2D& mesh,
- std::vector& affected);
-
//==============================================================================
struct support_compare
//==============================================================================
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/LinDepUtils.h b/lrsplines2D/include/GoTools/lrsplines2D/LinDepUtils.h
index f4daf3db..13e61b06 100644
--- a/lrsplines2D/include/GoTools/lrsplines2D/LinDepUtils.h
+++ b/lrsplines2D/include/GoTools/lrsplines2D/LinDepUtils.h
@@ -77,6 +77,19 @@ namespace Go
//============================================================================
std::vector unpeelableBasisFunctions ( const LRSplineSurface& );
+ //============================================================================
+ //============================================================================
+ std::vector fetchUnpeelable( const LRSplineSurface& surf,
+ int minnmb);
+ //============================================================================
+ //============================================================================
+ bool overloadedMeshRectangles(const LRSplineSurface& surf);
+
+ //============================================================================
+ //============================================================================
+ void checkOverloaded(int minNmb, std::vector& funs,
+ std::vector >& lindep);
+
} // end namespace LinDepUtils
} // end namespace Go
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/examples_lrsplines2D_doxymain.h b/lrsplines2D/include/GoTools/lrsplines2D/examples_lrsplines2D_doxymain.h
new file mode 100644
index 00000000..43ad3de8
--- /dev/null
+++ b/lrsplines2D/include/GoTools/lrsplines2D/examples_lrsplines2D_doxymain.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#ifndef _EXAMPLES_LRSPLINES2D_DOXYMAIN_H
+#define _EXAMPLES_LRSPLINES2D_DOXYMAIN_H
+/**
+\page examples_LRSplines2D Example programs related to lrsplines2D
+
+A number of example programs related to lrsplines2D.
+
+refine_lrsurf.C
+
+This program demonstrates definition of an LR spline surface from a
+tensor-product spline surface and how to refine this surface with
+specified knot line segments.
+
+evaluateLRSurface.C
+
+This program demonstrates the various evaluation possibilities for an
+LR spline surface.
+
+investigate_LRSplineSurface.C
+
+This program demonstrates a set of enquire functionalities for an
+LR spline surface.
+
+investigate_Element2D.C
+
+This program reads an LR spline surface from file.
+It iterates trough all elements in the surface and demonstrate available
+enquiries.
+
+approximateWithLRFunc.C
+
+Given a point cloud that can be parameterized on its x- and y-coordinated,
+set appropriate parameters and approximate the points with an LR surface
+in 1D (function).
+
+approximateParPointsWithLRSurf.C
+
+Given a parameterized point cloud, set a ppropriate parameters and
+approximate the points with a 3D LR surface.
+
+isoContoursLRFunc.C
+
+Compute equally spaced contour curves from LR spline function.
+
+comparePointsLRSurf3D.C
+
+Compute distance between a points in a parameterized point cloud and
+the corresponding 3D surface. Collect points into groups according the
+this distance.
+
+identify_and_resolve_linear_dependence.C
+
+Identify B-splines involved in a linear dependence situation.
+Remove the dependence by applying structured mesh refinement to the
+main B-splines in the dependence relation.
+
+\example refine_lrsurf refine_lrsurf.C
+\verbatim
+\endverbatim
+
+This program demonstrates definition of an LR spline surface from a
+tensor-product spline surface and how to refine this surface with
+specified knot line segments.
+
+\example evaluateLRSurface evaluateLRSurface.C
+\verbatim
+\endverbatim
+
+This program demonstrates the various evaluation possibilities for an
+LR spline surface.
+
+\example investigate_LRSplineSurface investigate_LRSplineSurface.C
+\verbatim
+\endverbatim
+
+
+This program demonstrates a set of enquire functionalities for an
+LR spline surface.
+
+\example investigate_Element2D investigate_Element2D.C
+\verbatim
+\endverbatim
+
+This program reads an LR spline surface from file.
+It iterates trough all elements in the surface and demonstrate available
+enquiries.
+
+\example approximateWithLRFunc approximateWithLRFunc.C
+\verbatim
+\endverbatim
+
+Given a point cloud that can be parameterized on its x- and y-coordinated,
+set appropriate parameters and approximate the points with an LR surface
+in 1D (function).
+
+\example approximateParPointsWithLRSurf approximateParPointsWithLRSurf.C
+\verbatim
+\endverbatim
+
+Given a parameterized point cloud, set a ppropriate parameters and
+approximate the points with a 3D LR surface.
+
+\example isoContoursLRFunc isoContoursLRFunc.C
+\verbatim
+\endverbatim
+
+Compute equally spaced contour curves from LR spline function.
+
+\example comparePointsLRSurf3D comparePointsLRSurf3D.C
+\verbatim
+\endverbatim
+
+Compute distance between a points in a parameterized point cloud and
+the corresponding 3D surface. Collect points into groups according the
+this distance.
+
+\example identify_and_resolve_linear_dependence identify_and_resolve_linear_dependence.C
+\verbatim
+\endverbatim
+
+Identify B-splines involved in a linear dependence situation.
+Remove the dependence by applying structured mesh refinement to the
+main B-splines in the dependence relation.
+
+*/
+#endif
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/lrsplines2d-doxymain.h b/lrsplines2D/include/GoTools/lrsplines2D/lrsplines2d-doxymain.h
index 262dde5d..9f043b39 100644
--- a/lrsplines2D/include/GoTools/lrsplines2D/lrsplines2d-doxymain.h
+++ b/lrsplines2D/include/GoTools/lrsplines2D/lrsplines2d-doxymain.h
@@ -44,20 +44,227 @@
This module contains classes and tools for working with LR spline surfaces.
-\subsection Summary
+This module depends on the following GoTools modules:
+- GoTools Core
+and the following modules external to GoTools:
+- SISL (SINTEF)
-The module lrsplines2D represents LR-spline surfaces.
+Example programs corresponding to this module are listed in
+\link examples_LRSplines2D examples_lrsplines2D \endlink
-\subsection The problem with tensor product grids
+\subsection TP The problem with tensor-product grids
The simplest way to generate parametric surface patches is by applying the tensor-product construction to univariate parametric space curves. Examples of these are B-spline surfaces, B-spline volumes, NURBS surfaces and NURBS volumes, which are implemented in GoTools.
-The number of control points of these tensor-product patches grows exponentially with the dimension of the geometric object. For instance, for curves with 10 control points, corresponding tensor-product surfaces will have 100 control points and tensor-product volumes will have 1000 control points. These control points form a rectangular gridded structure, making it impossible to refine the model locally without refining across the entire domain. Hence, in practice, it becomes unfeasible to add sufficient detail to the model where it is needed most.
+The number of control points of these tensor-product patches grows exponentially with the dimension of the geometric object. For instance, for curves with 10 control points, corresponding tensor-product surfaces will have 100 control points and tensor-product volumes will have 1000 control points. These control points form a rectlinear gridded structure, making it impossible to refine the model locally without refining across the entire domain. Hence, in practice, it becomes unfeasible to add sufficient detail to the model where it is needed most.
-\subsection LR-splines
+\subsection LR LR B-splines and LR spline surfaces
Locally Refined B-splines (LR B-splines) aim to solve this problem by providing a mathematical framework, generalizing the tensor-product construction, for refining the model locally. This framework extends to any dimension.
+An LR spline surface, \link Go::LRSplineSurface \endlink, is a piecewise polynomial or piecewise rational polynomial surface defined on an LR-mesh, \link Go::Mesh2D \endlink. An LR-mesh is a locally refined mesh made by applying a sequence of
+refinements starting from a tensor-product mesh. LR spline surfaces are algorithmically defined throughout the refinement process of the mesh.
+An LR spline surface is defined as
+
+\f[ F(u,v) = \sum _{i=1}^L P_i s_i R_{i, p_1, p_2} (u,v) \f]
+
+where Pi, i=1, ... ,L are the surface coefficients,
+and si are scaling factors introduced
+to ensure partition of unity of the resulting collection of tensor product B-splines.
+The tensor product B-splines Ri,p1,p2
+are of bi-degree (p1,p2)
+defined on knot vectors of lengths p1 + 2 and p2 + 2
+on the parametric domain in the \[u\] and \[v\] directions respectively.
+
+\image html mesh.PNG "LR-mesh. The support of one tensor product B-spline visualized as a red pattern. Initial knotlines are shown as black lines, the inserted knotline segments are blue." width=600px
+An LR-mesh corresponding to an LR spline surface of bidegree two is shown in
+the figure above. The mesh lines of the initial tensor-product surface are drawn
+in black. The corresponding knots are: [u1, u1, u1, u2, u4, u6, u7, u7,u7] in the first parameter direction and [v1, v1, v1, v3, v5, v6, 46, v6] in the second direction.
+The LR-mesh is constructed by first inserting knots at v2 and
+v4 covering parts of the parameter domain in the second parameter
+direction follwed by knots at u3 and u5. Note that a new
+knot line must cover the support of at least one B-spline in the current
+surface. The parameter patches limited by knot lines are denoted elements,
+\link Go::Element2D \endlink, and serve a role in manouvring in the parameter
+domain of the surface. In approximation context (link to page) the elements
+contain data points. The initial B-spline surface has 30 basis
+functions (B-splines) while the
+constructed LR spline surface has 42 B-splines, \link Go::LRSpline2D \endlink.
+Some lines of the LR-mesh intersecting the support of such B-spline do not correspond to knotlines of its knot mesh as they do not traverse the support completely. The refinement process is performed in the example \link refine_lrsurf
+refine_lrsurf.C \endlink .
+
+
+The procedure applied is the following:
+
+- Add a new line segment that triggers the refinement of at least one existing tensor-product B-spline. It can be an extension of an existing line segment, can be independent of existing line segments, or increase the multiplicity of an existing the line segment. Thus, a line segment going from
+(u5,v4) to (u5,v5) is a legal choice.
+
- Subdivide all tensor product B-splines with support that is completely traversed by the new line/extended line.
+
- The tensor product B-splines are required to have minimal support. This means that all line segments traversing the support of a tensor product B-spline are required to be knotline segments of the B-spline taking the multiplicity of line segments into account. After
+inserting a new line segment and performing the subdivision in Step 2., there might still be tensor product B-splines that do not have minimal support with respect to the LR-mesh.
+Consequently all such B-splines must be refined.
+This process is continued until all tensor product B-splines have minimal support.
+
+If more than one new knotline segment is defined simultaneously, the refinement process is applied one segment at the time. Some details on how to choose
+new knot line segments can be found in \link lrsplines2d_refine \endlink .
+
+LR spline surface possess most of the nice properties of spline surfaces, such as:
+- Non-negative basis function
+- Partition of unity
+- The surface lies in the convex hull of its coefficients
+
+However, depending on the refinement strategy, linear dependence situations may
+occur. A case where such situations are identified and resolves is explained
+in the example \link identify_and_resolve_linear_dependence
+identify_and_resolve_linear_dependence.C \endlink.
+
+\subsection Classes Classes involved in representing an LR spline surface
+
+\subsubsection Mesh2D
+The LR-mesh is represented in \link Go::Mesh2D \endlink. It contains
+information about knot values in the two parameter directions and
+segments for each knot value. The latter has a compact encoding where a
+knot line segment is represented by the index of the start knot and the
+knot multiplicity. Active segments have multiplicity one or higher while
+segments with multiplicity 0 indicates that there is no knot in this part
+of the parameter domain.
+
+Mesh2D provides functionality to enquire properties of the mesh such as:
+number of knots excluding multiplicity (numDistinctKnots), value of a given
+knot (kval), iterators to knots (knotsBegin, knotsEnd), access to knots
+(getKnots), parameter domain (minParam, maxParam). Also mesh rectangle
+information such as knot multiplicity and active and not active knot line
+segments, is available.
+
+\subsubsection BSplineUniLR
+\link Go::BSplineUniLR \endlink represents a univariate B-spline by
+storing indices to the corresponding knot vector in Mesh2D to the active knots
+of the current B-splines. Properties like degree, knot values and
+parameter interval are deduced. Information about a possible overlap between
+two univariate B-splines and the Greville parameter of this B-splines is
+available.
+
+\subsubsection LRBSpline2D
+A \link Go::LRBSpline2D \endlink is constructed as a tensor product between
+two univariate B-splines (BSplineUniLR), but contains in addition the
+corresponding coefficient, the scaling factor and a possible rational weight.
+The class contains information of the element in the support of the B-spline.
+
+The class provides functionality to enquire the coefficient, scaling factor
+and rational weight as well as geometry space dimension, associated knot
+vector and degree. The elements in the support are avaiable and the
+support limits can be requested. The associated mesh is also available.
+
+\subsubsection Element2D
+An element represents the domain of one polynomial patch in the LR spline
+surface. It is limited by active knot line segments in both parameter
+direction. \link Go::Element2D \endlink contains information about the
+limits of this domain, the B-splines overlapping it and, in approximation
+context, data points associated to this domain. Element2D provides access
+to information about the domain properties, the associated B-eplines and
+neighbouring elements. The example program
+\link investigate_Element2D nvestigate_Element2D \endlink shows how to
+obtain information related to the elements.
+
+\subsubsection LRSplineSurface
+\link Go::LRSplineSurface \endlink inherites \link Go::ParamSurface \endlink
+and thus the functionality defined there. Some functionalities are not
+ implemented, e.g. area.
+
+LRSplineSurface is the owner of all information required to represent the
+surface. Bivariate B-splines and elements are
+contained in maps to facilitate rapid recognition of the element and B-splines
+having a given parameter pair in its support. A parameter remembering the last
+element requested serves as a tool to speed up this search. The class also
+contains all individual univariate B-splines required to define the bivariate
+B-splines.
+
+Evaluation is performed through the functions point and evalGrid. The first
+is implemented in several varieties: With and without computing
+derivatives and with and without getting the relevant element as input.
+The latter
+evaluates a regular grid of points, one by one, after connecting the elements
+with a tensor-product grid. Connecting a parameter pair to an element is the
+most time consuming part of the evaluation, and the grid ensures a rapid
+recognition. Evaluation is demonstrated in the example \link evaluateLRSurface.C
+evaluateLRSurface \endlink . See also \link investigate_LRSplineSurface.C
+investigate_LRSplineSurface \endlink for more functionality.
+
+The LRSplineSurface is constructed through refinement given a tensor-product
+grid as input. The constructor can
+receive a spline surface, \link Go::SplineSurface \endlink, or the information
+defining the grid as input. Refinement is triggered by LRSplineSurface, but
+performed in \link Go::LRSplineUtils \endlink. Given an element or a B-spline
+selected for refinement, a knot line segment that complies to the
+requirements, see \link LR \endlink, must be specified. Several options
+exists and are explained in some detail in \link lrsplines2d_refine \endlink .
+
+\subsection Classes2 Other classes, definitions and namespaces
+- BSplineUniUtils Utility functionality for keeping track of
+univariate B-splines. The univariate B-splines are stored as vector in
+LRSplineSurface and these vectors need to be kept updated during refine
+operations.
+- Direction2D Specifies the parameter direction of a surface, see
+\link Go::Direction2D \endlink
+- LinDepUtils The peeling algorithm, one step in identifiying linear
+dependencies, see \link Go::LinDepUtils \endlink
+- LogLikelyhood A statistical critierion for goodness of fit.
+Related to scattered data approximation.
+- LRApproxApp Functionality related to the approximation of a point
+cloud by an LR spline surface: specific interfaces to the approximation and
+computation of accuracy, see \link Go::LRApproxApp \endlink and
+example \link comparePointsLRSurf3D.C comparePointsLRSurf3D \endlink
+- LRBSpline2Dutils LRBSpline2D related functionality used in refinement.
+- LRFeatureUtils Given a current LR spline surface with an
+associated point cloud, compute feature output in a grid. Called from
+LRSurfApprox to visualize certain aspects of the approximation, see the
+help documentation in \link PointCloud2LR.C \endlink
+- LRMinMax Computes extrema of LR spline function. The functionality
+requires associated contour curves as input, see \link Go::LRMinMax \endlink
+- LRSplineEvalGrid Grid evaluation of the elements of an
+LR spline surface, \link Go::LRSplineEvalGrid \endlink
+- LRSplineMBA Called from LRSurfApprox. The name space provides
+functionality to update an LR spline surface using an adaptation to the local
+approximation method multi resolution B-spline approximation, see
+\link Go::LRSplineMBA \endlink
+- LRSplineUtils Utilities, mostly related to refinement of an
+LR spline surface, but the namespace contains also some more functionality,
+see \link Go::LRSplineUtils \endlink
+- LRSurfApprox Approximate a scattered data point cloud by a 1D or 3D
+LR spline surface. In the latter case, the point cloud must be parameterized.
+A large collection of parameters can be used to guide the approximation.
+A short explanation can be found in the help text to the application
+\link PointCloud2LR.C \endlink , which provides an interface to the
+functionality. See also \link Go::LRSurfApprox \endlink and the example
+programs \link approximateWithLRFunc approximateWithLRFunc.C \endlink and
+\link approximateParPointsWithLRSurf approximateParPointsWithLRSurf.C \endlink .
+A simplified interface can be found in \link Go::LRApproxApp \endlink.
+- LRSurfSmoothLS Least squares approximation with a smoothing term.
+Called from LRSurfApprox. This approximation approach is combined
+with multi resolution B-spline approximation (MBA) to compute the
+approximating surface. Least squares approximation is typically used in the
+start of the process, then the process continues with MBA,
+\link Go::LRSurfSmoothLS \endlink
+- LRSurfStitch Modifies a collection of bivariate LR spline functions
+organized in a regular pattern to obtain C0 or C1
+continuity between adjacent functions. The process involves an increase
+in data size of the functions. See \link Go::LRSurfStitch \endlink
+- LRTraceIsocontours Compute the level-set curves of an LR spline
+function. The function is used to compute contour curves and the use is
+illustrated in the app \link isoContours.C \endlink and the
+example \link isoContoursLRFunc isoContoursLRFunc.C \endlink, see also
+\link Go::LRTraceIsocontours \endlink
+- SSurfTraceIsocontours Used by LRTraceIsocontours.
+- TraceContoursTypedefs Typedefs and tempate functionality used by
+LRTraceIsocontours.
+- Mesh2DUtils Utility functionality for manouvring in an LR mesh.
+- MeshLR Base class for Mesh2D and \link Go::Mesh3D \endlink in
+lrsplines3D.
+- TrimSurface Create bounded surface from an LR B-spline function
+and associated point cloud to make the function domain correspond to the
+domain of the point cloud represented by its x- and y-values, see
+\link Go::TrimSurface \endlink
+- LRSplinePlotUtils and LRSplinePlotUtils2 Debug functionality
+
\subsection Sources
T. Dokken, T. Lyche, K.F. Pettersen. Polynomial splines over locally refined box-partitions, Computer Aided Geometric Design, Volume 30, Issue 3, March 2013, Pages 331--356
diff --git a/lrsplines2D/include/GoTools/lrsplines2D/refine_strategies-doxymain.h b/lrsplines2D/include/GoTools/lrsplines2D/refine_strategies-doxymain.h
new file mode 100644
index 00000000..2e3739ea
--- /dev/null
+++ b/lrsplines2D/include/GoTools/lrsplines2D/refine_strategies-doxymain.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#ifndef _REFINE_STRATEGIES_DOXYMAIN_H
+#define _REFINE_STRATEGIES_DOXYMAIN_H
+/**
+ \page lrsplines2d_refine LRsplines2D, strategies for refinement
+
+Given an element to refine, a knot line segment to insert in the LR mesh
+must be defined. According to the rules, this segment must cover the
+support of at least one B-spline. The segment itself can cover the support or
+it can extend an existing knot line segment partially covering the support
+such that the combined segments will lead to splitting the B-spline. There
+exists several strategies for defining knot line segments. One can
+select a B-spline with the given element in its support and define one or more
+segments covering the support of this B-spline or one can base the definition
+of the knot line segment(s) on the element itself. The main strategies are:
+
+- Full span Given an element selected for refinement, all B-splines overlapping this element
+ are split in a parameter contained in the element.
+- Minimum span The shortest possible knotline overlapping a chosen element that split
+ at least one B-spline, is selected. Several candidate B-splines may exist and even if additional
+ selection criteria are added, the candidate may not be unique. The selected knotline is not necessarily
+ symmetric with respect to the element.
+- Structured mesh Choose a B-spline and refine all knot intervals in this B-spline.
+ No elements with an unbalanced aspect ratio will be created if the split is performed in the
+ middle of the knot intervals.
+- Restricted mesh Refine some knot intervals in a selected B-spline.
+The strategy is mostly relevant in an approximation context. The knot
+intervals are selected by length and the approximation accuracy in the the
+elements associated to a knot interval.
+
+\subsection IGA Refinement strategies for IGA
+Structured mesh is the preferred approximation strategy in IGA. It results
+in a well behaved mesh, but the data size of the surface increases rapidly.
+Structured mesh is known not to result in linearly dependent B-splines for
+polynomial degrees one, two and three.
+
+\subsection approx Refinement strategies for scattered data approximation
+Refinement and reapproximation is performed iteratively. The procedure is
+as follows:
+
+- Define initial surface
+
- Check approximation accuracy
+
- Until a tolerance is reached or a maximum number of iterations is performed:
+
+- Identify elements or B-splines where the approximation is too poor
+
- Define new knot line segments
+
- Refine
+
- Approximate
+
- Check approximation accuracy
+
+
+
+In approximation context, it is important to obtained the best possbiel
+accuracy with the least number of coefficients. Furthermore, the selected
+refinement strategy should provide a stable good result. Experience shows
+that the Full span strategy is a good choice in this context. Further
+reduction in the number of coefficients can be obtained by refining one
+parameter direction only in one iteration and alternating the directions.
+This approach results in a sligthly less balanced mesh.
+
+A further reduction on the speed in which new coeffients are introduced
+can be obtained by not refining all elements or B-splines where the
+approximation accuracy is not met. Parameters to guide the refinement process
+can be set in LRSurfApprox::setRefinementStrategy,
+see \link Go::LRSurfApprox \endlink .
+
+The Minimum span strategy leads to the least introduction of new coefficients
+for each identified element to refine and can give good accuracy with few
+coefficients in the beginning of the iterative approximation process.
+However, it has a tendency to get stuck adding coefficients without
+improving the accuracy later in the process. Moreover, this strategy is the
+one most prone to lead to linear dependencies.
+
+**/
+#endif // _REFINE_STRATEGIES_DOXYMAIN_H
diff --git a/lrsplines2D/src/DefineRefs2D.C b/lrsplines2D/src/DefineRefs2D.C
new file mode 100644
index 00000000..c2d85825
--- /dev/null
+++ b/lrsplines2D/src/DefineRefs2D.C
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines2D/DefineRefs2D.h"
+#include "GoTools/lrsplines2D/LRBSpline2D.h"
+#include "GoTools/lrsplines2D/Mesh2D.h"
+
+using namespace Go;
+using std::vector;
+
+//==============================================================================
+// Prepare input for structured mesh refinement corresponding to a selection
+// of B-splines
+//
+void DefineRefs2D::refineStructuredMesh(const LRSplineSurface& surf,
+ vector& source,
+ vector& refs_x,
+ vector& refs_y,
+ bool adjust, bool reduced)
+//==============================================================================
+{
+ double tol = surf.getKnotTol();
+ if (source.size() == 0)
+ return;
+ const Mesh2D& mesh = surf.mesh();
+ for (size_t ki=0; kidegree(XFIXED)+1;
+ int size2 = source[ki]->degree(YFIXED)+1;
+ const vector& kvec1 = source[ki]->kvec(XFIXED);
+ const vector& kvec2 = source[ki]->kvec(YFIXED);
+ double umin = source[ki]->umin();
+ double umax = source[ki]->umax();
+ int uxmin = source[ki]->suppMin(XFIXED);
+ int uxmax = source[ki]->suppMax(XFIXED);
+ double vmin = source[ki]->vmin();
+ double vmax = source[ki]->vmax();
+ int vxmin = source[ki]->suppMin(YFIXED);
+ int vxmax = source[ki]->suppMax(YFIXED);
+ for (int kj=0; kj 1 && adjust)
+ {
+ int ix = kj;
+ double maxdist = 0.0;
+ double mid = (mesh.kval(XFIXED, kvec1[kj+1]) +
+ mesh.kval(XFIXED, kvec1[kj]))/2;
+ for (int ka=kvec1[kj]+1; ka mr = mesh.mrects(XFIXED, ka);
+ int nu1, nu2;
+ for (nu1=0; nu1 vxmin)
+ break;
+ for (nu2=0; nu2 vxmax)
+ break;
+ double dist = 0.0;
+ for (int kb=nu1; kb 0)
+ {
+ int l1 = std::max(vxmin, mr[kb].ix);
+ int l2 = (kb < mr.size()-1) ? std::min(vxmax, mr[kb+1].ix) : vxmax;
+ dist += fabs(mesh.kval(YFIXED, l2) - mesh.kval(YFIXED, l1));
+ }
+ if (fabs(mesh.kval(XFIXED,ka)-mid) < fabs(mesh.kval(XFIXED,ix)-mid) &&
+ dist > 0.0)
+ {
+ ix = ka;
+ if (dist > maxdist)
+ maxdist = dist;
+ }
+ else if (dist > 2.0*maxdist)
+ {
+ ix = ka;
+ maxdist = dist;
+ }
+ }
+ if (maxdist > 0.0)
+ upar = mesh.kval(XFIXED, ix);
+ else if (reduced)
+ continue;
+ else
+ upar = 0.5*(u1+u2);
+ }
+ else if (reduced)
+ continue;
+ else
+ upar = 0.5*(u1+u2);
+ LRSplineSurface::Refinement2D curr_ref;
+ curr_ref.setVal(upar, source[ki]->vmin(),
+ source[ki]->vmax(), XFIXED, 1);
+ appendRef(refs_x, curr_ref, tol);
+ }
+
+ for (int kj=0; kj 1 && adjust)
+ {
+ int ix = kj;
+ int maxdist = 0.0;
+ double mid = (mesh.kval(YFIXED, kvec2[kj+1]) +
+ mesh.kval(YFIXED, kvec2[kj]))/2;
+ for (int ka=kvec2[kj]+1; ka mr = mesh.mrects(YFIXED, ka);
+ int nu1, nu2;
+ for (nu1=0; nu1 uxmin)
+ break;
+ for (nu2=0; nu2 uxmax)
+ break;
+ double dist = 0.0;
+ for (int kb=nu1; kb 0)
+ {
+ int l1 = std::max(uxmin, mr[kb].ix);
+ int l2 = (kb < mr.size()-1) ? std::min(uxmax, mr[kb+1].ix) : uxmax;
+ dist += fabs(mesh.kval(XFIXED, l2) - mesh.kval(XFIXED, l1));
+ }
+ if (fabs(mesh.kval(YFIXED,ka)-mid) < fabs(mesh.kval(YFIXED,ix)-mid) &&
+ dist > 0.0)
+ {
+ ix = ka;
+ if (dist > maxdist)
+ maxdist = dist;
+ }
+ else if (dist > 2.0*maxdist)
+ {
+ ix = ka;
+ maxdist = dist;
+ }
+ }
+ if (maxdist > 0.0)
+ vpar = mesh.kval(YFIXED, ix);
+ else if (reduced)
+ continue;
+ else
+ vpar = 0.5*(v1+v2);
+ }
+ else if (reduced)
+ continue;
+ else
+ vpar = 0.5*(v1+v2);
+ LRSplineSurface::Refinement2D curr_ref;
+ curr_ref.setVal(vpar, source[ki]->umin(),
+ source[ki]->umax(), YFIXED, 1);
+ appendRef(refs_y, curr_ref, tol);
+ }
+ }
+
+}
+
+//==============================================================================
+void DefineRefs2D::appendRef(vector& refs,
+ LRSplineSurface::Refinement2D& curr_ref, double tol)
+//==============================================================================
+{
+ // Check if the current refinement can be combined with an existing one
+ size_t ki;
+ for (ki=0; ki curr_ref.end+tol ||
+ curr_ref.start > refs[ki].end+tol))
+ {
+ // Merge new knots
+ refs[ki].start = std::min(refs[ki].start, curr_ref.start);
+ refs[ki].end = std::max(refs[ki].end, curr_ref.end);
+ break;
+ }
+ }
+ }
+
+ if (ki == refs.size())
+ refs.push_back(curr_ref);
+}
+
diff --git a/lrsplines2D/src/Element2D.C b/lrsplines2D/src/Element2D.C
index efb9b592..10798717 100644
--- a/lrsplines2D/src/Element2D.C
+++ b/lrsplines2D/src/Element2D.C
@@ -77,8 +77,10 @@ Element2D::Element2D() {
start_v_ = 0;
stop_u_ = 0;
stop_v_ = 0;
- overloadCount_ = 0;
+ //overloadCount_ = 0;
is_modified_ = false;
+ overload_ = false;
+
}
Element2D::Element2D(double start_u, double start_v, double stop_u, double stop_v) {
@@ -87,14 +89,36 @@ Element2D::Element2D(double start_u, double start_v, double stop_u, double stop_
start_v_ = start_v;
stop_u_ = stop_u ;
stop_v_ = stop_v ;
- overloadCount_ = 0;
+ //overloadCount_ = 0;
is_modified_ = false;
+ overload_ = false;
+
}
Element2D::~Element2D()
{
}
+bool Element2D::resetOverload()
+{
+ int nmb = 0;
+ for (size_t ki=0; kigetOverload())
+ {
+ ++nmb;
+ if (nmb == 2)
+ break;
+ }
+
+ overload_ = (nmb >= 2);
+ if (!overload_)
+ {
+ for (size_t ki=0; kieraseOverload();
+ }
+ return overload_;
+}
+
void Element2D::removeSupportFunction(LRBSpline2D *f) {
for (size_t i=0; i 0) {
- int p1 = support_.front()->degree(YFIXED) + 1;
- int p2 = support_.front()->degree(XFIXED) + 1;
- if(n > p1*p2)
- return true;
+ int p1 = support_.front()->degree(YFIXED) + 1;
+ int p2 = support_.front()->degree(XFIXED) + 1;
+
+ if(n > p1*p2)
+ return true;
}
return false;
}
+bool Element2D::isOverloaded(int lowest_nmb) {
+ int n = (int)support_.size();
+ if(n > lowest_nmb)
+ return true;
+ else
+ return false;
+}
+
+
void Element2D::fetchNeighbours(vector& neighbours) const
{
neighbours.clear();
@@ -731,50 +765,6 @@ double Element2D::sumOfScaledBsplines(double upar, double vpar)
return result;
}
- SplineCurve* Element2D::curveOnElement(double start_u, double start_v, double end_u, double end_v) const
- {
- if (support_.size() == 0)
- return NULL; // This should not happen, some B-splines must have support in this element
-
- int dim = support_[0]->dimension();
- int deg_u = support_[0]->degree(XFIXED);
- int deg_v = support_[0]->degree(YFIXED);
-
- vector > bernstein_u;
- vector > bernstein_v;
- univariateBernsteinEvaluationInLine(deg_u, start_u, end_u, bernstein_u);
- univariateBernsteinEvaluationInLine(deg_v, start_v, end_v, bernstein_v);
-
- int degree = deg_u + deg_v;
- vector binomial(degree + 1); // binomial[i] shall be the binomial (degree Choose i)
- binomial[0] = binomial[degree] = 1;
- for (int i = 0; i + i <= degree; ++i)
- binomial[degree - i] = binomial[i] = (binomial[i - 1] * (degree - i + 1)) / i;
-
- vector curve_coefs(dim * (degree + 1));
- vector surface_coefs = unitSquareBernsteinBasis();
- vector::const_iterator surf_it;
-
- for (int i2 = 0; i2 <= deg_v; ++i2)
- for (int i1 = 0; i1 <= deg_u; ++i1)
- for (int k = 0; k <= dim; ++k, ++surf_it)
- for (int j2 = 0; j2 <= deg_v; ++j2)
- for (int j1 = 0; j1 <= deg_u; ++j1)
- curve_coefs[dim*(j1 + j2) + k] += bernstein_v[i2][j2] * bernstein_u[i1][j1] * (*surf_it);
-
- for (int i = 0; i <= degree; ++i)
- for (int k = 0; k <= dim; ++k)
- curve_coefs[i * dim + k] /= (double)binomial[i];
-
- vector knots(2 * (degree + 1));
- for (int i = 0; i <= degree; ++i)
- {
- knots[i] = 0.0;
- knots[i + degree + 1] = 1.0;
- }
-
- return new SplineCurve(degree + 1, degree + 1, knots.begin(), curve_coefs.begin(), dim);
- }
void Element2D::bernsteinEvaluation(int degree, double value, vector >& result) const
@@ -867,7 +857,7 @@ double Element2D::sumOfScaledBsplines(double upar, double vpar)
vector binomial(degree + 1); // binomial[i] shall be the binomial (degree Choose i)
binomial[0] = binomial[degree] = 1;
- for (int i = 0; i + i <= degree; ++i)
+ for (int i = 1; i + i <= degree; ++i)
binomial[degree - i] = binomial[i] = (binomial[i - 1] * (degree - i + 1)) / i;
for (int j = 0; j <= degree; ++j)
diff --git a/lrsplines2D/src/LRApproxApp.C b/lrsplines2D/src/LRApproxApp.C
index 83cc478b..57626bf7 100644
--- a/lrsplines2D/src/LRApproxApp.C
+++ b/lrsplines2D/src/LRApproxApp.C
@@ -503,6 +503,136 @@ void LRApproxApp::computeDistPointSpline(vector& points,
avdist /= nmb_points;
}
+//=============================================================================
+void LRApproxApp::computeDistPointSpline3D(vector& points,
+ shared_ptr& surf,
+ double& max_above, double& max_below,
+ double& avdist, double& avdist_abs,
+ int& nmb_points,
+ vector& pointsdist,
+ bool close_dist)
+//=============================================================================
+{
+ max_above = std::numeric_limits::lowest();
+ max_below = std::numeric_limits::max();
+ avdist = 0.0;
+ avdist_abs = 0.0;
+ nmb_points = 0;
+
+ if (surf->dimension() != 3)
+ return; // Expects 3D surface
+ int del = 5; // Expects parameterized points u,v,x,y,z
+ int nmb_pts = (int)points.size()/del;
+ if (nmb_pts*del != (int)points.size())
+ {
+ return; // Point cloud not properly parameterized
+ }
+
+ pointsdist.reserve(4*nmb_pts);
+
+ // Get all knot values in the u-direction
+ const double* const uknots = surf->mesh().knotsBegin(XFIXED);
+ const double* const uknots_end = surf->mesh().knotsEnd(XFIXED);
+ int nmb_knots_u = surf->mesh().numDistinctKnots(XFIXED);
+ const double* knotu;
+
+ // Get all knot values in the v-direction
+ const double* const vknots = surf->mesh().knotsBegin(YFIXED);
+ const double* const vknots_end = surf->mesh().knotsEnd(YFIXED);
+ const double* knotv;
+
+ double aeps = 0.001;
+
+ // Construct mesh of element pointers
+ vector elements;
+ surf->constructElementMesh(elements);
+
+ // For each point, classify according to distance
+ // Sort points in v-direction
+ qsort(&points[0], nmb_pts, del*sizeof(double), compare_v_par);
+
+ int ki, kj, kr, ka;
+ double *curr;
+ double dist;
+
+ int pp0, pp1;
+ Element2D* elem = NULL;
+ for (pp0=0, knotv=vknots; pp0<(int)points.size() && points[pp0+1] < (*knotv);
+ pp0+=del);
+ for (kj=0, ++knotv; knotv!= vknots_end; ++knotv, ++kj)
+ {
+
+ for (pp1=pp0; pp1<(int)points.size() && points[pp1+1] < (*knotv); pp1+=del);
+ if (knotv+1 == vknots_end)
+ for (; pp1<(int)points.size() && points[pp1+1] <= (*knotv); pp1+=del);
+ // pp1 = (int)points.size();
+
+ // Sort the current sub set of points according to the u-parameter
+ qsort(&points[0]+pp0, (pp1-pp0)/del, del*sizeof(double), compare_u_par);
+
+ // Traverse the relevant points and identify the associated element
+ int pp2, pp3;
+ for (pp2=pp0, knotu=uknots; pp2closestPoint(pt, upar, vpar, pos,
+ dist2, aeps, 5, elem, NULL, seed);
+ surf->normal(norm, upar, vpar, elem);
+ }
+ else
+ {
+ // Evaluate
+ surf->point(pos, curr[0], curr[1], elem);
+ surf->normal(norm, curr[0], curr[1], elem);
+
+ }
+ Point vec = pos - pt;
+ dist = pos.dist(pt);
+ if (vec*norm < 0.0)
+ dist *= -1;
+
+ max_above = std::max(max_above, dist);
+ max_below = std::min(max_below, dist);
+ avdist_abs += fabs(dist);
+ avdist += dist;
+ pointsdist.push_back(curr[2]);
+ pointsdist.push_back(curr[3]);
+ pointsdist.push_back(curr[4]);
+ pointsdist.push_back(dist);
+
+ nmb_points++;
+ }
+ pp2 = pp3;
+ }
+ pp0 = pp1;
+ }
+ if (nmb_points > 0)
+ {
+ avdist /= nmb_points;
+ avdist_abs /= nmb_points;
+ }
+}
+
//=============================================================================
void LRApproxApp::computeDistPointSpline_omp(vector& points,
shared_ptr& surf,
diff --git a/lrsplines2D/src/LRBSpline2D.C b/lrsplines2D/src/LRBSpline2D.C
index 2156f2c5..e88d6008 100644
--- a/lrsplines2D/src/LRBSpline2D.C
+++ b/lrsplines2D/src/LRBSpline2D.C
@@ -93,7 +93,7 @@ LRBSpline2D::LRBSpline2D(const LRBSpline2D& rhs)
rational_ = rhs.rational_;
// don't copy the support
weight_ = rhs.weight_;
-
+ overload_ = rhs.overload_;
}
//==============================================================================
@@ -180,6 +180,7 @@ void LRBSpline2D::write(ostream& os) const
bspline_v_->read(is);
coef_fixed_ = 0;
+ overload_ = false;
}
@@ -236,6 +237,7 @@ void LRBSpline2D::write(ostream& os) const
bspline_v_->incrCount();
coef_fixed_ = 0;
+ overload_ = false;
}
//==============================================================================
@@ -527,7 +529,40 @@ bool LRBSpline2D::overlaps(Element2D *el) const
return true;
}
+//==============================================================================
+bool LRBSpline2D::covers(double domain[]) const
+//==============================================================================
+{
+ // Does it make sense to include equality?
+ if (domain[0] < umin())
+ return false;
+ if (domain[1] > umax())
+ return false;
+ if (domain[2] < vmin())
+ return false;
+ if (domain[3] > vmax())
+ return false;
+
+ return true;
+}
+//==============================================================================
+bool LRBSpline2D::covers(LRBSpline2D *bsp) const
+//==============================================================================
+{
+ // Does it make sense to include equality?
+ if (bsp->umin() < umin())
+ return false;
+ if (bsp->umax() > umax())
+ return false;
+ if (bsp->vmin() < vmin())
+ return false;
+ if (bsp->vmax() > vmax())
+ return false;
+
+ return true;
+}
+
//==============================================================================
bool LRBSpline2D::addSupport(Element2D *el)
//==============================================================================
@@ -584,6 +619,23 @@ std::vector::iterator LRBSpline2D::supportedElementEnd()
return support_.end();
}
+//==============================================================================
+bool LRBSpline2D::checkOverload()
+//==============================================================================
+{
+ bool overload = true;
+ for (size_t ki=0; kigetOverload())
+ {
+ overload = false;
+ break;
+ }
+
+ overload_ = overload;
+ return overload;
+}
+
+
//==============================================================================
void LRBSpline2D::reverseParameterDirection(bool dir_is_u)
//==============================================================================
@@ -637,7 +689,7 @@ vector LRBSpline2D::unitIntervalBernsteinBasis(double start, double stop
vector > coefs(deg+1);
for (int i = 0; i < deg + 2; ++i)
- {
+ // {
knots.push_back(slope * (knotval(d,knots_int[i]) - start));
// Get the position of the interval containing [0,1]. We assume that for
@@ -693,7 +745,7 @@ vector LRBSpline2D::unitIntervalBernsteinBasis(double start, double stop
coefs[i][j] = res;
}
}
- }
+ // }
return coefs[0];
}
diff --git a/lrsplines2D/src/LRSplineMBA.C b/lrsplines2D/src/LRSplineMBA.C
index ad37ad26..fdb4ece0 100644
--- a/lrsplines2D/src/LRSplineMBA.C
+++ b/lrsplines2D/src/LRSplineMBA.C
@@ -206,7 +206,7 @@ void LRSplineMBA::MBADistAndUpdate(LRSplineSurface *srf,
for (int ka=2; ka= nmb_pts)
dist_2 *= significant_factor;
distvec.push_back(dist_2);
@@ -237,15 +237,15 @@ void LRSplineMBA::MBADistAndUpdate(LRSplineSurface *srf,
for (kj=0; kjcoefFixed())
- {
- // Do not modify B-spline. Adjust residual
- Point coef = bsplines[kj]->coefTimesGamma();
- for (int ka=0; kacoefFixed())
+ // {
+ // // Do not modify B-spline. Adjust residual
+ // Point coef = bsplines[kj]->coefTimesGamma();
+ // for (int ka=0; kagamma();
tmp_weights[kj] = wgt;
@@ -257,6 +257,8 @@ void LRSplineMBA::MBADistAndUpdate(LRSplineSurface *srf,
// Compute contribution
for (kj=0; kjcoefFixed())
+ // continue;
const double wc = tmp_weights[kj];
for (int ka=0; kagamma();
if (ki >= nmb_pts)
val[kj] *= significant_factor;
- if (bsplines[kj]->coefFixed())
- {
- // Do not modify B-spline. Adjust residual
- Point coef = bsplines[kj]->coefTimesGamma();
- for (int ka=0; kacoefFixed())
+ // {
+ // // Do not modify B-spline. Adjust residual
+ // Point coef = bsplines[kj]->coefTimesGamma();
+ // for (int ka=0; kagamma();
// printf("kj: %i\n", kj);
diff --git a/lrsplines2D/src/LRSplinePlotUtils.C b/lrsplines2D/src/LRSplinePlotUtils.C
index 68a90372..b1b15ae9 100644
--- a/lrsplines2D/src/LRSplinePlotUtils.C
+++ b/lrsplines2D/src/LRSplinePlotUtils.C
@@ -46,6 +46,76 @@ using std::vector;
namespace Go
{
+
+ void writeg2Mesh(const Go::LRSplineSurface& lr_spline_sf,
+ std::ostream &out, int colour)
+ {
+ std::streamsize prev = out.precision(15);
+ const bool colorDiag = false;
+ const Mesh2D& mesh = lr_spline_sf.mesh();
+ const int num_diff_knots_u = mesh.numDistinctKnots(XFIXED);
+ const int num_diff_knots_v = mesh.numDistinctKnots(YFIXED);
+ // std::vector knot_u(num_diff_knots_u), knot_v(num_diff_knots_v);
+ const double* const knot_u = mesh.knotsBegin(XFIXED);
+ const double* const knot_v = mesh.knotsBegin(YFIXED);
+ // lr_spline_sf.getGlobalUniqueKnotVector(knot_u, knot_v);
+ vector line;
+ Mesh2DIterator mesh_beg = mesh.begin();
+ Mesh2DIterator mesh_end = mesh.end();
+ Mesh2DIterator mesh_it = mesh_beg;
+ while (mesh_it != mesh_end)
+ {
+ const std::array elem_corners = *mesh_it; // ll_u, ll_v, ur_u, ur_v.
+ line.push_back(knot_u[elem_corners[0]]);
+ line.push_back(knot_v[elem_corners[1]]);
+ line.push_back(0.0);
+ line.push_back(knot_u[elem_corners[2]]);
+ line.push_back(knot_v[elem_corners[1]]);
+ line.push_back(0.0);
+
+ line.push_back(knot_u[elem_corners[0]]);
+ line.push_back(knot_v[elem_corners[3]]);
+ line.push_back(0.0);
+ line.push_back(knot_u[elem_corners[2]]);
+ line.push_back(knot_v[elem_corners[3]]);
+ line.push_back(0.0);
+
+ line.push_back(knot_u[elem_corners[0]]);
+ line.push_back(knot_v[elem_corners[1]]);
+ line.push_back(0.0);
+ line.push_back(knot_u[elem_corners[0]]);
+ line.push_back(knot_v[elem_corners[3]]);
+ line.push_back(0.0);
+
+ line.push_back(knot_u[elem_corners[2]]);
+ line.push_back(knot_v[elem_corners[1]]);
+ line.push_back(0.0);
+ line.push_back(knot_u[elem_corners[2]]);
+ line.push_back(knot_v[elem_corners[3]]);
+ line.push_back(0.0);
+
+ ++mesh_it;
+ }
+
+ out << "410 1 0 4 ";
+ if (colour == 0)
+ out << "200 200 0 255";
+ else if(colour == 1)
+ out << "255 0 0 255";
+ else if (colour == 2)
+ out << "0 255 0 255";
+ else
+ out << "0 0 255 255";
+ out << std::endl;
+ out << line.size()/6 << std::endl;
+ for (int ki=0; ki<(int)line.size(); ki+=6)
+ {
+ for (int kj=0; kj<6; ++kj)
+ out << line[ki+kj] << " ";
+ out << std::endl;
+ }
+ }
+
void writePostscriptMesh(const Go::LRSplineSurface& lr_spline_sf,
std::ostream &out, const bool close)
{
@@ -270,6 +340,7 @@ namespace Go
out << std::endl;
}
+
void writePostscriptMesh(const Go::Mesh2D& mesh,
int minx, int maxx, int miny, int maxy,
std::ostream &out, const bool close)
diff --git a/lrsplines2D/src/LRSurfApprox.C b/lrsplines2D/src/LRSurfApprox.C
index 475c427b..15527502 100644
--- a/lrsplines2D/src/LRSurfApprox.C
+++ b/lrsplines2D/src/LRSurfApprox.C
@@ -57,12 +57,12 @@
#include "stdio.h"
#include
-//#define DEBUG
-//#define DEBUG1
-//#define DEBUG2
-//#define DEBUG_SURF
-//#define DEBUG_DIST
-//#define DEBUG_REFINE
+// #define DEBUG
+// #define DEBUG1
+// #define DEBUG2
+// #define DEBUG_SURF
+// #define DEBUG_DIST
+// #define DEBUG_REFINE
using std::vector;
using std::set;
@@ -526,6 +526,7 @@ void LRSurfApprox::getClassifiedPts(vector& outliers, int& nmb_outliers,
#endif
// Compute accuracy in data points
+ int dim = srf_->dimension();
if (omp_for_elements)
computeAccuracy_omp(ghost_elems);
else
@@ -549,7 +550,6 @@ void LRSurfApprox::getClassifiedPts(vector& outliers, int& nmb_outliers,
#ifdef DEBUG_DIST
std::ofstream r_out("residual0.txt");
- int dim = srf_->dimension();
int del2 = dim + 3; // Parameter pair, point and distance
for (LRSplineSurface::ElementMap::const_iterator it=srf_->elementsBegin();
it != srf_->elementsEnd(); ++it)
@@ -584,7 +584,6 @@ void LRSurfApprox::getClassifiedPts(vector& outliers, int& nmb_outliers,
{
vector residual;
residual.reserve(points_.size()+sign_points_.size());
- int dim = srf_->dimension();
int del2 = dim + 3; // Parameter pair, point and distance
for (LRSplineSurface::ElementMap::const_iterator it=srf_->elementsBegin();
it != srf_->elementsEnd(); ++it)
@@ -722,7 +721,6 @@ void LRSurfApprox::getClassifiedPts(vector& outliers, int& nmb_outliers,
std::ofstream of3("point_clouds.g2");
// distance between surface and point
- int dim = srf_->dimension();
for (LRSplineSurface::ElementMap::const_iterator it=srf_->elementsBegin();
it != srf_->elementsEnd(); ++it)
{
@@ -796,17 +794,18 @@ void LRSurfApprox::getClassifiedPts(vector& outliers, int& nmb_outliers,
// Update surface
if (useMBA_ || ki >= toMBA_)
{
- //#ifdef DEBUG
+ #ifdef DEBUG
std::cout << "Using MBA" << std::endl;
- //#endif
+ #endif
runMBAUpdate(true);
}
else
{
- //#ifdef DEBUG
+ #ifdef DEBUG
std::cout << "Using LS" << std::endl;
- //#endif
+ #endif
try {
+ LSapprox.setInitSf(srf_, coef_known_);
LSapprox.updateLocals();
performSmooth(&LSapprox);
if (has_min_constraint_ || has_max_constraint_ || has_local_constraint_)
@@ -966,7 +965,6 @@ void LRSurfApprox::getClassifiedPts(vector& outliers, int& nmb_outliers,
std::string ver = std::to_string(ki+1);
std::string outfile = body + ver + extension;
std::ofstream r_out2(outfile.c_str());
- int dim = srf_->dimension();
int del2 = dim + 3; // Parameter pair, point and distance
for (LRSplineSurface::ElementMap::const_iterator it=srf_->elementsBegin();
it != srf_->elementsEnd(); ++it)
@@ -1000,7 +998,6 @@ void LRSurfApprox::getClassifiedPts(vector& outliers, int& nmb_outliers,
{
vector residual;
residual.reserve(points_.size()+sign_points_.size());
- int dim = srf_->dimension();
int del2 = dim + 3; // Parameter pair, point and distance
for (LRSplineSurface::ElementMap::const_iterator it=srf_->elementsBegin();
it != srf_->elementsEnd(); ++it)
@@ -1147,6 +1144,10 @@ void LRSurfApprox::performSmooth(LRSurfSmoothLS *LSapprox)
//std::cout << "Smoothing weight: " << smoothweight_ << std::endl;
double wgt1 = 0.0;//0.8*smoothweight_;
double wgt3 = 0.8*smoothweight_;//0.0; //0.1*smoothweight_; //0.9*smoothweight_; // 0.5*smoothweight_;
+ int deg1 = srf_->degree(XFIXED);
+ int deg2 = srf_->degree(YFIXED);
+ if (std::min(deg1,deg2) < 3)
+ wgt3 = 0.0;
double wgt2 = (1.0 - wgt3 -wgt1)*smoothweight_;
double fac = 100.0;
@@ -1157,7 +1158,7 @@ void LRSurfApprox::performSmooth(LRSurfSmoothLS *LSapprox)
LSapprox->smoothBoundary(fac*wgt1, fac*wgt2, fac*wgt3);
double approx_weight = 1.0-wgt1-wgt2-wgt3;
- const bool use_omp = true;
+ const bool use_omp = false; //true;
if (use_omp)
{
LSapprox->setLeastSquares_omp(approx_weight, significant_fac_);
@@ -1240,7 +1241,6 @@ void LRSurfApprox::computeAccuracy(vector& ghost_elems)
#endif
RectDomain rd = srf_->containingDomain();
- int dim = srf_->dimension();
LRSplineSurface::ElementMap::const_iterator it;
int num = srf_->numElements();
@@ -1269,6 +1269,7 @@ void LRSurfApprox::computeAccuracy(vector& ghost_elems)
vector& ghost_points = it->second->getGhostPoints();
int nmb_pts = it->second->nmbDataPoints();
int nmb_ghost = it->second->nmbGhostPoints();
+ int dim = srf_->dimension();
int del = it->second->getNmbValPrPoint();
if (del == 0)
del = dim+3; // Parameter pair, point and distance
diff --git a/lrsplines2D/src/LRSurfSmoothLS.C b/lrsplines2D/src/LRSurfSmoothLS.C
index e5e62bf7..929f03d9 100644
--- a/lrsplines2D/src/LRSurfSmoothLS.C
+++ b/lrsplines2D/src/LRSurfSmoothLS.C
@@ -1359,8 +1359,9 @@ void LRSurfSmoothLS::computeDer1LineIntegrals(const vector& bsplin
if (coef_fixed)
{
// Add contribution to the right side of the equation system
+ Point coef = bsplines[kj]->Coef();
for (int kk=0; kk& bsplin
if (coef_fixed)
{
// Add contribution to the right side of the equation system
+ Point coef = bsplines[kj]->Coef();
for (int kk=0; kk& bsplin
if (coef_fixed)
{
// Add contribution to the right side of the equation system
+ Point coef = bsplines[kj]->Coef();
for (int kk=0; kk LinDepUtils::fetchUnpeelable( const LRSplineSurface& surf,
+ int minnmb)
+//============================================================================
+{
+ vector fun;
+
+ // Initialize elements
+ bool overload = false;
+ int nmb_el_init = 0;
+ int expected_nmb = (surf.degree(XFIXED)+1)*(surf.degree(YFIXED)+1);
+ for (auto it1=surf.elementsBegin(); it1!=surf.elementsEnd(); ++it1)
+ {
+ bool found = it1->second->initOverload(expected_nmb);
+ if (found)
+ {
+ overload = true;
+ nmb_el_init++;
+ }
+ }
+
+ if (!overload)
+ return fun;
+
+ // Initialize Bsplines
+ overload = false;
+ int nmb_bspl_init = 0;
+ for (auto it2=surf.basisFunctionsBegin(); it2!=surf.basisFunctionsEnd(); ++it2)
+ {
+ bool found = it2->second->checkOverload();
+ if (found)
+ {
+ overload = true;
+ nmb_bspl_init++;
+ }
+ }
+
+ if (!overload)
+ return fun;
+
+#ifdef DEBUG
+ std::ofstream of1("overload_cand2_0.g2");
+ for (auto it2=surf.basisFunctionsBegin(); it2!=surf.basisFunctionsEnd(); ++it2)
+ {
+ bool curr = it2->second->getOverload();
+ if (curr)
+ {
+ std::cout << it2->second.get() << std::endl;
+ LRBSpline2D *cand = it2->second.get();
+ of1 << "410 1 0 4 255 0 0 255" << std::endl;
+ of1 << "4" << std::endl;
+ of1 << cand>umin() << " " << cand>vmin() << " 0 ";
+ of1 << cand>umax() << " " << cand>vmin() << " 0" << std::endl;
+ of1 << cand>umin() << " " << cand>vmin() << " 0 ";
+ of1 << cand>umin() << " " << cand>vmax() << " 0" << std::endl;
+ of1 << cand>umax() << " " << cand>vmin() << " 0 ";
+ of1 << cand>umax() << " " << cand>vmax() << " 0" << std::endl;
+ of1 << cand>umin() << " " << cand>vmax() << " 0 ";
+ of1 << cand>umax() << " " << cand>vmax() << " 0" << std::endl;
+ }
+ }
+ std::cout << std::endl;
+ writeg2Mesh(surf, of1);
+#endif
+
+ bool changed = true;
+ while (changed)
+ {
+ changed = false;
+
+ // Reset element flag
+ overload = false;
+ for (auto it1=surf.elementsBegin(); it1!=surf.elementsEnd(); ++it1)
+ {
+ bool curr = it1->second->getOverload();
+ if (curr)
+ {
+ bool found = it1->second->resetOverload();
+ if (found)
+ overload = true;
+ if (curr != found)
+ changed = true;
+ }
+ }
+
+ // if (!overload)
+ // break;
+ // if (!changed)
+ // break;
+
+ // // Reset Bspline flag
+ // overload = false;
+ // for (auto it2=surf.basisFunctionsBegin(); it2!=surf.basisFunctionsEnd(); ++it2)
+ // {
+ // bool curr = it2->second->getOverload();
+ // if (curr)
+ // {
+ // bool found = it2->second->checkOverload();
+ // if (found)
+ // overload = true;
+ // if (curr != found)
+ // changed = true;
+ // }
+ // }
+ }
+
+#ifdef DEBUG
+ std::ofstream of2("overload_cand2_1.g2");
+ for (auto it2=surf.basisFunctionsBegin(); it2!=surf.basisFunctionsEnd(); ++it2)
+ {
+ bool curr = it2->second->getOverload();
+ if (curr)
+ {
+ std::cout << it2->second.get() << std::endl;
+ LRBSpline2D *cand = it2->second.get();
+ of2 << "410 1 0 4 255 0 0 255" << std::endl;
+ of2 << "4" << std::endl;
+ of2 << cand>umin() << " " << cand>vmin() << " 0 ";
+ of2 << cand>umax() << " " << cand>vmin() << " 0" << std::endl;
+ of2 << cand>umin() << " " << cand>vmin() << " 0 ";
+ of2 << cand>umin() << " " << cand>vmax() << " 0" << std::endl;
+ of2 << cand>umax() << " " << cand>vmin() << " 0 ";
+ of2 << cand>umax() << " " << cand>vmax() << " 0" << std::endl;
+ of2 << cand>umin() << " " << cand>vmax() << " 0 ";
+ of2 << cand>umax() << " " << cand>vmax() << " 0" << std::endl;
+ }
+ }
+ std::cout << std::endl;
+ writeg2Mesh(surf, of2);
+#endif
+
+ if (!overload)
+ return fun;
+
+ int nmb = 0;
+ for (auto it2=surf.basisFunctionsBegin(); it2!=surf.basisFunctionsEnd(); ++it2)
+ {
+ bool curr = it2->second->getOverload();
+ if (curr)
+ ++nmb;
+ }
+#ifdef DEBUG
+ std::cout << "Nmb overloaded pre meshrec: " << nmb << std::endl;
+#endif
+
+ overload = (nmb >= minnmb) ? overloadedMeshRectangles(surf) : false;
+
+ if (overload)
+ {
+ // Collect overloaded Bsplines
+ for (auto it2=surf.basisFunctionsBegin(); it2!=surf.basisFunctionsEnd(); ++it2)
+ {
+ bool curr = it2->second->getOverload();
+ if (curr)
+ fun.push_back(it2->second.get());
+ }
+ }
+
+ // Reset flags
+ for (auto it1=surf.elementsBegin(); it1!=surf.elementsEnd(); ++it1)
+ it1->second->eraseOverload();
+ for (auto it2=surf.basisFunctionsBegin(); it2!=surf.basisFunctionsEnd(); ++it2)
+ it2->second->eraseOverload();
+
+ return fun;
+}
+
+
+//==============================================================================
+// Check if identified overloaded B-splines have overloaded mesh rectangles.
+//
+bool LinDepUtils::overloadedMeshRectangles(const LRSplineSurface& surf)
+//==============================================================================
+{
+#ifdef DEBUG
+ std::cout << "Overloaded mesh rectangles, start." << std::endl;
+#endif
+ Direction2D ds[2] = {XFIXED, YFIXED};
+ const vector DirSeq(ds,ds+2);
+ MeshRectangleIndexMap meshrectangles;
+ vector > bspl;
+ int numbspl = 0;
+ vector overload;
+ for (auto it2=surf.basisFunctionsBegin(); it2!=surf.basisFunctionsEnd(); ++it2)
+ {
+ bool curr = it2->second->getOverload();
+ if (!curr)
+ continue;
+
+ numbspl++;
+ overload.push_back(it2->second.get());
+
+ // Collect associated mesh rectangles
+ map > kvec;
+ map > kmul;
+ map > kall;
+ for (vector::const_iterator ixy=DirSeq.begin();
+ ixy!=DirSeq.end(); ++ixy) {
+ vector kvec_all = it2->second->kvec(*ixy);
+ kvec[*ixy] = kvec_all;
+ vector::const_iterator it = unique( kvec[*ixy].begin(), kvec[*ixy].end() );
+ kvec[*ixy].resize( it - kvec[*ixy].begin() );
+ kmul[*ixy].resize( kvec[*ixy].size() );
+ for ( vector::iterator it_mu=kmul[*ixy].begin(), it_uk=kvec[*ixy].begin();
+ (it_mu!=kmul[*ixy].end() && it_uk!=kvec[*ixy].end());
+ ++it_mu, ++it_uk) {
+ *it_mu = (int) count(kvec_all.begin(), kvec_all.end(), *it_uk) - 1; // Note: we ensure zero-based multiplicity.
+ }
+ int kmin = kvec[*ixy].front();
+ int kmax = kvec[*ixy].back();
+ kall[*ixy].resize( kmax - kmin ); // Note: we exclude the last knot index.
+ int kv = kmin;
+ for (vector::iterator it_al=kall[*ixy].begin();
+ it_al!=kall[*ixy].end(); ++it_al)
+ *it_al = kv++;
+ }
+
+ // Using the above information for this B-spline, we proceed
+ // to update the MeshPart/column-wise storage of the
+ // incidence matrix.
+ for (vector::const_iterator
+ ixy=DirSeq.begin(); ixy!=DirSeq.end(); ++ixy)
+ { // Loop: over directions
+ // When doing mesh rectangles in a given Direction2D, we must
+ // loop first over the (p+2) knot indices of the B-spline in
+ // that Direction2D, and then for each of these loop over ALL
+ // but the last knot indices spanned by the B-spline.
+ vector KV = (*ixy==YFIXED) ? kvec[YFIXED] : kall[YFIXED];
+ vector KU = (*ixy==XFIXED) ? kvec[XFIXED] : kall[XFIXED];
+ for (unsigned int ikv=0; ikv!=KV.size(); ++ikv)
+ { // Loop: over v-knots
+ for (unsigned int iku=0; iku!=KU.size(); ++iku)
+ {// Loop over u-knots
+ int nmb = kmul[*ixy][(*ixy==XFIXED) ? iku : ikv];
+ for (int nu=0; nu<=nmb; ++nu)
+ { // Loop: over multiplicity
+ MeshRectangle tmprec;
+ tmprec.dir = *ixy;
+ tmprec.vmin = KV[ikv];
+ tmprec.umin = KU[iku];
+ tmprec.mult = nu;
+
+ // Check if the mesh rectangle exists already
+ auto it = meshrectangles.find(tmprec);
+ if (it == meshrectangles.end())
+ {
+ // Insert new meshrectangle
+ meshrectangles[tmprec] = bspl.size();
+ vector tmp;
+ tmp.push_back(overload.size()-1);
+ bspl.push_back(tmp);
+ }
+ else
+ {
+ bspl[it->second].push_back(overload.size()-1);
+ }
+ }
+ }
+ }
+ }
+ }
+
+#ifdef DEBUG
+ std::cout << "Overloaded mesh rectangles, middle. Found: " << numbspl << std::endl;
+#endif
+ // Remove mesh rectangles that contain less than two overloaded B-splines
+ // and reset the overload flag for associated B-splines
+ bool changed = true;
+ vector on(bspl.size(), true);
+ vector num(bspl.size());
+ for (size_t ki=0; kieraseOverload();
+ }
+ changed = true;
+ on[ki] = false;
+ -num2;
+ }
+ }
+ }
+#ifdef DEBUG
+ std::cout << std::endl << "Overloaded mesh rectangles, finish" << std::endl;
+#endif
+ return (bspl.size() > 0);
+}
+
+//==============================================================================
+// Given a set of non-peelable B-splines, check if they can be combined in
+// linear dependence relations
+//
+void LinDepUtils::checkOverloaded(int minNmb, vector& funs,
+ vector >& lindep)
+//==============================================================================
+{
+ // Check input
+ size_t nmb_funs = funs.size();
+
+ if (funs.size() < minNmb)
+ return;
+
+#ifdef DEBUG
+ std::ofstream of("overloaded.g2");
+ for (size_t ki=0; kiumin() << " " << funs[ki]->vmin() << " 0 ";
+ of << funs[ki]->umax() << " " << funs[ki]->vmin() << " 0" << std::endl;
+ of << funs[ki]->umin() << " " << funs[ki]->vmin() << " 0 ";
+ of << funs[ki]->umin() << " " << funs[ki]->vmax() << " 0" << std::endl;
+ of << funs[ki]->umax() << " " << funs[ki]->vmin() << " 0 ";
+ of << funs[ki]->umax() << " " << funs[ki]->vmax() << " 0" << std::endl;
+ of << funs[ki]->umin() << " " << funs[ki]->vmax() << " 0 ";
+ of << funs[ki]->umax() << " " << funs[ki]->vmax() << " 0" << std::endl;
+ }
+#endif
+ for (size_t ki=0; ki inside;
+ inside.push_back(funs[ki]);
+ for (auto it1=funs[ki]->supportedElementBegin();
+ it1!=funs[ki]->supportedElementEnd(); ++it1)
+ {
+ for (auto it2=(*it1)->supportBegin(); it2!=(*it1)->supportEnd(); ++it2)
+ {
+ if (*it2 == funs[ki])
+ continue;
+ if (funs[ki]->covers(*it2))
+ {
+ // Check for overload
+ for (kh=0; kh= minNmb)
+ lindep.push_back(inside);
+ }
+
+ // Remove internal cases
+ for (size_t kr=0; krumin() << " " << lindep[kj][0]->umax() << " ";
+ std::cout << lindep[kj][0]->vmin() << " " << lindep[kj][0]->vmax() << std::endl;
+ }
+#endif
+}
+
diff --git a/lrsplines3D/CMakeLists.txt b/lrsplines3D/CMakeLists.txt
index ec5e227e..52ea62da 100644
--- a/lrsplines3D/CMakeLists.txt
+++ b/lrsplines3D/CMakeLists.txt
@@ -137,6 +137,9 @@ ENDIF()
# Create a tmp directory.
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tmp)
+# Create the output data directory for the examples.
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/data)
+
# === Install and Export CMake Config Package ===
include(CMakePackageConfigHelpers)
diff --git a/lrsplines3D/Doxyfile b/lrsplines3D/Doxyfile
new file mode 100644
index 00000000..aa6bbe3a
--- /dev/null
+++ b/lrsplines3D/Doxyfile
@@ -0,0 +1,1363 @@
+# Doxyfile 1.5.5
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = "GoTools LRspline3D"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 1.0
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
+# and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH = include
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command , where is the value of
+# the FILE_VERSION_FILTER tag, and is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = .
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.C \
+ *.c \
+ *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = ../ttl/doc/images \
+ doc/images
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command , where
+# is the value of the INPUT_FILTER tag, and is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT =
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT =
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = YES
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT =
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is enabled by default, which results in a transparent
+# background. Warning: Depending on the platform used, enabling this option
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
+# become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+EXTRA_PACKAGES = mathtools amsmath
+USE_MATHJAX = YES
+MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_HTMLorMML #../../../../programs/node_modules/mathjax
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/lrsplines3D/examples/Bezier_extraction.C b/lrsplines3D/examples/Bezier_extraction.C
new file mode 100644
index 00000000..ce3f5e61
--- /dev/null
+++ b/lrsplines3D/examples/Bezier_extraction.C
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
+ * Applied Mathematics, Norway.
+ *
+ * Contact information: E-mail: tor.dokken@sintef.no
+ * SINTEF ICT, Department of Applied Mathematics,
+ * P.O. Box 124 Blindern,
+ * 0314 Oslo, Norway.
+ *
+ * This file is part of GoTools.
+ *
+ * GoTools is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * GoTools is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with GoTools. If not, see
+ * .
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines3D/LRSplineVolume.h"
+#include "GoTools/lrsplines3D/LRSpline3DBezierCoefs.h"
+#include "GoTools/geometry/ObjectHeader.h"
+#include "GoTools/trivariate/SplineVolume.h"
+#include
+#include
+#include
+
+using namespace Go;
+using namespace std;
+
+//===========================================================================
+//
+/// Description:
+/// Read LR spline volume from file.
+/// Input to the example is a volume constructed in the example
+/// program refine_lrvol.
+/// Extract coefficients of Bezier patches.
+/// Each patch is extended with knot vectors to be applicable for the g2-format
+/// and written to file. The output can be visualized with
+/// gotools/viewlib/app/goview_vol_and_lr.
+//
+//===========================================================================
+
+int main(int argc, char *argv[])
+{
+ // Output file
+ std::string outfile("data/Bezier_patches.g2");
+ std::ofstream of(outfile);
+
+ // Read LR B-spline volume from file
+ std::string infile("data/lrvol_fin.g2"); // Input file name
+ std::cout << "\nAttempting to read LRSplineVolume from file: " << infile << std::endl;
+
+ std::unique_ptr vol(new LRSplineVolume());
+
+ // Specific file reading and volume creation.
+ // In GoTools, you can use a factory or a specific reader method:
+ std::ifstream input_stream(infile.c_str());
+ if (!input_stream.is_open()) {
+ std::cerr << "Error: Could not open file " << infile << std::endl;
+ return 1;
+ }
+
+ // Read header specifying the type of geometry entity
+ // The function throws if the entity header is invalid
+ ObjectHeader header;
+ try {
+ header.read(input_stream);
+ }
+ catch (...)
+ {
+ std::cerr << "Exiting" << std::endl;
+ exit(-1);
+ }
+
+ try {
+ vol->read(input_stream);
+ } catch (const std::exception& e) {
+ std::cerr << "Error reading LRSplineVolume: " << e.what() << std::endl;
+ return 1;
+ }
+
+ // Compute Bezier coefficients. The coefficients are stored in within bez
+ LRSpline3DBezierCoefs bez(*vol);
+ bez.getBezierCoefs();
+
+ std::cout << "Finished converting volume " << std::endl;
+
+ // Fetch information about Bezier patches
+ int num = bez.numPatches();
+ int dim = bez.dimension(); // Dimension of geometry space
+ int deg1 = bez.degree(0); // Polynomial degree in 1. parameter direction
+ int deg2 = bez.degree(1);
+ int deg3 = bez.degree(2);
+ std::cout << "Number of patches: " << num << std::endl;
+ std::cout << "Dimension of geometry space: " << dim << std::endl;
+ std::cout << "Polynomial degrees: " << deg1 << ", " << deg2 << ", " << deg3 << std::endl;
+
+ vector coefs; // Bezier coefficents for all patches. Each patch has
+ // dim*(deg1+1)*(deg2+1)*(deg3+1) coeffients
+ bez.BezierCoefficients(coefs);
+
+ // For each Bezier patch, construct tensor-product spline volume and write to file
+ // First define knot vectors
+ vector knots1(2*(deg1+1), 0.0);
+ vector knots2(2*(deg2+1), 0.0);
+ vector knots3(2*(deg3+1), 0.0);
+ for (int ki=0; ki<=deg1; ++ki)
+ knots1[deg1+1+ki] = 1.0;
+ for (int ki=0; ki<=deg2; ++ki)
+ knots2[deg2+1+ki] = 1.0;
+ for (int ki=0; ki<=deg3; ++ki)
+ knots3[deg3+1+ki] = 1.0;
+
+ int n_coef = dim*(deg1+1)*(deg2+1)*(deg3+1);
+ for (int ki=0; ki tpvol(new SplineVolume(deg1+1, deg2+1, deg3+1,
+ deg1+1, deg2+1, deg3+1,
+ &knots1[0], &knots2[0], &knots3[0],
+ &coefs[ki*n_coef], dim));
+
+ // Write volume to file
+ tpvol->writeStandardHeader(of);
+ tpvol->write(of);
+ }
+
+ // One patch
+ int ix = num/2;
+ vector coefs2;
+ bez.BezierCoefficientsOfPatch(ix, coefs2);
+ std::cout << "Bezier coefficients of patch number (starting count from zero): " << ix << ":" << std::endl;
+ for (int ka=0; ka<(int)coefs2.size(); ka+=dim)
+ {
+ for (int kb=0; kb.
+ *
+ * In accordance with Section 7(b) of the GNU Affero General Public
+ * License, a covered work must retain the producer line in every data
+ * file that is created or manipulated using GoTools.
+ *
+ * Other Usage
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial activities involving the GoTools library without
+ * disclosing the source code of your own applications.
+ *
+ * This file may be used in accordance with the terms contained in a
+ * written agreement between you and SINTEF ICT.
+ */
+
+#include "GoTools/lrsplines3D/LRSplineVolume.h"
+#include "GoTools/lrsplines3D/LRSpline3DUtils.h"
+#include "GoTools/lrsplines3D/Element3D.h" // Not really needed as it is
+// included in LRSplineVolume.h
+#include "GoTools/lrsplines3D/LRBSpline3D.h" // As for Element3D
+#include "GoTools/geometry/PointCloud.h"
+#include "GoTools/geometry/ObjectHeader.h"
+#include
+
+using namespace Go;
+using std::vector;
+
+//===========================================================================
+//
+/// Description:
+/// Demonstrates the various evaluation possibilities for an LR spline volume
+///
+/// Input to the example is the volume constructed in the example
+/// program refine_lrvol.
+/// Evaluation results are written to standard output.
+/// Result of grid evaluation is written to data/grid_on_vol.g and grie
+/// evaluation for one element is written to the file data/grid_on_elem.g2.
+//
+//===========================================================================
+
+int main(int argc, char *argv[])
+{
+ // Read LR B-spline volume from file
+ std::string infile("data/lrvol_fin.g2");
+ std::ifstream input(infile.c_str());
+
+ // Prepare for output
+ std::string outfile("data/grid_on_vol.g2");
+ std::ofstream of(outfile.c_str());
+ std::string outfile2("data/grid_on_elem.g2");
+ std::ofstream of2(outfile2.c_str());
+
+ // Read header specifying the type of geometry entity
+ ObjectHeader header;
+ try {
+ header.read(input);
+ }
+ catch (...)
+ {
+ std::cerr << "File empty or corrupt. Exiting" << std::endl;
+ exit(-1);
+ }
+
+ // The following assumes that the specified file contains an LR spline
+ // volume
+ // Create empty volume
+ shared_ptr vol(new LRSplineVolume());
+ vol->read(input);
+ if (!vol.get())
+ {
+ std::cerr << "The file contains no LR B-spline volume" << std::endl;
+ exit(-1);
+ }
+
+ // Dimension of geometry space
+ int dim = vol->dimension();
+
+ // Fetch parameter domain of volume
+ double umin = vol->paramMin(XDIR); // First parameter direction
+ double umax = vol->paramMax(XDIR); // First parameter direction
+ double vmin = vol->paramMin(YDIR); // Second parameter direction
+ double vmax = vol->paramMax(YDIR); // Second parameter direction
+ double wmin = vol->paramMin(ZDIR); // Third parameter direction
+ double wmax = vol->paramMax(ZDIR); // Third parameter direction
+
+ // Alternative enquiry
+ double umin2 = vol->startparam_u();
+ double umax2 = vol->endparam_u();
+ double vmin2 = vol->startparam_v();
+ double vmax2 = vol->endparam_v();
+ double wmin2 = vol->startparam_w();
+ double wmax2 = vol->endparam_w();
+
+ // Parameter in which to evaluate
+ double upar = 0.3*umin + 0.7*umax;
+ double vpar = 0.5*(vmin + vmax);
+ double wpar = 0.55*wmin + 0.45*wmax;
+ std::cout << "Parameter tripple in which to evaluate: " << upar << ", " << vpar;
+ std::cout << ", " << wpar << std::endl;
+
+ // Evaluate without information of the element in which the parameter is
+ // situated
+ // Only position
+ Point pos1;
+ vol->point(pos1, upar, vpar, wpar);
+ std::cout << "Position: " << pos1 << std::endl;
+
+ // Position and first derivatives
+ // Given the volume S, the sequence is: S, Su, Sv, and Sw. If more derivatives
+ // are requested the sequence continues: Suu, Suv, Suw, Svv, Svw, Sww, ...
+ vector pts1(4);
+ int no_derivs = 1; // Number of derivatives to evaluate, = 0 means only
+ // position
+ bool upar_from_right = true; // False only if the parameter is placed
+ // at the upper boundary in the first parameter direction
+ bool vpar_from_right = true; // False only if the parameter is placed
+ // at the upper boundary in the second parameter direction
+ bool wpar_from_right = true; // False only if the parameter is placed
+ // at the upper boundary in the third parameter direction
+ vol->point(pts1, upar, vpar, wpar, no_derivs, upar_from_right, vpar_from_right,
+ wpar_from_right);
+ std::cout << "Position and first derivatives: " << pts1[0] << std::endl;
+ std::cout << pts1[1] << std::endl;
+ std::cout << pts1[2] << std::endl;
+ std::cout << pts1[3] << std::endl;
+
+ // If the element corresponding to the parameter tripple is known
+ // Identify element. Note that this call may be time consuming if the
+ // volume is large. If more than one evaluation is performed, the
+ // positioning of the previous parameter pair will be used to speed up
+ // the search of the current
+ Element3D *elem = vol->coveringElement(upar, vpar, wpar);
+
+ // Only position
+ Point pos2;
+ vol->point(pos2, upar, vpar, wpar, elem);
+
+ vector pts2(4);
+ vol->point(pts2, upar, vpar, wpar, no_derivs, elem, upar_from_right,
+ vpar_from_right, wpar_from_right);
+
+ // Fetch all Bsplines with the specified elemnt in its support
+ const vector