Reference documentation for deal.II version 8.5.1
boundary_lib.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2014 - 2017 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/opencascade/boundary_lib.h>
18 
19 #ifdef DEAL_II_WITH_OPENCASCADE
20 
21 DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
22 
23 #include <GCPnts_AbscissaPoint.hxx>
24 #include <BRepAdaptor_Curve.hxx>
25 #include <BRepAdaptor_CompCurve.hxx>
26 #include <BRepAdaptor_HCurve.hxx>
27 #include <BRepAdaptor_HCompCurve.hxx>
28 #include <GCPnts_AbscissaPoint.hxx>
29 #include <ShapeAnalysis_Curve.hxx>
30 #include <BRep_Tool.hxx>
31 #include <BRepTools.hxx>
32 #include <ShapeAnalysis_Surface.hxx>
33 #include <TopoDS.hxx>
34 
35 #include <Standard_Version.hxx>
36 #if (OCC_VERSION_MAJOR < 7)
37 # include <Handle_Adaptor3d_HCurve.hxx>
38 #endif
39 
40 DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
41 
42 DEAL_II_NAMESPACE_OPEN
43 
44 
45 namespace OpenCASCADE
46 {
47 
48 
49  namespace
50  {
56  Handle_Adaptor3d_HCurve curve_adaptor(const TopoDS_Shape &shape)
57  {
58  Assert( (shape.ShapeType() == TopAbs_WIRE) ||
59  (shape.ShapeType() == TopAbs_EDGE),
61  if (shape.ShapeType() == TopAbs_WIRE)
62  return Handle(BRepAdaptor_HCompCurve)(new BRepAdaptor_HCompCurve(TopoDS::Wire(shape)));
63  else if (shape.ShapeType() == TopAbs_EDGE)
64  return Handle(BRepAdaptor_HCurve)(new BRepAdaptor_HCurve(TopoDS::Edge(shape)));
65 
66  Assert(false, ExcInternalError());
67  return Handle(BRepAdaptor_HCurve)(new BRepAdaptor_HCurve());
68  }
69 
70 
71 
72 // Helper internal functions.
73  double shape_length(const TopoDS_Shape &sh)
74  {
75  Handle_Adaptor3d_HCurve adapt = curve_adaptor(sh);
76  return GCPnts_AbscissaPoint::Length(adapt->GetCurve());
77  }
78  }
79 
80  /*============================== NormalProjectionBoundary ==============================*/
81  template <int dim, int spacedim>
83  const double tolerance) :
84  sh(sh),
85  tolerance(tolerance)
86  {
87  Assert(spacedim == 3, ExcNotImplemented());
88  }
89 
90 
91  template <int dim, int spacedim>
93  project_to_manifold (const std::vector<Point<spacedim> > &surrounding_points,
94  const Point<spacedim> &candidate) const
95  {
96  (void)surrounding_points;
97 #ifdef DEBUG
98  for (unsigned int i=0; i<surrounding_points.size(); ++i)
99  Assert(closest_point(sh, surrounding_points[i], tolerance)
100  .distance(surrounding_points[i]) <
101  std::max(tolerance*surrounding_points[i].norm(), tolerance),
102  ExcPointNotOnManifold(surrounding_points[i]));
103 #endif
104  return closest_point(sh, candidate,tolerance);
105  }
106 
107 
108  /*============================== DirectionalProjectionBoundary ==============================*/
109  template <int dim, int spacedim>
111  const Tensor<1,spacedim> &direction,
112  const double tolerance) :
113  sh(sh),
114  direction(direction),
115  tolerance(tolerance)
116  {
117  Assert(spacedim == 3, ExcNotImplemented());
118  }
119 
120 
121  template <int dim, int spacedim>
123  project_to_manifold (const std::vector<Point<spacedim> > &surrounding_points,
124  const Point<spacedim> &candidate) const
125  {
126  (void)surrounding_points;
127 #ifdef DEBUG
128  for (unsigned int i=0; i<surrounding_points.size(); ++i)
129  Assert(closest_point(sh, surrounding_points[i],tolerance)
130  .distance(surrounding_points[i]) <
131  std::max(tolerance*surrounding_points[i].norm(), tolerance),
132  ExcPointNotOnManifold(surrounding_points[i]));
133 #endif
134  return line_intersection(sh, candidate, direction, tolerance);
135  }
136 
137 
138 
139  /*============================== NormalToMeshProjectionBoundary ==============================*/
140  template <int dim, int spacedim>
142  const double tolerance) :
143  sh(sh),
144  tolerance(tolerance)
145  {
146  Assert(spacedim == 3, ExcNotImplemented());
147  Assert(std_cxx11::get<0>(count_elements(sh)) > 0,
148  ExcMessage("NormalToMeshProjectionBoundary needs a shape containing faces to operate."));
149  }
150 
151 
152  template <int dim, int spacedim>
154  project_to_manifold (const std::vector<Point<spacedim> > &surrounding_points,
155  const Point<spacedim> &candidate) const
156  {
157  TopoDS_Shape out_shape;
158  Tensor<1,3> average_normal;
159 #ifdef DEBUG
160  for (unsigned int i=0; i<surrounding_points.size(); ++i)
161  {
162  Assert(closest_point(sh, surrounding_points[i], tolerance)
163  .distance(surrounding_points[i]) <
164  std::max(tolerance*surrounding_points[i].norm(), tolerance),
165  ExcPointNotOnManifold(surrounding_points[i]));
166  }
167 #endif
168 
169  switch (surrounding_points.size())
170  {
171  case 2:
172  {
173  for (unsigned int i=0; i<surrounding_points.size(); ++i)
174  {
175  std_cxx11::tuple<Point<3>, Tensor<1,3>, double, double>
176  p_and_diff_forms =
178  surrounding_points[i],
179  tolerance);
180  average_normal += std_cxx11::get<1>(p_and_diff_forms);
181  }
182 
183  average_normal/=2.0;
184 
185  Assert(average_normal.norm() > 1e-4,
186  ExcMessage("Failed to refine cell: the average of the surface normals at the surrounding edge turns out to be a null vector, making the projection direction undetermined."));
187 
188  Tensor<1,3> T = surrounding_points[0]-surrounding_points[1];
189  T /= T.norm();
190  average_normal = average_normal-(average_normal*T)*T;
191  average_normal /= average_normal.norm();
192  break;
193  }
194  case 8:
195  {
196  Tensor<1,3> u = surrounding_points[1]-surrounding_points[0];
197  Tensor<1,3> v = surrounding_points[2]-surrounding_points[0];
198  const double n1_coords[3] = {u[1] *v[2]-u[2] *v[1],u[2] *v[0]-u[0] *v[2],u[0] *v[1]-u[1] *v[0]};
199  Tensor<1,3> n1(n1_coords);
200  n1 = n1/n1.norm();
201  u = surrounding_points[2]-surrounding_points[3];
202  v = surrounding_points[1]-surrounding_points[3];
203  const double n2_coords[3] = {u[1] *v[2]-u[2] *v[1],u[2] *v[0]-u[0] *v[2],u[0] *v[1]-u[1] *v[0]};
204  Tensor<1,3> n2(n2_coords);
205  n2 = n2/n2.norm();
206  u = surrounding_points[4]-surrounding_points[7];
207  v = surrounding_points[6]-surrounding_points[7];
208  const double n3_coords[3] = {u[1] *v[2]-u[2] *v[1],u[2] *v[0]-u[0] *v[2],u[0] *v[1]-u[1] *v[0]};
209  Tensor<1,3> n3(n3_coords);
210  n3 = n3/n3.norm();
211  u = surrounding_points[6]-surrounding_points[7];
212  v = surrounding_points[5]-surrounding_points[7];
213  const double n4_coords[3] = {u[1] *v[2]-u[2] *v[1],u[2] *v[0]-u[0] *v[2],u[0] *v[1]-u[1] *v[0]};
214  Tensor<1,3> n4(n4_coords);
215  n4 = n4/n4.norm();
216  //for (unsigned int i=0; i<surrounding_points.size(); ++i)
217  // cout<<surrounding_points[i]<<endl;
218  //cout<<"-"<<endl;
219  //cout<<n1<<endl;cout<<n2<<endl;cout<<n3<<endl;cout<<n4<<endl;
220 
221  average_normal = (n1+n2+n3+n4)/4.0;
222 
223  Assert(average_normal.norm() > tolerance,
224  ExcMessage("Failed to refine cell: the normal estimated via the surrounding points turns out to be a null vector, making the projection direction undetermined."));
225 
226  average_normal /= average_normal.norm();
227  break;
228  }
229  default:
230  {
231  AssertThrow(false, ExcNotImplemented());
232  break;
233  }
234  }
235 
236  return line_intersection(sh, candidate, average_normal, tolerance);
237  }
238 
239 
240  /*============================== ArclengthProjectionLineManifold ==============================*/
241  template <int dim, int spacedim>
243  const double tolerance):
244 
245  ChartManifold<dim,spacedim,1>(sh.Closed() ?
246  Point<1>(shape_length(sh)) :
247  Point<1>()),
248  curve(curve_adaptor(sh)),
249  tolerance(tolerance),
250  length(shape_length(sh))
251  {
252  Assert(spacedim == 3, ExcNotImplemented());
253  }
254 
255 
256  template <int dim, int spacedim>
257  Point<1>
259  {
260  double t (0.0);
261  ShapeAnalysis_Curve curve_analysis;
262  gp_Pnt proj;
263  const double dist = curve_analysis.Project(curve->GetCurve(), point(space_point), tolerance, proj, t, true);
264  Assert(dist < tolerance*length, ExcPointNotOnManifold(space_point));
265  (void)dist; // Silence compiler warning in Release mode.
266  return Point<1>(GCPnts_AbscissaPoint::Length(curve->GetCurve(),curve->GetCurve().FirstParameter(),t));
267  }
268 
269 
270 
271  template <int dim, int spacedim>
274  {
275  GCPnts_AbscissaPoint AP(curve->GetCurve(), chart_point[0], curve->GetCurve().FirstParameter());
276  gp_Pnt P = curve->GetCurve().Value(AP.Parameter());
277  return point(P);
278  }
279 
280  template <int dim, int spacedim>
282  NURBSPatchManifold( const TopoDS_Face &face,
283  const double tolerance)
284  :
285  face(face),
286  tolerance(tolerance)
287  {}
288 
289  template<>
290  Point<2>
292  pull_back(const Point<3> &space_point) const
293  {
294  Handle(Geom_Surface) SurfToProj = BRep_Tool::Surface(face);
295 
296  ShapeAnalysis_Surface projector(SurfToProj);
297  gp_Pnt2d proj_params = projector.ValueOfUV(point(space_point), tolerance);
298 
299  double u = proj_params.X();
300  double v = proj_params.Y();
301 
302  return Point<2>(u,v);
303  }
304 
305  template<>
306  Point<3>
308  push_forward(const Point<2> &chart_point) const
309  {
310  return ::OpenCASCADE::push_forward(face, chart_point[0], chart_point[1]);
311  }
312 
313  template<>
316  push_forward_gradient(const Point<2> &chart_point) const
317  {
319  Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
320 
321  gp_Pnt q;
322  gp_Vec Du, Dv;
323  surf->D1(chart_point[0],chart_point[1], q, Du, Dv);
324 
325  DX[0][0] = Du.X();
326  DX[1][0] = Du.Y();
327  DX[2][0] = Du.Z();
328  DX[0][1] = Dv.X();
329  DX[1][1] = Dv.Y();
330  DX[2][1] = Dv.Z();
331 
332  return DX;
333  }
334 
335  template<>
336  std_cxx11::tuple<double, double, double, double>
338  get_uv_bounds() const
339  {
340  Standard_Real umin, umax, vmin, vmax;
341  BRepTools::UVBounds(face, umin, umax, vmin, vmax);
342  return std_cxx11::make_tuple(umin, umax, vmin, vmax);
343  }
344 
345 // Explicit instantiations
346  template class NURBSPatchManifold<2, 3 >;
347 #include "boundary_lib.inst"
348 
349 } // end namespace OpenCASCADE
350 
351 DEAL_II_NAMESPACE_CLOSE
352 
353 #endif
std_cxx11::tuple< Point< 3 >, Tensor< 1, 3 >, double, double > closest_point_and_differential_forms(const TopoDS_Shape &in_shape, const Point< 3 > &origin, const double tolerance=1e-7)
Definition: utilities.cc:554
Point< 3 > line_intersection(const TopoDS_Shape &in_shape, const Point< 3 > &origin, const Tensor< 1, 3 > &direction, const double tolerance=1e-7)
Definition: utilities.cc:392
virtual Point< 2 > pull_back(const Point< spacedim > &space_point) const
virtual Point< spacedim > push_forward(const Point< 2 > &chart_point) const
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
numbers::NumberTraits< Number >::real_type norm() const
Definition: tensor.h:991
virtual DerivativeForm< 1, 2, spacedim > push_forward_gradient(const Point< 2 > &chart_point) const
std_cxx11::tuple< unsigned int, unsigned int, unsigned int > count_elements(const TopoDS_Shape &shape)
Definition: utilities.cc:93
static ::ExceptionBase & ExcMessage(std::string arg1)
NormalToMeshProjectionBoundary(const TopoDS_Shape &sh, const double tolerance=1e-7)
virtual Point< spacedim > project_to_manifold(const std::vector< Point< spacedim > > &surrounding_points, const Point< spacedim > &candidate) const
#define Assert(cond, exc)
Definition: exceptions.h:313
static ::ExceptionBase & ExcPointNotOnManifold(Point< 3 > arg1)
virtual Point< spacedim > project_to_manifold(const std::vector< Point< spacedim > > &surrounding_points, const Point< spacedim > &candidate) const
std_cxx11::tuple< double, double, double, double > get_uv_bounds() const
numbers::NumberTraits< Number >::real_type distance(const Point< dim, Number > &p) const
Point< 3 > closest_point(const TopoDS_Shape &in_shape, const Point< 3 > &origin, const double tolerance=1e-7)
Definition: utilities.cc:544
virtual Point< spacedim > push_forward(const Point< 1 > &chart_point) const
static ::ExceptionBase & ExcNotImplemented()
ArclengthProjectionLineManifold(const TopoDS_Shape &sh, const double tolerance=1e-7)
static ::ExceptionBase & ExcUnsupportedShape()
virtual Point< spacedim > project_to_manifold(const std::vector< Point< spacedim > > &surrounding_points, const Point< spacedim > &candidate) const
Definition: boundary_lib.cc:93
NormalProjectionBoundary(const TopoDS_Shape &sh, const double tolerance=1e-7)
Definition: boundary_lib.cc:82
Point< 3 > point(const gp_Pnt &p)
Definition: utilities.cc:176
virtual Point< 1 > pull_back(const Point< spacedim > &space_point) const
static ::ExceptionBase & ExcInternalError()
DirectionalProjectionBoundary(const TopoDS_Shape &sh, const Tensor< 1, spacedim > &direction, const double tolerance=1e-7)