11 #ifndef BEMBEL_SRC_GEOMETRY_PATCH_HPP_
12 #define BEMBEL_SRC_GEOMETRY_PATCH_HPP_
42 Patch(
const std::vector<Eigen::Matrix<double, -1, -1>> &control_points,
43 const std::vector<double> &knots_x,
44 const std::vector<double> &knots_y) {
63 inline void init_Patch(
const std::vector<Eigen::Matrix<double, -1, -1>> &xyzw,
64 const std::vector<double> &x_knots,
65 const std::vector<double> &y_knots) {
66 assert(xyzw.size() == 4);
67 const int xyzw_cols = xyzw[0].cols();
68 const int xyzw_rows = xyzw[0].rows();
69 unique_knots_x_ = Spl::ExtractUniqueKnotVector(x_knots);
70 unique_knots_y_ = Spl::ExtractUniqueKnotVector(y_knots);
71 const int xnumpatch = unique_knots_x_.size() - 1;
72 const int ynumpatch = unique_knots_y_.size() - 1;
73 polynomial_degree_x_ = x_knots.size() - xyzw_cols;
74 polynomial_degree_y_ = y_knots.size() - xyzw_rows;
75 data_.resize(4 * (polynomial_degree_x_ * xnumpatch * polynomial_degree_y_ *
80 if (unique_knots_x_.size() == 2 && unique_knots_y_.size() == 2) {
81 for (
int i = 0; i < 4; i++) {
82 Eigen::Matrix<double, -1, 1> tmp =
Spl::Unroll(xyzw[i]);
83 for (
int j = 0; j < tmp.rows(); j++)
data_[j * 4 + i] = (tmp[j]);
91 x_knots, y_knots, unique_knots_x_, unique_knots_y_,
92 polynomial_degree_x_, polynomial_degree_y_);
94 for (
int i = 0; i < 4; i++) {
95 Eigen::Matrix<double, -1, 1> tmp =
98 for (
int j = 0; j < tmp.rows(); j++)
data_[j * 4 + i] = (tmp[j]);
115 Eigen::Vector3d
eval(
const Eigen::Vector2d &reference_point)
const {
116 const int x_location =
117 Spl::FindLocationInKnotVector(reference_point(0), unique_knots_x_);
118 const int y_location =
119 Spl::FindLocationInKnotVector(reference_point(1), unique_knots_y_);
120 const int numy = (unique_knots_y_.size() - 1) * polynomial_degree_y_;
121 const double scaledx =
122 Spl::Rescale(reference_point(0), unique_knots_x_[x_location],
123 unique_knots_x_[x_location + 1]);
124 const double scaledy =
125 Spl::Rescale(reference_point(1), unique_knots_y_[y_location],
126 unique_knots_y_[y_location + 1]);
128 double *xbasis =
new double[polynomial_degree_x_];
129 double *ybasis =
new double[polynomial_degree_y_];
131 Bembel::Basis::ShapeFunctionHandler::evalBasis(polynomial_degree_x_ - 1,
133 Bembel::Basis::ShapeFunctionHandler::evalBasis(polynomial_degree_y_ - 1,
136 double tmp[4] = {0., 0., 0., 0.};
138 for (
int i = 0; i < polynomial_degree_x_; i++) {
139 for (
int j = 0; j < polynomial_degree_y_; j++) {
140 const double tpbasisval = xbasis[i] * ybasis[j];
141 const int accs = 4 * (numy * (polynomial_degree_x_ * x_location + i) +
142 polynomial_degree_y_ * y_location + j);
144 for (
int k = 0; k < 4; k++) tmp[k] +=
data_[accs + k] * tpbasisval;
151 Eigen::Vector3d out(tmp[0], tmp[1], tmp[2]);
164 const Eigen::Vector2d &reference_point)
const {
165 const int x_location =
166 Spl::FindLocationInKnotVector(reference_point(0), unique_knots_x_);
167 const int y_location =
168 Spl::FindLocationInKnotVector(reference_point(1), unique_knots_y_);
169 const int numy = (unique_knots_y_.size() - 1) * polynomial_degree_y_;
170 const double scaledx =
171 Spl::Rescale(reference_point(0), unique_knots_x_[x_location],
172 unique_knots_x_[x_location + 1]);
173 const double scaledy =
174 Spl::Rescale(reference_point(1), unique_knots_y_[y_location],
175 unique_knots_y_[y_location + 1]);
177 double *xbasis =
new double[polynomial_degree_x_];
178 double *ybasis =
new double[polynomial_degree_y_];
179 double *xbasisD =
new double[polynomial_degree_x_];
180 double *ybasisD =
new double[polynomial_degree_y_];
182 Bembel::Basis::ShapeFunctionHandler::evalBasis(polynomial_degree_x_ - 1,
184 Bembel::Basis::ShapeFunctionHandler::evalBasis(polynomial_degree_y_ - 1,
186 Bembel::Basis::ShapeFunctionHandler::evalDerBasis(polynomial_degree_x_ - 1,
188 Bembel::Basis::ShapeFunctionHandler::evalDerBasis(polynomial_degree_y_ - 1,
191 double tmp[4] = {0., 0., 0., 0.};
192 double tmpDx[4] = {0., 0., 0., 0.};
193 double tmpDy[4] = {0., 0., 0., 0.};
195 for (
int i = 0; i < polynomial_degree_x_; i++) {
196 for (
int j = 0; j < polynomial_degree_y_; j++) {
197 const double tpbasisval = xbasis[i] * ybasis[j];
198 const double tpbasisvalDx = xbasisD[i] * ybasis[j];
199 const double tpbasisvalDy = xbasis[i] * ybasisD[j];
200 const int accs = 4 * (numy * (polynomial_degree_x_ * x_location + i) +
201 polynomial_degree_y_ * y_location + j);
206 for (
int k = 0; k < 4; k++) {
207 tmp[k] +=
data_[accs + k] * tpbasisval;
208 tmpDx[k] +=
data_[accs + k] * tpbasisvalDx;
209 tmpDy[k] +=
data_[accs + k] * tpbasisvalDy;
219 Eigen::Matrix<double, 3, 2> out;
223 double bot = 1. / (tmp[3] * tmp[3]);
226 for (
int k = 0; k < 3; k++) {
227 out(k, 0) = (tmpDx[k] * tmp[3] - tmp[k] * tmpDx[3]) * bot;
228 out(k, 1) = (tmpDy[k] * tmp[3] - tmp[k] * tmpDy[3]) * bot;
241 const Eigen::Vector2d &reference_point)
const {
242 Eigen::Matrix<double, 3, 2> jac =
evalJacobian(reference_point);
243 return jac.col(0).cross(jac.col(1));
257 inline Eigen::Vector3d
eval(
double x,
double y)
const {
258 return eval(Eigen::Vector2d(x, y));
267 inline Eigen::Matrix<double, 3, 2>
evalJacobian(
double x,
double y)
const {
277 inline Eigen::Matrix<double, 3, 1>
evalNormal(
double x,
double y)
const {
295 const Eigen::Vector2d &ref_pt,
double w,
296 const Eigen::Vector2d &xi)
const {
297 const int x_location =
298 Spl::FindLocationInKnotVector(ref_pt(0), unique_knots_x_);
299 const int y_location =
300 Spl::FindLocationInKnotVector(ref_pt(1), unique_knots_y_);
301 const int numy = (unique_knots_y_.size() - 1) * polynomial_degree_y_;
302 const double scaledx = Spl::Rescale(ref_pt(0), unique_knots_x_[x_location],
303 unique_knots_x_[x_location + 1]);
304 const double scaledy = Spl::Rescale(ref_pt(1), unique_knots_y_[y_location],
305 unique_knots_y_[y_location + 1]);
310 new double[2 * (polynomial_degree_x_ + polynomial_degree_y_) + 12];
311 for (
int i = 0; i < 12; ++i) buffer[i] = 0;
313 double *tmp = buffer;
314 double *tmpDx = tmp + 4;
315 double *tmpDy = tmpDx + 4;
316 double *xbasis = tmpDy + 4;
317 double *ybasis = xbasis + polynomial_degree_x_;
318 double *xbasisD = ybasis + polynomial_degree_y_;
319 double *ybasisD = xbasisD + polynomial_degree_x_;
321 Bembel::Basis::ShapeFunctionHandler::evalBasis(polynomial_degree_x_ - 1,
323 Bembel::Basis::ShapeFunctionHandler::evalBasis(polynomial_degree_y_ - 1,
325 Bembel::Basis::ShapeFunctionHandler::evalDerBasis(polynomial_degree_x_ - 1,
327 Bembel::Basis::ShapeFunctionHandler::evalDerBasis(polynomial_degree_y_ - 1,
330 for (
int i = 0; i < polynomial_degree_x_; ++i) {
331 for (
int j = 0; j < polynomial_degree_y_; ++j) {
332 const double tpbasisval = xbasis[i] * ybasis[j];
333 const double tpbasisvalDx = xbasisD[i] * ybasis[j];
334 const double tpbasisvalDy = xbasis[i] * ybasisD[j];
335 const int accs = 4 * (numy * (polynomial_degree_x_ * x_location + i) +
336 polynomial_degree_y_ * y_location + j);
340 for (
int k = 0; k < 4; ++k) {
341 tmp[k] +=
data_[accs + k] * tpbasisval;
342 tmpDx[k] +=
data_[accs + k] * tpbasisvalDx;
343 tmpDy[k] +=
data_[accs + k] * tpbasisvalDy;
348 const double bot = 1. / tmp[3];
349 const double botsqr = bot * bot;
351 (*srf_pt)(0) = xi(0);
352 (*srf_pt)(1) = xi(1);
354 (*srf_pt)(3) = tmp[0] * bot;
355 (*srf_pt)(4) = tmp[1] * bot;
356 (*srf_pt)(5) = tmp[2] * bot;
357 (*srf_pt)(6) = (tmpDx[0] * tmp[3] - tmp[0] * tmpDx[3]) * botsqr;
358 (*srf_pt)(7) = (tmpDx[1] * tmp[3] - tmp[1] * tmpDx[3]) * botsqr;
359 (*srf_pt)(8) = (tmpDx[2] * tmp[3] - tmp[2] * tmpDx[3]) * botsqr;
360 (*srf_pt)(9) = (tmpDy[0] * tmp[3] - tmp[0] * tmpDy[3]) * botsqr;
361 (*srf_pt)(10) = (tmpDy[1] * tmp[3] - tmp[1] * tmpDy[3]) * botsqr;
362 (*srf_pt)(11) = (tmpDy[2] * tmp[3] - tmp[2] * tmpDy[3]) * botsqr;
372 int polynomial_degree_x_;
373 int polynomial_degree_y_;
388 if (patch.unique_knots_y_.size() == 2 && patch.unique_knots_x_.size() == 2) {
393 const int xchips = patch.unique_knots_x_.size() - 1;
394 const int ychips = patch.unique_knots_y_.size() - 1;
396 const int xp = patch.polynomial_degree_x_;
397 const int yp = patch.polynomial_degree_y_;
398 const int numy = ychips * yp;
400 std::vector<Patch> out(xchips * ychips);
402 for (
int ix = 0; ix < xchips; ix++) {
403 for (
int iy = 0; iy < ychips; iy++) {
404 const int index = ix * ychips + iy;
406 out[index].unique_knots_x_ = {0, 1};
407 out[index].unique_knots_y_ = {0, 1};
408 out[index].polynomial_degree_x_ = xp;
409 out[index].polynomial_degree_y_ = yp;
410 out[index].data_.reserve(xp * yp * 4);
414 for (
int ix = 0; ix < xchips; ix++) {
415 for (
int iy = 0; iy < ychips; iy++) {
416 const int index = ix * ychips + iy;
417 for (
int jx = 0; jx < xp; jx++) {
418 for (
int jy = 0; jy < yp; jy++) {
419 const int accs = 4 * (numy * (xp * ix + jx) + yp * iy + jy);
420 for (
int k = 0; k < 4; k++) {
421 out[index].data_.push_back(patch.data_[accs + k]);
438 const std::vector<Patch> &patches) noexcept {
439 std::vector<Patch> out;
440 const int input_size = patches.size();
442 for (
int i = 0; i < input_size; i++) {
445 const int tmp_size = tmp.size();
447 for (
int j = 0; j < tmp_size; j++) out.push_back(tmp[j]);
Eigen::Matrix< double, 3, 1 > evalNormal(double x, double y) const
Evaluate normal vector at given point.
Eigen::Matrix< double, 3, 2 > evalJacobian(double x, double y) const
Evaluate Jacobian of the parametrization at given point.
Eigen::Matrix< double, 3, 2 > evalJacobian(const Eigen::Vector2d &reference_point) const
Evaluate Jacobian of the parametrization at given point.
Eigen::Matrix< double, 3, 1 > evalNormal(const Eigen::Vector2d &reference_point) const
Evaluate normal vector at given point.
void init_Patch(const std::vector< Eigen::Matrix< double, -1, -1 >> &xyzw, const std::vector< double > &x_knots, const std::vector< double > &y_knots)
init
Patch(const std::vector< Eigen::Matrix< double, -1, -1 >> &control_points, const std::vector< double > &knots_x, const std::vector< double > &knots_y)
Constructor of a Patch.
Eigen::Vector3d eval(double x, double y) const
Evaluate patch at given point.
Eigen::Vector3d eval(const Eigen::Vector2d &reference_point) const
Evaluate patch at given point.
std::vector< double > data_
getter
void updateSurfacePoint(SurfacePoint *srf_pt, const Eigen::Vector2d &ref_pt, double w, const Eigen::Vector2d &xi) const
Updates the surface point and returns the physical point and the derivatives there.
Eigen::Matrix< double, 12, 1 > SurfacePoint
typedef of SurfacePoint
Eigen::SparseMatrix< T > MakeProjection(const std::vector< T > &x_knots, const std::vector< T > &y_knots, const std::vector< T > &x_unique_knots, const std::vector< T > &y_unique_knots, const int polynomial_degree_x, const int polynomial_degree_y) noexcept
implements Bezier extraction via the solution of an interpolation problem.
Eigen::Matrix< T, -1, 1 > Unroll(const Eigen::Matrix< T, -1, -1 > &input_matrix) noexcept
Tiny helper functions.
Routines for the evalutation of pointwise errors.
std::vector< Patch > PatchShredder(const Patch &patch) noexcept
This function cuts a patch along internal knots, if any.