1 /** @file gsGeometry.h 2 3 @brief Provides declaration of Geometry abstract interface. 4 5 This file is part of the G+Smo library. 6 7 This Source Code Form is subject to the terms of the Mozilla Public 8 License, v. 2.0. If a copy of the MPL was not distributed with this 9 file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 11 Author(s): A. Mantzaflaris 12 */ 13 14 #pragma once 15 16 #include <gsCore/gsFunction.h> 17 #include <gsCore/gsBoundary.h> 18 19 20 #define GISMO_BASIS_ACCESSORS \ 21 Basis & basis() { return static_cast<Basis&>(*this->m_basis); } \ 22 const Basis & basis() const { return static_cast<const Basis&>(*this->m_basis); } 23 // bool isProjective() const{ return Basis::IsRational; } 24 25 namespace gismo 26 { 27 28 /** 29 \brief 30 Abstract base class representing a geometry map. 31 32 The combination of a basis with a coefficient matrix of the proper 33 size describes a function. Such objects are called geometries. 34 35 36 Note that geometries are, essentially, functions mapping from the 37 parameter domain to the physical space, 38 39 \f[ G \ :\ \mathbb R^d \to \mathbb R^n \f] 40 41 so that 42 43 \f[ G(\hat x) = x \qquad \hat x \in \mathbb R^d, \ x \in \mathbb R^n \f] 44 45 and therefore they derive from gsFunction. A gsGeometry can thus be 46 used wherever a gsFunction is expected. 47 48 All geometry classes derive from the abstract base class 49 gsGeometry, see the \ref geometry. In general, there is a 50 statically known one-to-one mapping between basis types and their 51 associated geometry types. For instance, when you ask a 52 gsBSplineBasis to create a geometry using some given coefficient 53 matrix, you will get back an instance of gsBSpline. In turn, the 54 basis that the gsBSpline object stores internally is of type 55 gsBSplineBasis. 56 57 The parameter domain of the basis is also the parameter domain of 58 the geometry map, and has a certain source dimension \em d (see 59 gsGeometry::parDim()). Depending on the parameter domain 60 dimension, derived geometries inherit gsCurve, gsSurface, gsVolume 61 or gsBulk, for dimension 1,2,3 or 4, respectively. 62 63 The dimension \em n of the resulting geometry, 64 i.e., of the image of the geometry map, is defined by the 65 size of the given coefficients, and may be larger than \em d 66 (see gsGeometry::geoDim()). $\,$ 67 68 For instance, for a B-spline basis (<em>d = 1</em>), we could 69 have coefficients of dimension <em>n = 1</em>, which results 70 in a parametrization of a 1-D interval, or we could have 71 coefficients of size <em>n = 3</em>, which results in a B-spline 72 curve in 3-D space. 73 74 The coefficients are stored as an <em>s x n</em> matrix, 75 where \em s is the size of the basis, i.e., the number of 76 its basis functions. 77 Every row of the coefficient matrix is an *n*-dimensional control 78 point, i.e., the vector-valued coefficient for the associated 79 basis function. 80 81 Evaluation at parameter values is done with 82 \ref func_eval_members "the Evaluation member functions" derived 83 from gsFunction. 84 85 \tparam T coefficient type 86 87 \ingroup function 88 \ingroup geometry 89 \ingroup Core 90 */ 91 template<class T> 92 class gsGeometry : public gsFunction<T> 93 { 94 95 public: 96 /// Shared pointer for gsGeometry 97 typedef memory::shared_ptr< gsGeometry > Ptr; 98 99 /// Unique pointer for gsGeometry 100 typedef memory::unique_ptr< gsGeometry > uPtr; 101 102 typedef T Scalar_t; 103 104 public: 105 106 /// @name Constructors 107 /// @{ 108 109 /// @brief Default constructor. Note: Derived constructors (except for 110 /// the default) should assign \a m_basis to a valid pointer gsGeometry()111 gsGeometry() :m_basis( NULL ), m_id(0) 112 { } 113 114 /// @brief Constructor by a basis and coefficient vector 115 /// 116 /// Coefficients are given by \em{give(coefs) and they are 117 /// consumed, i.e. the \coefs variable will be empty after the call gsGeometry(const gsBasis<T> & basis,gsMatrix<Scalar_t> coefs)118 gsGeometry( const gsBasis<T> & basis, gsMatrix<Scalar_t> coefs) : 119 m_basis(basis.clone().release()), m_id(0) 120 { 121 m_coefs.swap(coefs); 122 GISMO_ASSERT( basis.size() == m_coefs.rows(), 123 "The coefficient matrix of the geometry (rows="<<m_coefs.rows() 124 <<") does not match the number of basis functions in its basis(" 125 << basis.size() <<")."); 126 } 127 128 /// @brief Copy Constructor gsGeometry(const gsGeometry & o)129 gsGeometry(const gsGeometry & o) 130 : m_coefs(o.m_coefs), m_basis(o.m_basis != NULL ? o.basis().clone().release() : NULL), m_id(o.m_id) 131 { } 132 133 /// @} 134 135 gsGeometry& operator=( const gsGeometry & o) 136 { 137 if ( this != &o ) 138 { 139 m_coefs = o.m_coefs; 140 delete m_basis; 141 m_basis = o.basis().clone().release() ; 142 m_id = o.m_id; 143 } 144 return *this; 145 } 146 ~gsGeometry()147 virtual ~gsGeometry() 148 { 149 delete m_basis; 150 } 151 152 #if EIGEN_HAS_RVALUE_REFERENCES gsGeometry(gsGeometry && other)153 gsGeometry(gsGeometry&& other) 154 : m_coefs(std::move(other.m_coefs)), m_basis(other.m_basis), 155 m_id(std::move(other.m_id)) 156 { 157 other.m_basis = NULL; 158 } 159 gsGeometry & operator=(gsGeometry&& other) 160 { 161 m_coefs.swap(other.m_coefs); other.m_coefs.clear(); 162 delete m_basis; 163 m_basis = other.m_basis; other.m_basis = NULL; 164 m_id = std::move(other.m_id); 165 return *this; 166 } 167 #endif 168 169 public: 170 171 /** 172 @name Evaluation functions 173 174 re-implemented from gsFunction, see also \ref func_eval_members 175 @{ 176 */ 177 178 /** \brief Evaluate the function at points \a u into \a result. 179 * 180 * Let \em d be the dimension of the source space ( d = domainDim() ).\n 181 * Let \em n be the dimension of the image/target space ( n = targetDim() ).\n 182 * Let \em N denote the number of evaluation points. 183 * 184 * \param[in] u gsMatrix of size <em>d</em> x <em>N</em>, where each 185 * column of \em u represents one evaluation point. 186 * \param[out] result gsMatrix of size <em>n</em> x <em>N</em>, where each 187 * column of \em u represents the result of the function at the 188 * respective valuation point. 189 */ 190 // Look at gsFunction class for documentation eval_into(const gsMatrix<T> & u,gsMatrix<T> & result)191 void eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const 192 { this->basis().evalFunc_into(u, m_coefs, result); } 193 194 /** \brief Evaluate derivatives of the function 195 * \f$f:\mathbb{R}^d\rightarrow\mathbb{R}^n\f$ 196 * at points \a u into \a result. 197 * 198 * Let \em d be the dimension of the source space ( d = domainDim() ).\n 199 * Let \em n be the dimension of the image/target space ( n = targetDim() ).\n 200 * Let \em N denote the number of evaluation points. 201 * 202 * Let \f$ f:\mathbb R^2 \rightarrow \mathbb R^3 \f$, i.e., 203 * \f$ f(x,y) = ( f^{(1)}(x,y), f^{(2)}(x,y), f^{(3)}(x,y) )^T\f$,\n 204 * and let 205 * \f$ u = ( u_1, \ldots, u_N) = ( (x_1,y_1)^T, \ldots, (x_N, y_N)^T )\f$.\n 206 * Then, \em result is of the form 207 * \f[ 208 \left[ 209 \begin{array}{cccc} 210 \partial_x f^{(1)}(u_1) & \partial_x f^{(1)}(u_2) 211 & \ldots & \partial_x f^{(1)}(u_N) \\ 212 \partial_y f^{(1)}(u_1) & \partial_y f^{(1)}(u_2) 213 & \ldots & \partial_y f^{(1)}(u_N) \\ 214 \partial_x f^{(2)}(u_1) & \partial_x f^{(2)}(u_2) 215 & \ldots & \partial_x f^{(2)}(u_N) \\ 216 \partial_y f^{(2)}(u_1) & \partial_y f^{(2)}(u_2) 217 & \ldots & \partial_x f^{(2)}(u_N) \\ 218 \partial_x f^{(3)}(u_1) & \partial_x f^{(3)}(u_2) 219 & \ldots & \partial_x f^{(3)}(u_N)\\ 220 \partial_y f^{(3)}(u_1) & \partial_y f^{(3)}(u_2) 221 & \ldots & \partial_y f^{(3)}(u_N) 222 \end{array} 223 \right] 224 \f] 225 * 226 * \param[in] u gsMatrix of size <em>d</em> x <em>N</em>, where each 227 * column of \em u represents one evaluation point. 228 * \param[out] result gsMatrix of size <em>(d * n)</em> x <em>N</em>. 229 * Each row of \em result corresponds to one component in the target 230 * space and contains the gradients for each evaluation point, 231 * as row vectors, one after the other (see above for details on the format). 232 * 233 * \warning By default, gsFunction uses central finite differences 234 * with h=0.00001! One must override this function in derived 235 * classes to get proper results. 236 */ 237 // Look at gsFunction class for documentation deriv_into(const gsMatrix<T> & u,gsMatrix<T> & result)238 void deriv_into(const gsMatrix<T>& u, gsMatrix<T>& result) const 239 { this->basis().derivFunc_into(u, m_coefs, result); } 240 241 242 /** @brief Evaluate second derivatives of the function at points \a u into \a result. 243 * 244 * Let \em d be the dimension of the source space ( d = domainDim() ).\n 245 * Let \em n be the dimension of the image/target space ( n = targetDim() ).\n 246 * Let \em N denote the number of evaluation points. 247 * 248 * \param[in] u gsMatrix of size <em>d</em> x <em>N</em>, where each 249 * column of \em u represents one evaluation point. 250 * \param[out] result gsMatrix of size <em>(S*n)</em> x <em>N</em>, 251 * where <em>S=d*(d+1)/2</em>.\n 252 * Each column in \em result corresponds to one point (i.e., one column in \em u)\n 253 * and contains the following values (for <em>d=3</em>, <em>n=3</em>):\n 254 * \f$ (\partial_{xx} f^{(1)}, \partial_{yy} f^{(1)}, \partial_{zz} f^{(1)}, \partial_{xy} f^{(1)}, 255 \partial_{xz} f^{(1)}, \partial_{yz} f^{(1)}, \partial_{xx} f^{(2)},\ldots,\partial_{yz} f^{(3)} )^T\f$ 256 * \warning By default uses central finite differences with h=0.00001! 257 * One must override this function in derived 258 * classes to get proper results. 259 */ 260 // Look at gsFunctionSet class for documentation deriv2_into(const gsMatrix<T> & u,gsMatrix<T> & result)261 void deriv2_into(const gsMatrix<T>& u, gsMatrix<T>& result) const 262 { this->basis().deriv2Func_into(u, m_coefs, result); } 263 evalAllDers_into(const gsMatrix<T> & u,int n,std::vector<gsMatrix<T>> & result)264 void evalAllDers_into(const gsMatrix<T> & u, int n, 265 std::vector<gsMatrix<T> > & result) const 266 { this->basis().evalAllDersFunc_into(u, m_coefs, n, result); } 267 268 /// @} 269 270 271 // Look at gsFunctionSet for documentation 272 virtual void compute(const gsMatrix<T> & in, gsFuncData<T> & out) const; 273 274 /// \brief Evaluates if the geometry orientation coincide with the 275 /// ambient orientation. 276 /// This is computed in the center of the parametrization and will 277 /// fail to be meaningful if the geometry is singular. 278 /// returns one if codimension is not zero orientation()279 int orientation() const 280 { 281 if ( parDim() == geoDim() ) 282 { 283 const T val = gsFunction<T>::jacobian( parameterCenter() ).determinant(); 284 return (T(0) < val) - (val < T(0)); 285 } 286 return 1; 287 } 288 289 /// @} 290 291 /*************************************************************************/ 292 293 /// @name Accessors 294 /// @{ 295 296 /// \brief Returns a const reference to the basis of the geometry. 297 /// \note This function will return the derived concrete type of the basis. 298 virtual const gsBasis<T> & basis() const = 0; 299 300 /// \brief Returns a reference to the basis of the geometry. 301 /// \note This function will return the derived concrete type of the basis. 302 virtual gsBasis<T> & basis() = 0; 303 304 /// Dimension of the ambient physical space (overriding gsFunction::targetDim()) targetDim()305 short_t targetDim() const { return this->coefDim(); } 306 307 /// Dimension \em n of the coefficients (control points) coefDim()308 short_t coefDim() const { return static_cast<short_t>(m_coefs.cols()); } 309 310 /// Dimension \em n of the absent physical space geoDim()311 short_t geoDim() const { return this->coefDim(); } 312 313 /// Dimension \em d of the parameter domain (overriding gsFunction::domainDim()). domainDim()314 virtual short_t domainDim() const { return this->basis().domainDim(); } 315 316 /// Dimension \em d of the parameter domain (same as domainDim()). parDim()317 short_t parDim() const { return this->basis().domainDim(); } 318 319 /// Co-dimension of the geometric object coDim()320 short_t coDim() const { return coefDim()-this->basis().domainDim(); } 321 322 /// Returns the range of parameters (same as parameterRange()) support()323 gsMatrix<T> support() const 324 { return this->basis().support(); } 325 326 /// Returns the range of parameters as a matrix with two columns, [lower upper] parameterRange()327 gsMatrix<T> parameterRange() const 328 { return this->basis().support(); } 329 330 /// Returns a "central" point inside inside the parameter domain parameterCenter()331 virtual gsMatrix<T> parameterCenter() const 332 { 333 // default impl. assumes convex support 334 gsMatrix<T> S = this->basis().support(); 335 return ( S.col(0) + S.col(1) ) * T(0.5); 336 } 337 338 /// Get coordinates of the boxCorner \a bc in the parameter domain 339 gsMatrix<T> parameterCenter( const boxCorner& bc ); 340 341 /// Get coordinates of the midpoint of the boxSide \a bs in the parameter domain 342 gsMatrix<T> parameterCenter( const boxSide& bs ); 343 344 /// Get back the side of point \a u 345 //boxSide sideOf(const gsVector<T> & u); // 346 347 /// Check if points \a u also lie on the geometry and if required computes the if the points in \a u lie on one of the boundaries of the geometry 348 /** 349 * 350 * @param u Matrix of points of the form geoDim() x #points 351 * @param onG2 gsVector of booleans which indicate if the point is in the domain or outside 352 * @param preIm Matrix of preimages of the points u 353 * @param lookForBoundary if required the boundaries are computed the points in u lie on 354 * @return A std::vector of boxSides containing the numbers of the sides or zero if the points are in the interior 355 * If the flag lookForBoundary is not set then a vector containing anything will be returned 356 */ 357 std::vector<boxSide> locateOn(const gsMatrix<T> & u, gsVector<bool> & onG2, gsMatrix<T> & preIm, bool lookForBoundary = false, real_t tol = 1.e-6) const; // 358 359 // Whether the coefficients of this geometry are stored in projective or affine form 360 //virtual bool isProjective() const = 0; 361 362 /// @} 363 364 /*************************************************************************/ 365 366 /** @name Coefficient access functions 367 368 These functions allow direct access to the coefficient matrix of the geometry. 369 @{ 370 */ 371 372 /// Returns the coefficient matrix of the geometry 373 /// Coefficient matrix of size coefsSize() x geoDim() 374 // todo: coefsSize() x (geoDim() + 1) if projective coefs()375 gsMatrix<T> & coefs() { return this->m_coefs; } 376 377 /// Returns the coefficient matrix of the geometry coefs()378 const gsMatrix<T> & coefs() const { return this->m_coefs; } 379 380 /// Returns the i-th coefficient of the geometry as a row expression coef(index_t i)381 typename gsMatrix<T>::RowXpr coef(index_t i) { return m_coefs.row(i); } 382 383 /// Returns the i-th coefficient of the geometry as a row expression coef(index_t i)384 typename gsMatrix<T>::ConstRowXpr coef(index_t i) const { return m_coefs.row(i); } 385 386 /// Returns the j-th coordinate of the i-th coefficient of the geometry coef(index_t i,index_t j)387 T & coef(index_t i, index_t j) 388 { 389 GISMO_ASSERT( ((i < m_coefs.rows()) && (j < m_coefs.cols()) ), 390 "Coefficient or coordinate which is out of range requested."); 391 return m_coefs(i,j); 392 } 393 394 /// Returns the j-th coordinate of the i-th coefficient of the geometry coef(index_t i,index_t j)395 const T coef(index_t i, index_t j) const 396 { 397 GISMO_ASSERT( ((i < m_coefs.rows()) && (j < m_coefs.cols()) ), 398 "Coefficient or coordinate which is out of range requested."); 399 return m_coefs(i,j); 400 } 401 402 /// Set the coefficient matrix of the geometry, taking ownership of the matrix setCoefs(gsMatrix<T> cc)403 void setCoefs(gsMatrix<T> cc) { this->m_coefs.swap(cc); } 404 405 /// Return the number of coefficients (control points) coefsSize()406 unsigned coefsSize() const { return m_coefs.rows(); } 407 // Warning: This can cause some clash while using periodic basis, since the ghost coefs are stored but ignored. 408 409 410 411 /// @} 412 413 /*************************************************************************/ 414 415 /** @name Transformation functions 416 417 These functions apply various linear and affine transformations 418 to the coefficients. 419 @{ 420 */ 421 422 /// Apply the given square matrix to every control point. linearTransform(const gsMatrix<T> & mat)423 void linearTransform(const gsMatrix<T>& mat) 424 { 425 this->m_coefs = this->m_coefs * mat.transpose(); 426 } 427 428 /// Apply 3D Rotation by \a angle radians around axis \a axis rotate(T angle,const gsVector<T,3> & axis)429 void rotate(T angle, const gsVector<T,3> & axis ) 430 { 431 assert( geoDim() == 3 ); 432 Eigen::Transform<T,3,Eigen::Affine> 433 rot( Eigen::AngleAxis<T> (angle,axis.normalized()) ); 434 // To do: Simpler way to use transforms ? 435 this->m_coefs = (this->m_coefs.rowwise().homogeneous() * 436 rot.matrix().transpose() ).leftCols(3) ; 437 } 438 439 /// Apply 2D Rotation by \a angle radians rotate(T angle)440 void rotate(T angle) 441 { 442 GISMO_ASSERT( geoDim() == 2, "Only for 2D"); 443 Eigen::Rotation2D<T> rot(angle); 444 this->m_coefs *= rot.matrix().transpose(); 445 } 446 447 /// Apply Scaling by factor \a s 448 void scale(T s, int coord = -1) 449 { 450 if ( coord == -1) // Uniform scaling 451 this->m_coefs *= s; 452 else if ( coord <geoDim() )//scale coordinate coord 453 this->m_coefs.col(coord) *= s; 454 } 455 456 /// Apply Scaling coord-wise by a vector v scale(gsVector<T> const & v)457 void scale(gsVector<T> const & v) 458 { 459 GISMO_ASSERT( v.rows() == this->m_coefs.cols(), "Sizes do not agree." ); 460 this->m_coefs.array().rowwise() *= v.array().transpose(); 461 } 462 463 /// Apply translation by vector v translate(gsVector<T> const & v)464 void translate(gsVector<T> const & v) 465 { 466 this->m_coefs.rowwise() += v.transpose(); 467 } 468 469 /// \brief Returns the control point at corner \a c 470 typename gsMatrix<T>::RowXpr 471 coefAtCorner(boxCorner const & c); 472 473 /// \brief Returns the control point at corner \a c 474 typename gsMatrix<T>::ConstRowXpr 475 coefAtCorner(boxCorner const & c) const; 476 477 /// @} 478 479 /*************************************************************************/ 480 481 /// @name Other miscellaneous functions 482 /// @{ 483 484 /// Refine the geometry uniformly, inserting \a numKnots new knots into each knot span 485 virtual void uniformRefine(int numKnots = 1, int mul=1) // todo: int dir = -1 486 { 487 this->basis().uniformRefine_withCoefs( m_coefs, numKnots, mul); 488 } 489 490 /** \brief Refines the basis and adjusts the coefficients to keep the geometry the same. 491 * 492 * The syntax of \em boxes depends on the implementation in the 493 * underlying basis. See gsBasis::refineElements_withCoefs() for details. 494 */ refineElements(std::vector<index_t> const & boxes)495 void refineElements( std::vector<index_t> const & boxes ) 496 { 497 this->basis().refineElements_withCoefs(this->m_coefs, boxes ); 498 } 499 coord(const index_t c)500 typename gsGeometry::uPtr coord(const index_t c) const {return this->basis().makeGeometry( this->coefs().col(c) ); } 501 502 /// Embeds coefficients in 3D embed3d()503 void embed3d() 504 { 505 embed(3); 506 } 507 508 /// \brief Embeds coefficients in \a N dimensions 509 ///For the new dimensions zeros are added (or removed) on the 510 /// right (if \a pad_right is true) or on the left (if \a 511 /// pad_right is false) 512 void embed(index_t N, bool pad_right = true) 513 { 514 GISMO_ASSERT( N > 0, "Embed dimension must be positive"); 515 516 const index_t nc = N - m_coefs.cols(); 517 if ( nc == 0 ) return; 518 519 if (!pad_right && nc<0) 520 m_coefs.leftCols(N) = m_coefs.rightCols(N); 521 m_coefs.conservativeResize(Eigen::NoChange, N); 522 523 if ( nc > 0 ) 524 { 525 if (pad_right) 526 m_coefs.rightCols(nc).setZero(); 527 else 528 { 529 m_coefs.rightCols(N-nc) = m_coefs.leftCols(N-nc); 530 m_coefs.leftCols(nc).setZero(); 531 } 532 } 533 # ifndef NDEBUG 534 else gsWarn<<"Coefficients projected (deleted)..\n"; 535 # endif 536 } 537 538 /// \brief Returns the degree wrt direction i degree(const short_t & i)539 short_t degree(const short_t & i) const 540 //{ return this->basisComponent(i).degree(); }; 541 { return this->basis().degree(i); } 542 543 /// \brief Elevate the degree by the given amount \a i for the 544 /// direction \a dir. If \a dir is -1 then degree elevation is 545 /// done for all directions 546 virtual void degreeElevate(short_t const i = 1, short_t const dir = -1); 547 548 /// \brief Reduces the degree by the given amount \a i for the 549 /// direction \a dir. If \a dir is -1 then degree reduction is 550 /// done for all directions 551 virtual void degreeReduce(short_t const i = 1, short_t const dir = -1); 552 553 /// Compute the Hessian matrix of the coordinate \a coord 554 /// evaluated at points \a u 555 virtual void hessian_into(const gsMatrix<T>& u, gsMatrix<T> & result, 556 index_t coord) const; 557 558 /// Return the control net of the geometry controlNet(gsMesh<T> & mesh)559 void controlNet( gsMesh<T> & mesh) const 560 { basis().connectivity(m_coefs, mesh); } 561 562 /// @brief Computes the outer normals at parametric points \a u. 563 /// 564 /// Assumes that \a u is a list of points on the boundary of the geometry. 565 void outerNormal_into(const gsMatrix<T>& u, gsMatrix<T> & result) const; 566 567 /// Get boundary of this geometry as a vector of new gsGeometry instances 568 std::vector<gsGeometry *> boundary() const; 569 570 /// Get parametrization of boundary side \a s as a new gsGeometry uPtr. 571 typename gsGeometry::uPtr boundary(boxSide const& s) const; 572 573 /// Computes and returns the interface with \a other as a new geometry 574 virtual typename gsGeometry::uPtr iface(const boundaryInterface & bi, 575 const gsGeometry & other) const; 576 577 /// Get parametrization of box component \a bc as a new gsGeometry uPtr. 578 typename gsGeometry::uPtr component(boxComponent const& bc) const; 579 GISMO_UPTR_FUNCTION_PURE(gsGeometry,clone)580 GISMO_UPTR_FUNCTION_PURE(gsGeometry, clone) 581 582 /// Prints the object as a string. 583 virtual std::ostream &print(std::ostream &os) const 584 { 585 os << "Geometry "<< "R^"<< this->parDim() << 586 " --> R^"<< this->geoDim()<< ", #control pnts= "<< coefsSize() << 587 ": "<< coef(0) <<" ... "<< coef(this->coefsSize()-1); 588 os<<"\nBasis:\n" << this->basis() ; 589 return os; 590 } 591 592 /// Merge the given \a other geometry into this one. 593 virtual void merge( gsGeometry * other ); 594 595 virtual void toMesh(gsMesh<T> & msh, int npoints) const; 596 597 /// Updates the vertices of input \a mesh by evaluating the 598 /// geometry at vertices. 599 /// Vertices of the new mesh are 600 /// 601 /// { geom(v) | v vertex of input mesh } 602 /// 603 void evaluateMesh(gsMesh<T>& mesh) const; 604 605 606 /// Splits the geometry 2^d parts, where each direction is divided into two parts in 607 /// in a uniform way, i.e., in the middle of the corresponding side. This method 608 /// allocated new space for each new geometry, the original one stays unchanged. 609 virtual std::vector<gsGeometry<T>* > uniformSplit(index_t dir =-1 ) const; 610 611 /// @} 612 613 /// Gives back an isoParametric slice of the geometry with fixed 614 /// \a par in direction \a dim_fixed as an gsGeometrySlice object. 615 gsGeometrySlice<T> getIsoParametricSlice(index_t dir_fixed, T par) const; 616 617 /// Takes the physical \a points and computes the corresponding 618 /// parameter values. If the point cannot be inverted (eg. is not 619 /// part of the geometry) the corresponding parameter values will be undefined 620 virtual void invertPoints(const gsMatrix<T> & points, gsMatrix<T> & result, 621 const T accuracy = 1e-6, 622 const bool useInitialPoint = false) const; 623 624 /// Returns the parameters of closest point to \a pt 625 void closestPointTo(const gsVector<T> & pt, 626 gsVector<T> & result, 627 const T accuracy = 1e-6, 628 const bool useInitialPoint = false) const; 629 630 /// Sets the patch index for this patch setId(const size_t i)631 void setId(const size_t i) { m_id = i; } 632 633 /// Returns the patch index for this patch id()634 size_t id() const { return m_id; } 635 636 637 protected: swap(gsGeometry & other)638 void swap(gsGeometry & other) 639 { 640 std::swap(m_basis, other.m_basis); 641 m_coefs.swap(other.m_coefs); 642 std::swap(m_id, other.m_id); 643 } 644 645 protected: 646 647 /// Coefficient matrix of size coefsSize() x geoDim() 648 //todo: coefsSize() x (geoDim() + 1) if projective 649 gsMatrix<T> m_coefs; 650 651 /// Pointer to the basis of this geometry 652 gsBasis<T> * m_basis; 653 654 /// An auxiliary index for this geometry (eg. in case it is part 655 /// of a multi-patch object) 656 size_t m_id; 657 658 }; // class gsGeometry 659 660 /// Print (as string) operator to be used by all derived classes 661 template<class T> 662 std::ostream &operator<<(std::ostream &os, const gsGeometry<T>& b) 663 {return b.print(os); } 664 665 } // namespace gismo 666 667 #include <gsCore/gsCurve.h> 668 #include <gsCore/gsSurface.h> 669 #include <gsCore/gsVolume.h> 670 #include <gsCore/gsBulk.h> 671 672 namespace gismo 673 { 674 675 // Generic traits for geometry with dimension known at compile time 676 template <short_t d, typename T> 677 struct gsGeoTraits 678 { 679 typedef gsGeometry<T> GeometryBase; 680 }; 681 682 // Traits for curve 683 template <typename T> 684 struct gsGeoTraits<1,T> 685 { 686 typedef gsCurve<T> GeometryBase; 687 }; 688 689 // Traits for surface 690 template <typename T> 691 struct gsGeoTraits<2,T> 692 { 693 typedef gsSurface<T> GeometryBase; 694 }; 695 696 // Traits for volume 697 template <typename T> 698 struct gsGeoTraits<3,T> 699 { 700 typedef gsVolume<T> GeometryBase; 701 }; 702 703 // Traits for bulk 704 template <typename T> 705 struct gsGeoTraits<4,T> 706 { 707 typedef gsBulk<T> GeometryBase; 708 }; 709 710 } // namespace gismo 711 712 713 #ifndef GISMO_BUILD_LIB 714 #include GISMO_HPP_HEADER(gsGeometry.hpp) 715 #endif 716