various improvements to speed up surface meshing of BRL-CAD geometries
[engrid.git] / src / libengrid / cadinterface.cpp
blobf0e15afac1f2c94582dec390f1271ce2f556bc87
1 //
2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + +
4 // + This file is part of enGrid. +
5 // + +
6 // + Copyright 2008-2013 enGits GmbH +
7 // + +
8 // + enGrid is free software: you can redistribute it and/or modify +
9 // + it under the terms of the GNU General Public License as published by +
10 // + the Free Software Foundation, either version 3 of the License, or +
11 // + (at your option) any later version. +
12 // + +
13 // + enGrid is distributed in the hope that it will be useful, +
14 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
15 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
16 // + GNU General Public License for more details. +
17 // + +
18 // + You should have received a copy of the GNU General Public License +
19 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
20 // + +
21 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 //
23 #include "cadinterface.h"
25 #include <QTextStream>
26 #include <QFile>
28 CadInterface::CadInterface()
30 QFile file(":/resources/misc/raysphere_fine.dat");
31 //QFile file(":/resources/misc/raysphere.dat");
32 //QFile file(":/resources/misc/raysphere_coarse.dat");
33 file.open(QIODevice::ReadOnly);
34 QTextStream s(&file);
35 int N;
36 s >> N;
37 m_RayPoints.resize(N);
38 for (int i = 0; i < N; ++i) {
39 for (int j = 0; j < 3; ++j) {
40 s >> m_RayPoints[i][j];
42 m_RayPoints[i].normalise();
44 m_LastRadius = 1e99;
45 m_LastNormal = vec3_t(0,0,0);
46 setName("generic CAD interface");
47 m_ShootRayImplemented = false;
48 getSet("surface meshing", "critical length for node snapping", 0.1, m_CriticalSnapLength);
51 void CadInterface::setForegroundGrid(vtkUnstructuredGrid *grid)
53 m_FGrid = grid;
54 m_FPart.trackGrid(m_FGrid);
59 vec3_t CadInterface::snap(vec3_t x, bool correct_curvature)
62 double L_best = 1e99;
63 double r_best;
64 vec3_t x_best;
65 vec3_t n_best;
66 bool no_hit = true;
67 foreach (vec3_t x_ray, m_RayPoints) {
68 double r_hit;
69 vec3_t x_hit;
70 vec3_t n_hit;
71 vec3_t v = x_ray;
73 // standard ray
74 if (shootRay(x, v, x_hit, n_hit, r_hit) != Miss) {
75 double L = (x_hit - x).abs();
76 if (L < L_best) {
77 x_best = x_hit;
78 n_best = n_hit;
79 r_best = r_hit;
80 L_best = L;
81 no_hit = false;
83 v = n_hit;
85 // shoot a "far-side return ray" ...
86 if (shootRay(x_hit, -1*x_ray, x_hit, n_hit, r_hit)) {
87 double L = (x_hit - x).abs();
88 if (L < L_best) {
89 x_best = x_hit;
90 n_best = n_hit;
91 r_best = r_hit;
92 L_best = L;
93 no_hit = false;
97 // re-shoot standard ray with surface normal
98 if (shootRay(x, v, x_hit, n_hit, r_hit) != Miss) {
99 double L = (x_hit - x).abs();
100 if (L < L_best) {
101 x_best = x_hit;
102 n_best = n_hit;
103 r_best = r_hit;
104 L_best = L;
105 no_hit = false;
109 // re-shoot standard ray with surface normal in opposite direction
110 v *= -1;
111 if (shootRay(x, v, x_hit, n_hit, r_hit) != Miss) {
112 double L = (x_hit - x).abs();
113 if (L < L_best) {
114 x_best = x_hit;
115 n_best = n_hit;
116 r_best = r_hit;
117 L_best = L;
118 no_hit = false;
124 if (no_hit) {
125 EG_BUG;
128 if (correct_curvature) {
129 x_best = correctCurvature(x_best);
132 m_LastNormal = n_best;
133 m_LastRadius = r_best;
134 return x_best;
137 vec3_t CadInterface::snapNode(vtkIdType id_node, bool correct_curvature)
139 vec3_t x;
140 m_FGrid->GetPoint(id_node, x.data());
141 return snapNode(id_node, x, correct_curvature);
144 vec3_t CadInterface::snapNode(vtkIdType id_node, vec3_t x, bool correct_curvature)
146 vec3_t n = m_FPart.globalNormal(id_node);
147 vec3_t x_proj = projectNode(id_node, x, n, false, correct_curvature);
148 double L_crit = m_CriticalSnapLength*m_FPart.getMinSurfaceStencilEdgeLength(id_node);
149 if ((x - x_proj).abs() < L_crit) {
150 return x_proj;
152 return snap(x, correct_curvature);
155 void CadInterface::notImplemented()
157 QString msg;
158 msg += "The functionality you are trying cannot be provided by the current CAD interface.\n";
159 msg += "You are using a \"" + name() + "\"";
160 EG_ERR_RETURN(msg);
164 vec3_t CadInterface::project(vec3_t x, vec3_t v, bool strict_direction, bool correct_curvature)
166 if (!checkVector(v)) {
167 return x;
169 vec3_t x_proj = x;
170 m_LastNormal = v;
171 m_LastRadius = 1e10;
173 vec3_t x_hit1, n_hit1, x_hit2, n_hit2;
174 double r_hit1, r_hit2;
175 CadInterface::HitType hit_type1, hit_type2;
177 hit_type1 = shootRay(x, v, x_hit1, n_hit1, r_hit1);
178 if (hit_type1 == CadInterface::Miss && !strict_direction) {
179 v *= -1;
180 hit_type1 = shootRay(x, v, x_hit1, n_hit1, r_hit1);
182 if (hit_type1 == CadInterface::Miss) {
183 m_Failed = true;
184 return x;
186 m_Failed = false;
187 v *= -1;
188 x_proj = x_hit1;
189 m_LastNormal = n_hit1;
190 m_LastRadius = r_hit1;
191 if (!strict_direction) {
192 hit_type2 = shootRay(x_hit1, v, x_hit2, n_hit2, r_hit2);
193 if (hit_type2 != CadInterface::Miss) {
194 if ((x - x_hit2).abs() < (x - x_hit1).abs()) {
195 x_proj = x_hit2;
196 m_LastNormal = n_hit2;
197 m_LastRadius = r_hit2;
202 if (correct_curvature) {
203 x_proj = correctCurvature(x_proj);
206 return x_proj;
209 vec3_t CadInterface::projectNode(vtkIdType, vec3_t x, vec3_t v, bool strict_direction, bool correct_curvature)
211 return project(x, v, strict_direction, correct_curvature);
214 vec3_t CadInterface::projectNode(vtkIdType id_node, vec3_t x, bool strict_direction, bool correct_curvature)
216 vec3_t v = m_FPart.globalNormal(id_node);
217 if (!checkVector(v)) {
218 cout << "vector defect (id_node=" << id_node << ")" << endl;
219 return x;
221 return projectNode(id_node, x, v, strict_direction, correct_curvature);
224 vec3_t CadInterface::projectNode(vtkIdType id_node, bool strict_direction, bool correct_curvature)
226 vec3_t x;
227 m_FGrid->GetPoint(id_node, x.data());
228 return projectNode(id_node, x, strict_direction, correct_curvature);
231 double CadInterface::getRadius(vtkIdType id_node)
233 vec3_t x;
234 m_FGrid->GetPoint(id_node, x.data());
235 snapNode(id_node, x, false);
236 return m_LastRadius;