G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsVolumeBlock.h
Go to the documentation of this file.
1
15#pragma once
16
17#include <gsModeling/gsSolid.h>
20
21#include <gsCore/gsVolume.h>
22#include <gsCore/gsBoundary.h>
23
24
25
26namespace gismo {
27
28template <class T>
29class gsVolumeBlock : public gsSolidElement<T>
30{
31public:
32 // to do change all types in gsModeling
33
34 typedef gsSolidElement<T> SolidElement;
35 typedef typename SolidElement::scalar_t scalar_t;
36 typedef gsSolidHalfFace<T> HalfFace;
37 typedef gsSolidHalfEdge<T> HalfEdge;
38 typedef gsSolidHeVertex<T> Vertex;
39
40public:
41 gsVolumeBlock() : SolidElement() { }
42
43 explicit gsVolumeBlock(int const& i) : SolidElement(i) { }
44
45 explicit gsVolumeBlock(std::vector<HalfFace*> const & hfaces)
46 {
47 face = hfaces;
48 typename std::vector<HalfFace*>::const_iterator it;
49 for (it = hfaces.begin();it!=hfaces.end();++it)
50 {
51 (*it)->vol = this;
52 }
53 }
54
55 virtual ~gsVolumeBlock()
56 { }
57
58public:
59
66 boxSide getSideOfHexahedron(const unsigned faceId)
67 {
68 if (!isHexahedron())
69 {
70 GISMO_ERROR("VolumeBlock is not hexahedron.\n");
71 }
72
73 HalfEdge* edge = face[0]->loop[0];
74 std::vector<HalfEdge* > hex; // hexahedrons initial HalfEdges
75 getHexEdges(hex, edge); // each side is presented with leading edge
76
77 HalfFace* myFace = face[faceId];
78
79 int sideIndex = -1; // resulting index of side - 1
80
81 for (size_t edgeIndx = 0; edgeIndx < hex.size(); edgeIndx++)
82 {
83 HalfEdge* faceEdge = hex[edgeIndx];
84
85 // checks if the edge e is in the face
86 HalfEdge* e = myFace->loop[0];
87 for (unsigned i = 0; i < 4; i++)
88 {
89 if (e == faceEdge)
90 {
91 sideIndex = static_cast<int>(edgeIndx);
92 }
93
94 e = e->next;
95 }
96 }
97
98 if (sideIndex == -1)
99 {
100 gsWarn << "Didn't transform face with id = " << faceId << "\n";
101 }
102
103 return boxSide(sideIndex + 1);
104 }
105
106
107
114 bool isHexahedron() const
115 {
116
117 if (face.size() != 6)
118 {
119 return false;
120 }
121 else
122 {
123 for (unsigned idFace = 0; idFace != face.size(); idFace++)
124 {
125 HalfFace* myFace = face[idFace];
126
127 if (1 < myFace->loopN())
128 {
129 gsWarn << "Input volume has a hole in its face. "
130 "Ignoring it...\n";
131 }
132
133
134 gsPlanarDomain<T>& domain = myFace->surf->domain();
135
136 // first loop (loop(0)) describes outer boundary
137 gsCurveLoop<T>& curveLoop = domain.loop(0);
138
139 if (curveLoop.numCurves() != 4)
140 return false;
141 }
142
143 return true;
144 }
145 }
146
148 gsTensorBSpline<3, T> getTensorBSplineVolume(int numSamplePoints,
149 int numInternalKnots,
150 int degree,
151 T lambda,
152 T eps)
153 {
154 if (!isHexahedron())
155 {
156 GISMO_ERROR("VolumeBlock is not hexahedron.\n"
157 "Function getVolume can not tranform VolumeBlock into "
158 "gsVolume if VolumeBlock is not hexahedron.\n");
159
160 }
161
162 gsMatrix<T> points;
163 gsMatrix<T> params;
164 //getUniformBoundaryPoints(numSamplePoints, params, points);
165 getUniformPoints(numSamplePoints, params, points, eps);
166
167 gsKnotVector<T> kv1(0, 1, numInternalKnots, degree + 1, 1);
168 gsKnotVector<T> kv2(0, 1, numInternalKnots, degree + 1, 1);
169 gsKnotVector<T> kv3(0, 1, numInternalKnots, degree + 1, 1);
170
171 gsTensorBSplineBasis<3, T> basis(kv1, kv2, kv3);
172
173 gsDebugVar(kv1.detail());
174 gsDebugVar(basis);
175 gsFitting<T> fitting(params, points, basis);
176 fitting.compute(lambda);
177
178 // note gsFitting deletes the geomety in destructor
179 gsGeometry<T>* geo = fitting.result();
180
181 gsTensorBSpline<3, T>* bspline = dynamic_cast<gsTensorBSpline<3, T>* > (geo);
182
183 if (bspline == NULL)
184 {
185 GISMO_ERROR("Problems with casting gsGeometry to gsTensorBspline");
186 }
187
188 return *bspline;
189 }
190
191
197 void getUniformPoints(const int n,
198 gsMatrix<T>& params,
199 gsMatrix<T>& points,
200 T eps)
201 {
202 gsMatrix<T> bParams, bPoints;
203 getUniformBoundaryPoints(n, bParams, bPoints, eps);
204
205 typedef std::pair<std::pair<T, T>, T> tuple;
206
207 // make a map for fast access
208 std::map<tuple, int> map;
209 for (int col = 0; col < bParams.cols(); col++)
210 {
211 tuple t = makeTuple(bParams(0, col), bParams(1, col), bParams(2, col));
212 map[t] = col;
213 }
214
215 // save points at corners because they are used often
216 const gsVector<T> p000 = bPoints.col(map[makeTuple(0., 0., 0.)]);
217 const gsVector<T> p001 = bPoints.col(map[makeTuple(0., 0., 1.)]);
218 const gsVector<T> p010 = bPoints.col(map[makeTuple(0., 1., 0.)]);
219 const gsVector<T> p011 = bPoints.col(map[makeTuple(0., 1., 1.)]);
220 const gsVector<T> p100 = bPoints.col(map[makeTuple(1., 0., 0.)]);
221 const gsVector<T> p101 = bPoints.col(map[makeTuple(1., 0., 1.)]);
222 const gsVector<T> p110 = bPoints.col(map[makeTuple(1., 1., 0.)]);
223 const gsVector<T> p111 = bPoints.col(map[makeTuple(1., 1., 1.)]);
224
225 const int numPoints = (n - 2) * (n - 2) * (n - 2) + bParams.cols();
226 params.resize(3, numPoints);
227 points.resize(3, numPoints);
228
229 // Coons patch algorithm
230 int column = 0;
231 for (int indx = 1; indx != n - 1; indx++)
232 {
233 const T x = (indx * 1.0) / (n - 1);
234
235 for (int indy = 1; indy != n - 1; indy++)
236 {
237 const T y = (indy * 1.0) / (n - 1);
238
239 for (int indz = 1; indz != n - 1; indz++)
240 {
241 const T z = (indz * 1.0) / (n - 1);
242
243 // parameters
244 params(0, column) = x;
245 params(1, column) = y;
246 params(2, column) = z;
247
248 // points 3D Coons Patch Algorithm
249
250 // interpolation of faces
251 const gsVector<T> A =
252 (1 - x) * bPoints.col(map[makeTuple(0, y, z)]) +
253 x * bPoints.col(map[makeTuple(1, y, z)]);
254
255 const gsVector<T> B =
256 (1 - y) * bPoints.col(map[makeTuple(x, 0, z)]) +
257 y * bPoints.col(map[makeTuple(x, 1, z)]);
258
259 const gsVector<T> C =
260 (1 - z) * bPoints.col(map[makeTuple(x, y, 0)]) +
261 z * bPoints.col(map[makeTuple(x, y, 1)]);
262
263 // interpolation of boundary curves
264 const gsVector<T> AB =
265 (1 - x) * (1 - y) * bPoints.col(map[makeTuple(0, 0, z)]) +
266 (1 - x) * y * bPoints.col(map[makeTuple(0, 1, z)]) +
267 x * (1 - y) * bPoints.col(map[makeTuple(1, 0, z)]) +
268 x * y * bPoints.col(map[makeTuple(1, 1, z)]);
269
270 const gsVector<T> BC =
271 (1 - y) * (1 - z) * bPoints.col(map[makeTuple(x, 0, 0)]) +
272 (1 - y) * z * bPoints.col(map[makeTuple(x, 0, 1)]) +
273 y * (1 - z) * bPoints.col(map[makeTuple(x, 1, 0)]) +
274 y * z * bPoints.col(map[makeTuple(x, 1, 1)]);
275
276 const gsVector<T> AC =
277 (1 - x) * (1 - z) * bPoints.col(map[makeTuple(0, y, 0)]) +
278 (1 - x) * z * bPoints.col(map[makeTuple(0, y, 1)]) +
279 x * (1 - z) * bPoints.col(map[makeTuple(1, y, 0)]) +
280 x * z * bPoints.col(map[makeTuple(1, y, 1)]);
281
282 // interpolation of corner points
283 const gsVector<T> ABC =
284 (1 - x) * ((1 - y) * ((1 - z) * p000 + z * p001) +
285 y * ((1 - z) * p010 + z * p011)) +
286 x * ((1 - y) * ((1 - z) * p100 + z * p101) +
287 y * ((1 - z) * p110 + z * p111));
288
289 points.col(column) = A + B + C - AB - BC - AC + ABC;
290
291 column++;
292 }
293 }
294 }
295
296
297 // append boundary points to
298 for (int col = 0; col < bPoints.cols(); ++col)
299 {
300 points.col(column) = bPoints.col(col);
301 params.col(column) = bParams.col(col);
302 column++;
303 }
304 }
305
306
311 void getUniformBoundaryPoints(const int n,
312 gsMatrix<T>& params3D,
313 gsMatrix<T>& points,
314 T eps = 1e-6)
315 {
316 HalfEdge* edge = face[0]->loop[0];
317 std::vector<HalfEdge* > hex; // hexahedrons initial HalfEdges
318 getHexEdges(hex, edge);
319
320 int nmbOfPts = 6 * (n * n + 4); // 6 faces * number of points on faces
321 points .resize(3, nmbOfPts);
322 params3D.resize(3, nmbOfPts);
323
324 gsVector<T> params1D(n);
325 for (int index = 0; index != n; index++)
326 {
327 params1D(index) = index * 1.0 / (n - 1);
328 }
329
330 int column = 0;
331
332 for (boxSide side = boxSide::getFirst(3); side<boxSide::getEnd(3); ++side )
333 {
334
335 // this variable is true if we must turn around a curve loop in
336 // this side
337 bool turnAround = turnCurveLoopAround(side);
338 T fixedConstant = side.parameter() ? 1.0 : 0.0;
339
340 // fixed - index of coordinate where parameter for this side has
341 // fixedConstant value
342 // first - index of coordinate where first curve in hexahedron has
343 // its range
344 // second - index of cooridnate where first curve in hexahedron is
345 // constant
346 int fixed = side.direction();
347 int first = (fixed == 0) ? 1 : 0;
348 int second = (fixed == 2) ? 1 : 2;
349
350 if (fixed == 0) // east and west
351 {
352 int t = first;
353 first = second;
354 second = t;
355 }
356
357// gsDebug << "side: " << side << "\n"
358// << "directions side: " << fixed << "\n"
359// << "parameter: " << fixedConstant << "\n"
360// << "first: " << first << "\n"
361// << "seconde: " << second << "\n" << std::endl;
362
363 std::vector<gsVector<T> > faceBoundaryParams;
364 HalfEdge* faceEdge = hex[side - 1];
365
366
367
368 // compute uniform points on each curve
369 for (int curveId = 0; curveId < 4; curveId++)
370 {
371 HalfEdge* edge2 = faceEdge->moveAlongEdge(curveId);
372
373 // gets index of a curve in Trimmed surface
374 int index = edge2->face->indexOfEdge(edge2);
375
376 gsVector<T> params;
377 edge2->face->surf->getPhysicalyUniformCurveParameters(
378 0, index, n, params, eps);
379
380
381 gsMatrix<T> curvePoints;
382 edge2->face->surf->evalCurve_into(
383 0, index, params.transpose(), curvePoints);
384
385
386 bool turnCurve = turnCurveAround(turnAround, curveId);
387
388 // curve has constant parameter along two dimensions
389 // (in parameter domain)
390 // - first constant is set by position of the face
391 // - second constant is set by position of the curve in
392 // curve loop
393 T curveConstant = 0.0;
394 if ( (turnAround && (curveId == 2 || curveId == 3)) ||
395 (!turnAround && (curveId == 1 || curveId == 2)) )
396 {
397 curveConstant = 1.0;
398 }
399
400 // curveConstantIndex - index of parameter domain where curve
401 // is constant
402 // curveNonConstIndex - index of parameter domain where curve
403 // is not constant
404 int curveConstantIndex = first;
405 int curveNonConstIndex = second;
406 if (curveId == 0 || curveId == 2)
407 {
408 curveConstantIndex = second;
409 curveNonConstIndex = first;
410 }
411
412
413 for (int col = 0; col < n; col++)
414 {
415 params3D(fixed, column) = fixedConstant;
416 params3D(curveConstantIndex, column) = curveConstant;
417 params3D(curveNonConstIndex, column) = params1D(col);
418
419 if (turnCurve)
420 {
421 points.col(column) = curvePoints.col(n - 1 - col);
422 }
423 else
424 {
425 points.col(column) = curvePoints.col(col);
426 }
427 column++;
428
429
430// gsDebug << "side: " << side << " curveID: " << curveId
431// << " turnCurve: " << turnCurve
432// << " turnAround: " << turnAround << "\n"
433// << "params: " << params3D.col(column - 1).transpose()
434// << "\n"
435// << "points: " << points.col(column - 1).transpose()
436// << "\n" << std::endl;
437 }
438
439 if (turnCurve)
440 {
441 params.reverseInPlace();
442 }
443
444 faceBoundaryParams.push_back(params);
445 }
446
447 // compute points in the interior of face
448
449 // sometimes (depends on the orientation of the curve loop
450 // we must exchange 1 and 3 curve in coons patch algorithm
451 bool switch1and3curve = false;
452 if (side == boundary::east ||
453 side == boundary::front ||
454 side == boundary::north)
455 {
456 switch1and3curve = true;
457 }
458
459 // first we compute parameter for surface via conns patch algorithm
460 // for given 4 boundary curves
461
462 gsMatrix<T> cpParams; // coons patch parameters
463 modifiedCoonsPatch(hex[side - 1], faceBoundaryParams,
464 params1D, cpParams, switch1and3curve);
465
466 gsMatrix<T> cpPoints;
467 faceEdge->face->surf->evalSurface_into(cpParams, cpPoints);
468
469 // set global parameters and points
470 for (int indv = 0; indv != n - 2; indv++)
471 {
472 for (int indu = 0; indu != n - 2; indu++)
473 {
474 params3D(fixed, column) = fixedConstant;
475 params3D(first, column) = params1D(indu + 1);
476 params3D(second, column) = params1D(indv + 1);
477
478 points.col(column) = cpPoints.col(indv * (n - 2) + indu);
479 column++;
480 }
481 }
482
483 }
484 }
485
486
487private:
488 static std::pair<std::pair<T, T>, T> makeTuple(T x, T y, T z)
489 {
490 return std::make_pair(std::make_pair(x, y), z);
491 }
492
493// static void printTuple(std::pair<std::pair<T, T>, T> tuple)
494// {
495// gsDebug << tuple.first.first << " " << tuple.first.second << " "
496// << tuple.second;
497// }
498
512 void modifiedCoonsPatch(HalfEdge* edge,
513 const std::vector<gsVector<T> >& boundaryParams,
514 const gsVector<T>& params1D,
515 gsMatrix<T>& cpPoints,
516 const bool switch1and3curve)
517 {
518 int n = boundaryParams[0].size();
519 int m = boundaryParams[1].size();
520
521 cpPoints.resize(2, (n - 2) * (m - 2));
522
523 // eval all curves...
524 std::vector<gsMatrix<T> > values;
525 for (int curveId = 0; curveId != 4; curveId++)
526 {
527 HalfEdge* curveEdge = edge->moveAlongEdge(curveId);
528 int internalIndex = getInternalIndexOfCurve(curveEdge);
529 gsCurve<T>& curve = edge->face->surf->getCurve(0, internalIndex);
530
531 gsMatrix<T> curvePoints;
532 curve.eval_into(boundaryParams[curveId].transpose(), curvePoints);
533 values.push_back(curvePoints);
534 }
535
536 // save boundary points
537 gsVector<T> c00 = values[0].col(0);
538 gsVector<T> c01 = values[0].col(n - 1);
539
540 gsVector<T> c20 = values[2].col(0);
541 gsVector<T> c21 = values[2].col(n - 1);
542
543 // do the coons patch
544
545 int column = 0;
546 // indv is index in "v direction", similar indu
547 for (int indv = 1; indv != n - 1; indv++) // ommit boundary
548 {
549 T v = params1D[indv];
550
551
552 for (int indu = 1; indu != m - 1; indu++)
553 {
554 T u = params1D[indu];
555 cpPoints.col(column) = (1 - v) * values[0].col(indu) +
556 v * values[2].col(indu)
557 - (1 - v) * (1 - u) * c00
558 - (1 - v) * u * c01
559 - v * (1 - u) * c20
560 - v * u * c21;
561
562 gsVector<T> vec;
563 if (switch1and3curve)
564 {
565 vec = (1 - u) * values[3].col(indv) +
566 u * values[1].col(indv);
567 }
568 else
569 {
570 vec = (1 - u) * values[1].col(indv) +
571 u * values[3].col(indv);
572 }
573
574 cpPoints.col(column) += vec;
575
576// gsDebug << "u: " << u << " v: " << v << "\n"
577// << "indu: " << indu << " indv: " << indv << "\n"
578// << "change1and2: " << switch1and3 << "\n";
579
580// gsMatrix<T> mat(2, 1);
581// mat(0, 0) = cpPoints(0, column);
582// mat(1, 0) = cpPoints(1, column);
583// gsMatrix<T> res;
584// edge->face->surf->evalSurface_into(mat, res);
585
586// gsDebug << "coons patch: " << res.transpose() << std::endl;
587
588// mat(0, 0) = values[0](0, indu);
589// mat(1, 0) = values[0](1, indu);
590// edge->face->surf->evalSurface_into(mat, res);
591
592// gsDebug << "curve0(indu): " << res.transpose() << std::endl;
593
594// mat(0, 0) = values[2](0, indu);
595// mat(1, 0) = values[2](1, indu);
596// edge->face->surf->evalSurface_into(mat, res);
597
598// gsDebug << "curve2(indu): " << res.transpose() << std::endl;
599
600// mat(0, 0) = values[1](0, indv);
601// mat(1, 0) = values[1](1, indv);
602// edge->face->surf->evalSurface_into(mat, res);
603
604// gsDebug << "curve1(indv): " << res.transpose() << std::endl;
605
606// mat(0, 0) = values[3](0, indv);
607// mat(1, 0) = values[3](1, indv);
608// edge->face->surf->evalSurface_into(mat, res);
609
610// gsDebug << "curve3(indv): " << res.transpose() << std::endl;
611
612 column++;
613 }
614 }
615 }
616
617
622 static
623 bool turnCurveAround(const bool curveLoopAround, const int curveId)
624 {
625 if ( (!curveLoopAround && (curveId == 2 || curveId == 3)) ||
626 (curveLoopAround && (curveId == 0 || curveId == 3)) )
627 {
628 return true;
629 }
630 else
631 {
632 return false;
633 }
634 }
635
636
641 static
642 bool turnCurveLoopAround(boxSide side)
643 {
644 if (side == boundary::west ||
645 side == boundary::south ||
646 side == boundary::back)
647 {
648 return true;
649 }
650 else
651 {
652 return false;
653 }
654 }
655
656
657
658
660 int getInternalIndexOfCurve(HalfEdge* edge) const
661 {
662 return edge->face->indexOfEdge(edge);
663 }
664
670 void getHexEdges(std::vector<HalfEdge*>& hex, HalfEdge* edge)
671 {
672 // set the west face as the first face of the volume
673 // and set the first edge of the west face as the first edge of the
674 // first face
675 hex.push_back(edge);
676
677 hex.push_back(getEastEdge(edge));
678
679 hex.push_back(getSouthEdge(edge));
680
681 hex.push_back(getNorthEdge(edge));
682
683 hex.push_back(getFrontEdge(edge));
684
685 hex.push_back(getBackEdge(edge));
686
687 }
688
690 HalfEdge* getEastEdge(HalfEdge* edge)
691 {
692 edge = edge->next;
693 edge = edge->mate;
694 edge = edge->moveAlongEdge(2);
695 edge = edge->mate;
696 edge = edge->next;
697 return edge;
698 }
699
701 HalfEdge* getSouthEdge(HalfEdge* edge)
702 {
703 edge = edge->mate;
704 edge = edge->prev;
705 return edge;
706 }
707
709 HalfEdge* getNorthEdge(HalfEdge* edge)
710 {
711 edge = edge->moveAlongEdge(2);
712 edge = edge->mate;
713 edge = edge->next;
714 return edge;
715 }
716
718 HalfEdge* getFrontEdge(HalfEdge* edge)
719 {
720 edge = edge->next;
721 edge = edge->mate;
722 edge = edge->next;
723 return edge;
724 }
725
727 HalfEdge* getBackEdge(HalfEdge* edge)
728 {
729 edge = edge->prev;
730 edge = edge->mate;
731 edge = edge->prev;
732 return edge;
733 }
734
735
736
737public:
738 std::vector<HalfFace*> face;
739};
740
741} // namespace gismo
static boxSide getEnd(short_t dim)
helper for iterating on sides of an n-dimensional box
Definition gsBoundary.h:176
static boxSide getFirst(short_t)
helper for iterating on sides of an n-dimensional box
Definition gsBoundary.h:160
Provides structs and classes related to interfaces and boundaries.
#define GISMO_ERROR(message)
Definition gsDebug.h:118
#define gsWarn
Definition gsDebug.h:50
Provides declaration of data fitting algorithms by least squares approximation.
Provides gsSolidElement class - interface for an element (vertex, edge or face) of a solid.
Provides declaration of gsSolid class, a boundary-represented solid.
Provides declaration of Volume abstract interface.
The G+Smo namespace, containing all definitions for the library.