Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CADSurfOCE.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: CADSurf.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: cad object surface methods.
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
37 
38 using namespace std;
39 
40 namespace Nektar
41 {
42 namespace NekMeshUtils
43 {
44 
45 std::string CADSurfOCE::key = GetCADSurfFactory().RegisterCreatorFunction(
46  "oce", CADSurfOCE::create, "CADSurfOCE");
47 
48 void CADSurfOCE::Initialise(int i, TopoDS_Shape in)
49 {
50  // this bit of code changes the units of the cad from mm opencascade
51  // defualt to m
52 
53  m_s = BRep_Tool::Surface(TopoDS::Face(in));
54 
55  if (in.Orientation() == 1)
56  {
57  m_orientation = CADOrientation::eBackwards;
58  }
59 
60  gp_Trsf transform;
61  gp_Pnt ori(0.0, 0.0, 0.0);
62  transform.SetScale(ori, 1.0 / 1000.0);
63  TopLoc_Location mv(transform);
64 
65  in.Move(mv);
66  m_occSurface = BRepAdaptor_Surface(TopoDS::Face(in));
67  m_id = i;
68 
69  m_bounds = Array<OneD, NekDouble>(4);
70  BRepTools::UVBounds(TopoDS::Face(in), m_bounds[0], m_bounds[1], m_bounds[2],
71  m_bounds[3]);
72  m_sas = new ShapeAnalysis_Surface(m_s);
73  m_sas->SetDomain(m_bounds[0], m_bounds[1], m_bounds[2], m_bounds[3]);
74 }
75 
76 Array<OneD, NekDouble> CADSurfOCE::GetBounds()
77 {
78  return m_bounds;
79 }
80 
82 {
83  // has to transfer back to mm
84  gp_Pnt loc(p[0] * 1000.0, p[1] * 1000.0, p[2] * 1000.0);
85 
87 
88  gp_Pnt2d p2 = m_sas->ValueOfUV(loc, 1e-3);
89  uvr[0] = p2.X();
90  uvr[1] = p2.Y();
91 
92  gp_Pnt p3 = m_sas->Value(p2);
93  if (p3.Distance(loc) > 1.0)
94  {
95  cout << "large locuv distance " << p3.Distance(loc) << " " << m_id
96  << endl;
97  }
98 
99  // if the uv returned is slightly off the surface
100  //(which ShapeAnalysis_Surface can do sometimes)
101  if (uvr[0] < m_bounds[0] || uvr[0] > m_bounds[1] || uvr[1] < m_bounds[2] ||
102  uvr[1] > m_bounds[3])
103  {
104  if (uvr[0] < m_bounds[0])
105  {
106  uvr[0] = m_bounds[0];
107  }
108  else if (uvr[0] > m_bounds[1])
109  {
110  uvr[0] = m_bounds[1];
111  }
112  else if (uvr[1] < m_bounds[2])
113  {
114  uvr[1] = m_bounds[2];
115  }
116  else if (uvr[1] > m_bounds[3])
117  {
118  uvr[1] = m_bounds[3];
119  }
120  else
121  {
122  ASSERTL0(false, "Cannot correct locuv");
123  }
124  }
125 
126  return uvr;
127 }
128 
129 NekDouble CADSurfOCE::Curvature(Array<OneD, NekDouble> uv)
130 {
131 #if defined(NEKTAR_DEBUG)
132  Test(uv);
133 #endif
134 
135  Array<OneD, NekDouble> n = N(uv);
136 
137  // a zero normal occurs at a signularity, CurvaturePoint
138  // cannot be sampled here
139  if (n[0] == 0 && n[1] == 0 && n[2] == 0)
140  {
141  return 0.0;
142  }
143 
144  Array<OneD, NekDouble> r = D2(uv);
145 
146  // metric and curvature tensors
147  NekDouble E = r[3] * r[3] + r[4] * r[4] + r[5] * r[5];
148  NekDouble F = r[3] * r[6] + r[4] * r[7] + r[5] * r[8];
149  NekDouble G = r[6] * r[6] + r[7] * r[7] + r[8] * r[8];
150  NekDouble e = n[0] * r[9] + n[1] * r[10] + n[2] * r[11];
151  NekDouble f = n[0] * r[15] + n[1] * r[16] + n[2] * r[17];
152  NekDouble g = n[0] * r[12] + n[1] * r[13] + n[2] * r[14];
153 
154  // if det is zero cannot invert matrix, R=0 so must skip
155  if (E * G - F * F < 1E-30)
156  {
157  return 0.0;
158  }
159 
160  NekDouble K, H;
161 
162  K = (e * g - f * f) / (E * G - F * F);
163  H = 0.5 * (e * G - 2 * f * F + g * E) / (E * G - F * F);
164 
165  NekDouble kv[2];
166  kv[0] = abs(H + sqrt(H * H - K));
167  kv[1] = abs(H - sqrt(H * H - K));
168 
169  return kv[0] > kv[1] ? kv[0] : kv[1];
170 }
171 
172 NekDouble CADSurfOCE::DistanceTo(Array<OneD, NekDouble> p)
173 {
174  gp_Pnt loc(p[0] * 1000.0, p[1] * 1000.0, p[2] * 1000.0);
175 
176  // alternative locuv methods
177  ShapeAnalysis_Surface sas(m_s);
178  sas.SetDomain(m_bounds[0], m_bounds[1], m_bounds[2], m_bounds[3]);
179 
180  gp_Pnt2d p2 = sas.ValueOfUV(loc, 1e-7);
181 
182  gp_Pnt p3 = sas.Value(p2);
183 
184  return p3.Distance(loc);
185 }
186 
187 void CADSurfOCE::ProjectTo(Array<OneD, NekDouble> &tp,
189 {
190  gp_Pnt loc(tp[0] * 1000.0, tp[1] * 1000.0, tp[2] * 1000.0);
191 
192  // alternative locuv methods
193  ShapeAnalysis_Surface sas(m_s);
194  sas.SetDomain(m_bounds[0], m_bounds[1], m_bounds[2], m_bounds[3]);
195 
196  gp_Pnt2d p2 = sas.ValueOfUV(loc, 1e-7);
197 
198  gp_Pnt p3 = sas.Value(p2);
199 
200  tp[0] = p3.X() / 1000.0;
201  tp[1] = p3.Y() / 1000.0;
202  tp[2] = p3.Z() / 1000.0;
203 
204  uv[0] = p2.X();
205  uv[1] = p2.Y();
206 }
207 
209 {
210 #if defined(NEKTAR_DEBUG)
211  Test(uv);
212 #endif
213 
214  Array<OneD, NekDouble> location(3);
215  gp_Pnt loc;
216  loc = m_occSurface.Value(uv[0], uv[1]);
217  location[0] = loc.X();
218  location[1] = loc.Y();
219  location[2] = loc.Z();
220  return location;
221 }
222 
224 {
225 #if defined(NEKTAR_DEBUG)
226  Test(uv);
227 #endif
228 
229  BRepLProp_SLProps slp(m_occSurface, 2, 1e-6);
230  slp.SetParameters(uv[0], uv[1]);
231 
232  if (!slp.IsNormalDefined())
233  {
234  return Array<OneD, NekDouble>(3, 0.0);
235  }
236 
237  gp_Dir d = slp.Normal();
238 
239  Array<OneD, NekDouble> normal(3);
240 
241  if (m_orientation == CADOrientation::eBackwards)
242  {
243  d.Reverse();
244  }
245 
246  normal[0] = d.X();
247  normal[1] = d.Y();
248  normal[2] = d.Z();
249 
250  return normal;
251 }
252 
254 {
255 #if defined(NEKTAR_DEBUG)
256  Test(uv);
257 #endif
258 
260  gp_Pnt Loc;
261  gp_Vec D1U, D1V;
262  m_occSurface.D1(uv[0], uv[1], Loc, D1U, D1V);
263 
264  r[0] = Loc.X(); // x
265  r[1] = Loc.Y(); // y
266  r[2] = Loc.Z(); // z
267  r[3] = D1U.X(); // dx/du
268  r[4] = D1U.Y(); // dy/du
269  r[5] = D1U.Z(); // dz/du
270  r[6] = D1V.X(); // dx/dv
271  r[7] = D1V.Y(); // dy/dv
272  r[8] = D1V.Z(); // dz/dv
273 
274  return r;
275 }
276 
278 {
279 #if defined(NEKTAR_DEBUG)
280  Test(uv);
281 #endif
282 
284  gp_Pnt Loc;
285  gp_Vec D1U, D1V, D2U, D2V, D2UV;
286  m_occSurface.D2(uv[0], uv[1], Loc, D1U, D1V, D2U, D2V, D2UV);
287 
288  r[0] = Loc.X(); // x
289  r[1] = Loc.Y(); // y
290  r[2] = Loc.Z(); // z
291  r[3] = D1U.X(); // dx/dx
292  r[4] = D1U.Y(); // dy/dy
293  r[5] = D1U.Z(); // dz/dz
294  r[6] = D1V.X(); // dx/dx
295  r[7] = D1V.Y(); // dy/dy
296  r[8] = D1V.Z(); // dz/dz
297  r[9] = D2U.X(); // d2x/du2
298  r[10] = D2U.Y(); // d2y/du2
299  r[11] = D2U.Z(); // d2z/du2
300  r[12] = D2V.X(); // d2x/dv2
301  r[13] = D2V.Y(); // d2y/dv2
302  r[14] = D2V.Z(); // d2z/dv2
303  r[15] = D2UV.X(); // d2x/dudv
304  r[16] = D2UV.Y(); // d2y/dudv
305  r[17] = D2UV.Z(); // d2z/dudv
306 
307  return r;
308 }
309 
310 void CADSurfOCE::Test(Array<OneD, NekDouble> uv)
311 {
312  stringstream error;
313 
314  error << "Point not within parameter plane: ";
315 
316  bool passed = true;
317 
318  if (uv[0] < m_bounds[0])
319  {
320  if (fabs(uv[0] - m_bounds[0]) > 1E-6)
321  {
322  error << "U(" << uv[0] << ") is less than Umin(" << m_bounds[0]
323  << ")";
324  passed = false;
325  }
326  }
327  else if (uv[0] > m_bounds[1])
328  {
329  if (fabs(uv[0] - m_bounds[1]) > 1E-6)
330  {
331  error << "U(" << uv[0] << ") is greater than Umax(" << m_bounds[1]
332  << ")";
333  passed = false;
334  }
335  }
336  else if (uv[1] < m_bounds[2])
337  {
338  if (fabs(uv[1] - m_bounds[2]) > 1E-6)
339  {
340  error << "V(" << uv[1] << ") is less than Vmin(" << m_bounds[2]
341  << ")";
342  passed = false;
343  }
344  }
345  else if (uv[1] > m_bounds[3])
346  {
347  if (fabs(uv[1] - m_bounds[3]) > 1E-6)
348  {
349  error << "V(" << uv[1] << ") is greater than Vmax(" << m_bounds[3]
350  << ")";
351  passed = false;
352  }
353  }
354 
355  error << " On Surface: " << GetId();
356  ASSERTL1(passed, "Warning: " + error.str());
357 }
358 }
359 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:198
STL namespace.
CADSurfFactory & GetCADSurfFactory()
Definition: CADSystem.cpp:72
double NekDouble
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:228
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:215