29 class gsVolumeBlock :
public gsSolidElement<T>
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;
41 gsVolumeBlock() : SolidElement() { }
43 explicit gsVolumeBlock(
int const& i) : SolidElement(i) { }
45 explicit gsVolumeBlock(std::vector<HalfFace*>
const & hfaces)
48 typename std::vector<HalfFace*>::const_iterator it;
49 for (it = hfaces.begin();it!=hfaces.end();++it)
55 virtual ~gsVolumeBlock()
66 boxSide getSideOfHexahedron(
const unsigned faceId)
73 HalfEdge* edge = face[0]->loop[0];
74 std::vector<HalfEdge* > hex;
75 getHexEdges(hex, edge);
77 HalfFace* myFace = face[faceId];
81 for (
size_t edgeIndx = 0; edgeIndx < hex.size(); edgeIndx++)
83 HalfEdge* faceEdge = hex[edgeIndx];
86 HalfEdge* e = myFace->loop[0];
87 for (
unsigned i = 0; i < 4; i++)
91 sideIndex =
static_cast<int>(edgeIndx);
100 gsWarn <<
"Didn't transform face with id = " << faceId <<
"\n";
103 return boxSide(sideIndex + 1);
114 bool isHexahedron()
const
117 if (face.size() != 6)
123 for (
unsigned idFace = 0; idFace != face.size(); idFace++)
125 HalfFace* myFace = face[idFace];
127 if (1 < myFace->loopN())
129 gsWarn <<
"Input volume has a hole in its face. "
134 gsPlanarDomain<T>& domain = myFace->surf->domain();
137 gsCurveLoop<T>& curveLoop = domain.loop(0);
139 if (curveLoop.numCurves() != 4)
148 gsTensorBSpline<3, T> getTensorBSplineVolume(
int numSamplePoints,
149 int numInternalKnots,
157 "Function getVolume can not tranform VolumeBlock into "
158 "gsVolume if VolumeBlock is not hexahedron.\n");
165 getUniformPoints(numSamplePoints, params, points, eps);
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);
171 gsTensorBSplineBasis<3, T> basis(kv1, kv2, kv3);
173 gsDebugVar(kv1.detail());
175 gsFitting<T> fitting(params, points, basis);
176 fitting.compute(lambda);
179 std::vector<T> errors;
180 fitting.get_Error(errors, 1);
181 gsDebug <<
"Maximum error is: " << *std::max_element(errors.begin(),
186 gsGeometry<T>* geo = fitting.result();
188 gsTensorBSpline<3, T>* bspline =
dynamic_cast<gsTensorBSpline<3, T>*
> (geo);
192 GISMO_ERROR(
"Problems with casting gsGeometry to gsTensorBspline");
204 void getUniformPoints(
const int n,
209 gsMatrix<T> bParams, bPoints;
210 getUniformBoundaryPoints(n, bParams, bPoints, eps);
212 typedef std::pair<std::pair<T, T>, T> tuple;
215 std::map<tuple, int> map;
216 for (
int col = 0; col < bParams.cols(); col++)
218 tuple t = makeTuple(bParams(0, col), bParams(1, col), bParams(2, col));
223 const gsVector<T> p000 = bPoints.col(map[makeTuple(0., 0., 0.)]);
224 const gsVector<T> p001 = bPoints.col(map[makeTuple(0., 0., 1.)]);
225 const gsVector<T> p010 = bPoints.col(map[makeTuple(0., 1., 0.)]);
226 const gsVector<T> p011 = bPoints.col(map[makeTuple(0., 1., 1.)]);
227 const gsVector<T> p100 = bPoints.col(map[makeTuple(1., 0., 0.)]);
228 const gsVector<T> p101 = bPoints.col(map[makeTuple(1., 0., 1.)]);
229 const gsVector<T> p110 = bPoints.col(map[makeTuple(1., 1., 0.)]);
230 const gsVector<T> p111 = bPoints.col(map[makeTuple(1., 1., 1.)]);
232 const int numPoints = (n - 2) * (n - 2) * (n - 2) + bParams.cols();
233 params.resize(3, numPoints);
234 points.resize(3, numPoints);
238 for (
int indx = 1; indx != n - 1; indx++)
240 const T x = (indx * 1.0) / (n - 1);
242 for (
int indy = 1; indy != n - 1; indy++)
244 const T y = (indy * 1.0) / (n - 1);
246 for (
int indz = 1; indz != n - 1; indz++)
248 const T z = (indz * 1.0) / (n - 1);
251 params(0, column) = x;
252 params(1, column) = y;
253 params(2, column) = z;
258 const gsVector<T> A =
259 (1 - x) * bPoints.col(map[makeTuple(0, y, z)]) +
260 x * bPoints.col(map[makeTuple(1, y, z)]);
262 const gsVector<T> B =
263 (1 - y) * bPoints.col(map[makeTuple(x, 0, z)]) +
264 y * bPoints.col(map[makeTuple(x, 1, z)]);
266 const gsVector<T> C =
267 (1 - z) * bPoints.col(map[makeTuple(x, y, 0)]) +
268 z * bPoints.col(map[makeTuple(x, y, 1)]);
271 const gsVector<T> AB =
272 (1 - x) * (1 - y) * bPoints.col(map[makeTuple(0, 0, z)]) +
273 (1 - x) * y * bPoints.col(map[makeTuple(0, 1, z)]) +
274 x * (1 - y) * bPoints.col(map[makeTuple(1, 0, z)]) +
275 x * y * bPoints.col(map[makeTuple(1, 1, z)]);
277 const gsVector<T> BC =
278 (1 - y) * (1 - z) * bPoints.col(map[makeTuple(x, 0, 0)]) +
279 (1 - y) * z * bPoints.col(map[makeTuple(x, 0, 1)]) +
280 y * (1 - z) * bPoints.col(map[makeTuple(x, 1, 0)]) +
281 y * z * bPoints.col(map[makeTuple(x, 1, 1)]);
283 const gsVector<T> AC =
284 (1 - x) * (1 - z) * bPoints.col(map[makeTuple(0, y, 0)]) +
285 (1 - x) * z * bPoints.col(map[makeTuple(0, y, 1)]) +
286 x * (1 - z) * bPoints.col(map[makeTuple(1, y, 0)]) +
287 x * z * bPoints.col(map[makeTuple(1, y, 1)]);
290 const gsVector<T> ABC =
291 (1 - x) * ((1 - y) * ((1 - z) * p000 + z * p001) +
292 y * ((1 - z) * p010 + z * p011)) +
293 x * ((1 - y) * ((1 - z) * p100 + z * p101) +
294 y * ((1 - z) * p110 + z * p111));
296 points.col(column) = A + B + C - AB - BC - AC + ABC;
305 for (
int col = 0; col < bPoints.cols(); ++col)
307 points.col(column) = bPoints.col(col);
308 params.col(column) = bParams.col(col);
318 void getUniformBoundaryPoints(
const int n,
319 gsMatrix<T>& params3D,
323 HalfEdge* edge = face[0]->loop[0];
324 std::vector<HalfEdge* > hex;
325 getHexEdges(hex, edge);
327 int nmbOfPts = 6 * (n * n + 4);
328 points .resize(3, nmbOfPts);
329 params3D.resize(3, nmbOfPts);
331 gsVector<T> params1D(n);
332 for (
int index = 0; index != n; index++)
334 params1D(index) = index * 1.0 / (n - 1);
344 bool turnAround = turnCurveLoopAround(side);
345 T fixedConstant = side.parameter() ? 1.0 : 0.0;
353 int fixed = side.direction();
354 int first = (fixed == 0) ? 1 : 0;
355 int second = (fixed == 2) ? 1 : 2;
370 std::vector<gsVector<T> > faceBoundaryParams;
371 HalfEdge* faceEdge = hex[side - 1];
376 for (
int curveId = 0; curveId < 4; curveId++)
378 HalfEdge* edge2 = faceEdge->moveAlongEdge(curveId);
381 int index = edge2->face->indexOfEdge(edge2);
384 edge2->face->surf->getPhysicalyUniformCurveParameters(
385 0, index, n, params, eps);
388 gsMatrix<T> curvePoints;
389 edge2->face->surf->evalCurve_into(
390 0, index, params.transpose(), curvePoints);
393 bool turnCurve = turnCurveAround(turnAround, curveId);
400 T curveConstant = 0.0;
401 if ( (turnAround && (curveId == 2 || curveId == 3)) ||
402 (!turnAround && (curveId == 1 || curveId == 2)) )
411 int curveConstantIndex = first;
412 int curveNonConstIndex = second;
413 if (curveId == 0 || curveId == 2)
415 curveConstantIndex = second;
416 curveNonConstIndex = first;
420 for (
int col = 0; col < n; col++)
422 params3D(fixed, column) = fixedConstant;
423 params3D(curveConstantIndex, column) = curveConstant;
424 params3D(curveNonConstIndex, column) = params1D(col);
428 points.col(column) = curvePoints.col(n - 1 - col);
432 points.col(column) = curvePoints.col(col);
448 params.reverseInPlace();
451 faceBoundaryParams.push_back(params);
458 bool switch1and3curve =
false;
459 if (side == boundary::east ||
460 side == boundary::front ||
461 side == boundary::north)
463 switch1and3curve =
true;
469 gsMatrix<T> cpParams;
470 modifiedCoonsPatch(hex[side - 1], faceBoundaryParams,
471 params1D, cpParams, switch1and3curve);
473 gsMatrix<T> cpPoints;
474 faceEdge->face->surf->evalSurface_into(cpParams, cpPoints);
477 for (
int indv = 0; indv != n - 2; indv++)
479 for (
int indu = 0; indu != n - 2; indu++)
481 params3D(fixed, column) = fixedConstant;
482 params3D(first, column) = params1D(indu + 1);
483 params3D(second, column) = params1D(indv + 1);
485 points.col(column) = cpPoints.col(indv * (n - 2) + indu);
495 static std::pair<std::pair<T, T>, T> makeTuple(T x, T y, T z)
497 return std::make_pair(std::make_pair(x, y), z);
519 void modifiedCoonsPatch(HalfEdge* edge,
520 const std::vector<gsVector<T> >& boundaryParams,
521 const gsVector<T>& params1D,
522 gsMatrix<T>& cpPoints,
523 const bool switch1and3curve)
525 int n = boundaryParams[0].size();
526 int m = boundaryParams[1].size();
528 cpPoints.resize(2, (n - 2) * (m - 2));
531 std::vector<gsMatrix<T> > values;
532 for (
int curveId = 0; curveId != 4; curveId++)
534 HalfEdge* curveEdge = edge->moveAlongEdge(curveId);
535 int internalIndex = getInternalIndexOfCurve(curveEdge);
536 gsCurve<T>& curve = edge->face->surf->getCurve(0, internalIndex);
538 gsMatrix<T> curvePoints;
539 curve.eval_into(boundaryParams[curveId].transpose(), curvePoints);
540 values.push_back(curvePoints);
544 gsVector<T> c00 = values[0].col(0);
545 gsVector<T> c01 = values[0].col(n - 1);
547 gsVector<T> c20 = values[2].col(0);
548 gsVector<T> c21 = values[2].col(n - 1);
554 for (
int indv = 1; indv != n - 1; indv++)
556 T v = params1D[indv];
559 for (
int indu = 1; indu != m - 1; indu++)
561 T u = params1D[indu];
562 cpPoints.col(column) = (1 - v) * values[0].col(indu) +
563 v * values[2].col(indu)
564 - (1 - v) * (1 - u) * c00
570 if (switch1and3curve)
572 vec = (1 - u) * values[3].col(indv) +
573 u * values[1].col(indv);
577 vec = (1 - u) * values[1].col(indv) +
578 u * values[3].col(indv);
581 cpPoints.col(column) += vec;
630 bool turnCurveAround(
const bool curveLoopAround,
const int curveId)
632 if ( (!curveLoopAround && (curveId == 2 || curveId == 3)) ||
633 (curveLoopAround && (curveId == 0 || curveId == 3)) )
649 bool turnCurveLoopAround(boxSide side)
651 if (side == boundary::west ||
652 side == boundary::south ||
653 side == boundary::back)
667 int getInternalIndexOfCurve(HalfEdge* edge)
const
669 return edge->face->indexOfEdge(edge);
677 void getHexEdges(std::vector<HalfEdge*>& hex, HalfEdge* edge)
684 hex.push_back(getEastEdge(edge));
686 hex.push_back(getSouthEdge(edge));
688 hex.push_back(getNorthEdge(edge));
690 hex.push_back(getFrontEdge(edge));
692 hex.push_back(getBackEdge(edge));
697 HalfEdge* getEastEdge(HalfEdge* edge)
701 edge = edge->moveAlongEdge(2);
708 HalfEdge* getSouthEdge(HalfEdge* edge)
716 HalfEdge* getNorthEdge(HalfEdge* edge)
718 edge = edge->moveAlongEdge(2);
725 HalfEdge* getFrontEdge(HalfEdge* edge)
734 HalfEdge* getBackEdge(HalfEdge* edge)
745 std::vector<HalfFace*> face;
#define gsDebug
Definition: gsDebug.h:61
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.
Provides declaration of Volume abstract interface.
Provides declaration of data fitting algorithms by least squares approximation.
static boxSide getEnd(short_t dim)
helper for iterating on sides of an n-dimensional box
Definition: gsBoundary.h:176
#define gsWarn
Definition: gsDebug.h:50
Provides gsSolidElement class - interface for an element (vertex, edge or face) of a solid...
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
Provides declaration of gsSolid class, a boundary-represented solid.