29 : m_g1(&(mp[bi.first().patch])), m_g2(&(mp[bi.second().patch])),
30 m_b1(&(basis[bi.first().patch])), m_b2(&(basis[bi.second().patch])),
32 m_isMatching(true), m_isAffine(true),
33 m_equalityTolerance(opt.getReal(
"EqualityTolerance")), m_newtonTolerance(opt.getReal(
"NewtonTolerance"))
36 const index_t numSamplePoints = opt.
getInt(
"NumSamplePoints");
37 const index_t intervalsOfFittingCurve = opt.
getInt(
"IntervalsOfFittingCurve");
38 const index_t degreeOfFittingCurve = opt.
getInt(
"DegreeOfFittingCurve");
55 "gsRemapInterface: Parameter checkAffine has invalid value:" << checkAffine );
58 else if (checkAffine > 0)
64 "gsRemapInterface: Can handle non-affine interfaces only for 2 dimensions." );
87 lower[i] = upper[i] = pr( i, s.
parameter() );
88 numberGridPoints[i] = 1;
94 numberGridPoints[i] = 2;
101 void transferCorners(
const gsMatrix<T> &corners,
const gsGeometry<T> &g1,
const gsGeometry<T> &g2,
102 const T newtonTolerance,
const T equalityTolerance, gsMatrix<T> &cornerstransferred, gsVector<bool> &converged)
104 cornerstransferred.resize(corners.rows(), corners.cols());
105 converged.resize(corners.cols());
107 gsVector<T> cornerTransferred = g2.parameterRange().col(0);
108 for (
index_t i=0; i<corners.cols(); ++i)
110 gsVector<T> cornerPhysical = g1.eval(corners.col(i));
111 g2.newtonRaphson(cornerPhysical, cornerTransferred,
true, newtonTolerance, 100);
112 cornerstransferred.col(i) = cornerTransferred;
113 converged[i] = (cornerPhysical - g2.eval(cornerTransferred)).norm() < equalityTolerance;
117 template <
class Vector,
class T>
118 void widenParameterBounds(
const Vector &point, gsMatrix<T> ¶meterBounds)
120 if (parameterBounds.cols()==0)
122 parameterBounds.resize(point.rows(),2);
123 parameterBounds.col(0) = point;
124 parameterBounds.col(1) = point;
128 for (
index_t i=0; i<parameterBounds.rows(); ++i)
130 parameterBounds(i,0) = std::min( parameterBounds(i,0), point(i,0) );
131 parameterBounds(i,1) = std::max( parameterBounds(i,1), point(i,0) );
142 gsMatrix<T> corners1 = determineCorners(*m_g1,m_bi.first());
143 gsMatrix<T> corners2 = determineCorners(*m_g2,m_bi.second());
147 gsMatrix<T> corners1transferredTo2, corners2transferredTo1;
149 transferCorners(corners1, *m_g1, *m_g2, m_newtonTolerance, m_equalityTolerance, corners1transferredTo2, converged1);
150 transferCorners(corners2, *m_g2, *m_g1, m_newtonTolerance, m_equalityTolerance, corners2transferredTo1, converged2);
155 for (
index_t i=0; i<corners1.cols(); ++i)
159 widenParameterBounds(corners1.col(i), m_parameterBounds1);
160 widenParameterBounds(corners1transferredTo2.col(i), m_parameterBounds2);
164 m_isMatching =
false;
168 for (
index_t i=0; i<corners2.cols(); ++i)
172 widenParameterBounds(corners2.col(i), m_parameterBounds2);
173 widenParameterBounds(corners2transferredTo1.col(i), m_parameterBounds1);
177 m_isMatching =
false;
182 const index_t d1 = m_bi.first().direction();
183 m_parameterBounds1.row(d1).setConstant(m_g1->parameterRange()(d1,m_bi.first().parameter()));
185 const index_t d2 = m_bi.second().direction();
186 m_parameterBounds2.row(d2).setConstant(m_g2->parameterRange()(d2,m_bi.second().parameter()));
188 GISMO_ASSERT ( m_parameterBounds1.cols()&&m_parameterBounds2.cols(),
189 "gsRemapInterface<T>::constructInterfaceBox: Could not find an interface.");
190 for (
index_t j=0; j<domainDim(); ++j)
192 GISMO_ASSERT ( j==m_bi.first().direction() ||m_parameterBounds1(j,0) < m_parameterBounds1(j,1),
193 "gsRemapInterface<T>::constructInterfaceBox: Could not find an interface.");
194 GISMO_ASSERT ( j==m_bi.second().direction()||m_parameterBounds2(j,0) < m_parameterBounds2(j,1),
195 "gsRemapInterface<T>::constructInterfaceBox: Could not find an interface.");
206 numberGridPoints[m_bi.first().direction()] = 1;
209 eval_into(points1, points2);
215 ).
template lpNorm<gsEigen::Infinity>();
229 result.resize(dim, u.cols());
233 result.row(i).setConstant( parameterBounds(i,0) );
243 const index_t intervalsOfFittingCurve,
244 const index_t degreeOfFittingCurve)
248 const short_t direction1 = m_bi.first().direction();
251 const short_t tangential1 = ! direction1;
254 const bool flipSide2 = (m_bi.dirOrientation()(tangential1) == 0);
258 numPoints[direction1] = 1;
270 gsVector<T> pointMapped = m_parameterBounds2.col(flipSide2 ? 1 : 0);
271 for (
index_t i = 0; i < numSamplePoints; ++i)
273 m_g2->newtonRaphson(physPoints.col(i), pointMapped,
true, m_newtonTolerance, 100);
274 GISMO_ASSERT ( (physPoints.col(i)-m_g2->eval(pointMapped)).norm() <= m_equalityTolerance,
275 "gsRemapInterface<T>::constructFittingCurve: Newton did not converge." );
276 B.row(i) = pointMapped.transpose();
280 gsKnotVector<T> KV(m_parameterBounds1(tangential1, 0), m_parameterBounds1(tangential1, 1),
281 intervalsOfFittingCurve, degreeOfFittingCurve+1);
285 m_intfMap = fit.curve().clone();
291 template <
class T,
class Vector>
292 inline void addBreaks(std::vector< std::vector<T> > & breaks,
294 const Vector & point,
295 const T equalityTolerance)
297 const index_t dim = point.rows();
300 const T t = point(d,0);
301 if ( parameterBounds(d,0) <= t && t <= parameterBounds(d,1) )
304 typename std::vector<T>::iterator pos = std::lower_bound(breaks[d].begin(), breaks[d].end(), t-equalityTolerance );
305 if ( pos == breaks[d].end() || *pos > t+equalityTolerance )
306 breaks[d].insert(pos, t);
311 template <
class T,
class Vector>
312 inline bool inRange(
const gsMatrix<T> & range,
313 const Vector & point)
315 for (
index_t i=0; i<range.rows(); ++i)
316 if ( point(i,0) < range(i,0) || point(i,0) > range(i,1) )
327 m_breakpoints.resize(domainDim());
329 const typename gsBasis<T>::domainIter domIt1 = m_b1->makeDomainIterator(m_bi.first());
330 addBreaks(m_breakpoints, m_parameterBounds1, m_parameterBounds1.col(0), m_equalityTolerance);
331 for (; domIt1->good(); domIt1->next())
332 addBreaks(m_breakpoints, m_parameterBounds1, domIt1->upperCorner(), m_equalityTolerance);
333 addBreaks(m_breakpoints, m_parameterBounds1, m_parameterBounds1.col(1), m_equalityTolerance);
335 const typename gsBasis<T>::domainIter domIt2 = m_b2->makeDomainIterator(m_bi.second());
338 gsAffineFunction<T> intfMap_inverse(m_bi.dirMap(m_bi.second()), m_bi.dirOrientation(m_bi.second()),
339 m_parameterBounds2, m_parameterBounds1);
341 for (; domIt2->good(); domIt2->next())
342 addBreaks(m_breakpoints, m_parameterBounds1, intfMap_inverse.
eval(domIt2->upperCorner()), m_equalityTolerance);
346 gsVector<T> breakpoint_transferred = m_parameterBounds1.col(0);
347 for (; domIt2->good(); domIt2->next())
349 if (inRange(m_parameterBounds2, domIt2->upperCorner()))
351 gsMatrix<T> breakpoint_phys = m_g2->eval(domIt2->upperCorner());
353 m_g1->newtonRaphson( breakpoint_phys, breakpoint_transferred,
true, m_newtonTolerance, 100 );
354 GISMO_ASSERT ( (breakpoint_phys-m_g1->eval(breakpoint_transferred)).norm() <= m_equalityTolerance,
355 "gsRemapInterface::constructBreaks: Newton method did not find point in parameter domain."
356 << (breakpoint_phys-m_g1->eval(breakpoint_transferred)).norm() );
358 addBreaks(m_breakpoints, m_parameterBounds1, breakpoint_transferred, m_equalityTolerance);
371 const T equalityTolerance)
373 for (
index_t r=0; r<u.rows(); ++r)
375 const T begin = parameterBounds(r, 0);
376 const T end = parameterBounds(r, 1);
377 for (
index_t c=0; c<u.cols(); ++c)
379 if ( u(r,c) < begin-equalityTolerance || u(r,c) > end+equalityTolerance )
389 void projectOntoInterface(gsMatrix<T> & u,
const gsMatrix<T> & parameterBounds)
391 for(
index_t r = 0; r < u.rows(); r++)
393 const T begin = parameterBounds(r, 0);
394 const T end = parameterBounds(r, 1);
396 for(
index_t c = 0; c < u.cols(); c++)
397 u(r,c) = std::min( std::max( u(r,c), begin ), end );
407 GISMO_ASSERT( u.rows() == domainDim(),
"gsRemapInterface::eval_into: "
408 "The rows of the evaluation points must be equal to the dimension of the domain." );
410 GISMO_ASSERT( checkIfOnInterface( u, m_parameterBounds1, m_equalityTolerance ),
411 "gsRemapInterface::eval_into: The incoming coefficients are not located on the interface."
412 <<
"\nu=\n"<<u<<
"\nm_parameterBounds1=\n"<<m_parameterBounds1);
416 m_intfMap->eval_into(u, result);
421 projectOntoInterface(uProjected, m_parameterBounds1);
424 const index_t direction1 = m_bi.first().direction();
425 const index_t tangential1 = ! direction1;
426 m_intfMap->eval_into(uProjected.row(tangential1),result);
428 projectOntoInterface(result, m_parameterBounds2);
437 for (
index_t i=0; i<domainDim(); ++i)
439 if (i!=m_bi.first().direction())
449 os <<
"gsRemapInterface:"
450 <<
"\n First side: " << m_bi.first()
451 <<
"\n Second side: " << m_bi.second()
452 <<
"\n Is Affine: " << ( m_isAffine ?
"yes" :
"no")
453 <<
"\n Is Matching: " << ( m_isMatching ?
"yes" :
"no")
454 <<
"\n Bounding box 1 min: " << m_parameterBounds1.transpose().row(0)
455 <<
"\n max: " << m_parameterBounds1.transpose().row(1)
456 <<
"\n Bounding box 2 min: " << m_parameterBounds2.transpose().row(0)
457 <<
"\n max: " << m_parameterBounds2.transpose().row(1);
459 for (
size_t i=0; i<m_breakpoints.size(); ++i)
461 os <<
"\n Beakpoints " << (i<3?char(
'x'+i):
' ') <<
": ";
462 if ( m_breakpoints[i].size() <= 10 )
464 for (
size_t j=0; j<m_breakpoints[i].size(); ++j)
465 os <<
" " << m_breakpoints[i][j];
469 for (
size_t j=0; j<5; ++j)
470 os <<
" " << m_breakpoints[i][j];
472 for (
size_t j=m_breakpoints[i].size()-5; j<m_breakpoints[i].size(); ++j)
473 os <<
" " << m_breakpoints[i][j];
477 os <<
"\n Fitting curve:\n" << *m_intfMap;
478 os <<
"\n Error of reparam: " << estimateReparamError(20);
boundaryInterface m_bi
Corresponding boundary interface.
Definition: gsRemapInterface.h:168
Abstract base class representing a geometry map.
Definition: gsGeometry.h:92
void constructBreaks()
Constructs the breakpoints m_breakpoints.
Definition: gsRemapInterface.hpp:325
gsMatrix< T > parameterRange() const
Returns the range of parameters as a matrix with two columns, [lower upper].
Definition: gsGeometry.hpp:198
void constructFittingCurve(index_t numSamplePoints, index_t intervalsOfFittingCurve, index_t degreeOfFittingCurve)
Constructs the fitting curve m_intfMap in the non-affine case.
Definition: gsRemapInterface.hpp:242
gsFunction< T >::Ptr m_intfMap
Iff affine, interface map, otherwise the fitting curve.
Definition: gsRemapInterface.h:175
#define short_t
Definition: gsConfig.h:35
bool parameter() const
Returns the parameter value (false=0=start, true=1=end) that corresponds to this side.
Definition: gsBoundary.h:128
virtual void eval_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Evaluates the interface map.
Definition: gsRemapInterface.hpp:405
gsMatrix< T > eval(const gsMatrix< T > &u) const
Evaluate the function,.
Definition: gsFunctionSet.hpp:120
#define index_t
Definition: gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
gsMatrix< T > m_parameterBounds1
The bounds of the box that represents .
Definition: gsRemapInterface.h:182
const index_t & getInt(const std::string &label) const
Reads value for option label from options.
Definition: gsOptionList.cpp:37
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
gsMatrix< T > m_parameterBounds2
The bounds of the box that represents .
Definition: gsRemapInterface.h:187
T m_equalityTolerance
Tolerance for considering points to be equal.
Definition: gsRemapInterface.h:189
memory::unique_ptr< gsDomainIterator > uPtr
Unique pointer for gsDomainIterator.
Definition: gsDomainIterator.h:73
void setBreaks(std::vector< T > newBreaks, index_t i)
Function to set the breakpoints in direction i manually.
Definition: gsTensorDomainBoundaryIterator.h:194
Representation of an affine function.
Definition: gsAffineFunction.h:29
Provides declaration of TensorNurbsBasis abstract interface.
Holds a set of patch-wise bases and their topology information.
Definition: gsMultiBasis.h:36
Provides declaration of the MultiPatch class.
Re-implements gsDomainIterator for iteration over all elements of the boundary of a tensor product pa...
Definition: gsTensorDomainBoundaryIterator.h:37
GISMO_DEPRECATED index_t direction(index_t s)
Returns the parametric direction that corresponds to side s.
Definition: gsBoundary.h:1048
gsMatrix< T > gsPointGrid(gsVector< T > const &a, gsVector< T > const &b, gsVector< unsigned > const &np)
Construct a Cartesian grid of uniform points in a hypercube, using np[i] points in direction i...
Definition: gsPointGrid.hpp:82
Class for performing a least squares fit to get a open/closed B-Spline curve for some given data...
Definition: gsCurveFitting.h:32
Fits a (closed) B-spline curve to some given data.
void compute()
computes the least squares fit for a (closed) B-spline curve
Definition: gsCurveFitting.h:100
T estimateReparamError(index_t steps) const
Estimates error between geometry1 and geometry2 after repearametrization on physical domain...
Definition: gsRemapInterface.hpp:201
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition: gsMultiPatch.h:33
Struct which represents a certain side of a box.
Definition: gsBoundary.h:84
virtual short_t domainDim() const
Returns parameter dimension of the domains.
Definition: gsRemapInterface.h:125
virtual std::ostream & print(std::ostream &os) const
Prints the state of the object.
Definition: gsRemapInterface.hpp:447
static uPtr make(const gsMatrix< T > mat, const gsVector< T > trans)
Affine maps are the composition of a linear map with a translation this constructor takes the two com...
Definition: gsAffineFunction.h:75
An std::vector with sorting capabilities.
Class for representing a knot vector.
Definition: gsKnotVector.h:79
void constructInterfaceBox()
Computes the box which represents the intersection of sides of incoming patches.
Definition: gsRemapInterface.hpp:140
Instructs constructor always to use an affine mapping.
Definition: gsRemapInterface.h:67
Struct which represents an interface between two patches.
Definition: gsBoundary.h:649
const gsGeometry< T > * m_g1
Geometry of first patch.
Definition: gsRemapInterface.h:162
Class which holds a list of parameters/options, and provides easy access to them. ...
Definition: gsOptionList.h:32
const gsGeometry< T > * m_g2
Geometry of second patch.
Definition: gsRemapInterface.h:163
gsDomainIterator< T >::uPtr makeDomainIterator() const
Returns a domain iterator.
Definition: gsRemapInterface.hpp:434
bool m_isAffine
True iff the interface is affine.
Definition: gsRemapInterface.h:171
gsRemapInterface(const gsMultiPatch< T > &mp, const gsMultiBasis< T > &mb, const boundaryInterface &bi, const gsOptionList &opt=defaultOptions())
Constructor.
Definition: gsRemapInterface.hpp:25
short_t direction() const
Returns the parametric direction orthogonal to this side.
Definition: gsBoundary.h:113
Instructs constructor not to use an affine mapping.
Definition: gsRemapInterface.h:66
patchSide & first()
first, returns the first patchSide of this interface
Definition: gsBoundary.h:776