limited volume meshing to boundary layer only
[engrid-github.git] / src / libengrid / optimisenormalvector.cpp
blob11a226c8bdf0199074b8c7a226cc727a2dfe2d7f
1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 // + +
3 // + This file is part of enGrid. +
4 // + +
5 // + Copyright 2008-2014 enGits GmbH +
6 // + +
7 // + enGrid is free software: you can redistribute it and/or modify +
8 // + it under the terms of the GNU General Public License as published by +
9 // + the Free Software Foundation, either version 3 of the License, or +
10 // + (at your option) any later version. +
11 // + +
12 // + enGrid is distributed in the hope that it will be useful, +
13 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
14 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
15 // + GNU General Public License for more details. +
16 // + +
17 // + You should have received a copy of the GNU General Public License +
18 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
19 // + +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 #include "optimisenormalvector.h"
23 #include "geometrytools.h"
25 OptimiseNormalVector::OptimiseNormalVector(bool use_grouping, double grouping_angle)
27 m_UseGrouping = use_grouping;
28 m_GroupingAngle = grouping_angle;
31 void OptimiseNormalVector::addConstraint(vec3_t n)
33 m_Constraints.append(n);
36 void OptimiseNormalVector::addFace(vec3_t n)
38 if (m_UseGrouping) {
39 bool found = false;
40 foreach (vec3_t nf, m_Faces) {
41 if (GeometryTools::angle(n, nf) < m_GroupingAngle) {
42 found = true;
43 break;
46 if (!found) {
47 m_Faces.append(n);
49 } else {
50 m_Faces.append(n);
54 double OptimiseNormalVector::func(vec3_t n)
56 double hf_min = 1;
57 double hf_max = -1;
58 double hc = 0;
59 vec3_t n0 = n;
60 n0.normalise();
61 double err = 0;
62 foreach (vec3_t nc, m_Constraints) {
63 nc.normalise();
64 double h = nc*n0;
65 hc = max(h, fabs(hc));
67 foreach (vec3_t nf, m_Faces) {
68 nf.normalise();
69 double h = nf*n0;
70 hf_min = min(h, hf_min);
71 hf_max = max(h, hf_max);
72 err += sqr(1 - h);
74 if (m_UseGrouping) {
75 err += sqr(hc);
76 } else {
77 err = sqr(hc) + sqr(1 - hf_min) + sqr(1 - hf_max);
79 return err;
82 vec3_t OptimiseNormalVector::optimise(vec3_t n)
84 int count = 0;
85 computeDerivatives(n);
86 n.normalise();
87 double scale = 0.1;
88 while (count < 100 && scale > 1e-4) {
89 double err1 = func(n);
90 vec3_t dn = -1.0*grad_f;
91 dn -= (n*dn)*n;
92 if (grad_f.abs() > 1e-10) {
93 dn.normalise();
95 double relax = min(scale, scale*grad_f.abs());
96 dn *= relax;
97 vec3_t n_old = n;
98 n += dn;
99 n.normalise();
100 double err2 = func(n);
101 if (err2 > err1) {
102 scale *= 0.1;
103 n = n_old;
105 ++count;
106 computeDerivatives(n);
108 return n;
111 vec3_t OptimiseNormalVector::operator()(vec3_t n)
113 vec3_t n_opt = optimise(n);
114 if (!checkVector(n_opt)) {
115 n_opt = n;
117 n_opt.normalise();
118 return n_opt;