Reference documentation for deal.II version 9.0.0
utilities.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2014 - 2018 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 #include <deal.II/opencascade/utilities.h>
17 
18 #ifdef DEAL_II_WITH_OPENCASCADE
19 
20 #include <deal.II/base/point.h>
21 #include <deal.II/base/utilities.h>
22 #include <deal.II/base/exceptions.h>
23 
24 #include <cstdio>
25 #include <iostream>
26 #include <set>
27 
28 
29 #include <IGESControl_Controller.hxx>
30 #include <IGESControl_Reader.hxx>
31 #include <IGESControl_Writer.hxx>
32 
33 #include <STEPControl_Controller.hxx>
34 #include <STEPControl_Reader.hxx>
35 #include <STEPControl_Writer.hxx>
36 
37 #include <TopoDS.hxx>
38 #include <TopoDS_Shape.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopExp_Explorer.hxx>
42 
43 #include <Standard_Version.hxx>
44 #if (OCC_VERSION_MAJOR < 7)
45 # include <Handle_Standard_Transient.hxx>
46 #else
47 # include <Standard_Transient.hxx>
48 #endif
49 
50 #include <TColStd_SequenceOfTransient.hxx>
51 #include <TColStd_HSequenceOfTransient.hxx>
52 #include <TColgp_HArray1OfPnt.hxx>
53 
54 #include <gp_Pnt.hxx>
55 #include <gp_Lin.hxx>
56 #include <gp_Vec.hxx>
57 #include <GeomAPI_ProjectPointOnSurf.hxx>
58 #include <GeomAPI_ProjectPointOnCurve.hxx>
59 #include <IntCurvesFace_ShapeIntersector.hxx>
60 
61 #include <BRepTools.hxx>
62 #include <BRepAdaptor_Curve.hxx>
63 #include <BRepAdaptor_HCurve.hxx>
64 #include <BRepAdaptor_HCompCurve.hxx>
65 #include <BRepAdaptor_Surface.hxx>
66 #include <BRep_Builder.hxx>
67 #include <BRepBuilderAPI_Transform.hxx>
68 #include <BRepBuilderAPI_MakeEdge.hxx>
69 #include <BRepAlgo_Section.hxx>
70 
71 #include <Geom_Plane.hxx>
72 #include <Geom_BoundedCurve.hxx>
73 #include <GeomAPI_Interpolate.hxx>
74 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
75 #include <GeomLProp_SLProps.hxx>
76 
77 #include <GCPnts_AbscissaPoint.hxx>
78 #include <ShapeAnalysis_Surface.hxx>
79 
80 
81 #include <vector>
82 #include <algorithm>
83 
84 DEAL_II_NAMESPACE_OPEN
85 
86 namespace OpenCASCADE
87 {
88  std::tuple<unsigned int, unsigned int, unsigned int>
89  count_elements(const TopoDS_Shape &shape)
90  {
91  TopExp_Explorer exp;
92  unsigned int n_faces=0, n_edges=0, n_vertices=0;
93  for (exp.Init(shape, TopAbs_FACE);
94  exp.More(); exp.Next(), ++n_faces)
95  {}
96  for (exp.Init(shape, TopAbs_EDGE);
97  exp.More(); exp.Next(), ++n_edges)
98  {}
99  for (exp.Init(shape, TopAbs_VERTEX);
100  exp.More(); exp.Next(), ++n_vertices)
101  {}
102  return std::tuple<unsigned int, unsigned int, unsigned int>(n_faces, n_edges, n_vertices);
103  }
104 
105  void extract_geometrical_shapes(const TopoDS_Shape &shape,
106  std::vector<TopoDS_Face> &faces,
107  std::vector<TopoDS_Edge> &edges,
108  std::vector<TopoDS_Vertex> &vertices)
109  {
110  faces.resize(0);
111  edges.resize(0);
112  vertices.resize(0);
113 
114  TopExp_Explorer exp;
115  for (exp.Init(shape, TopAbs_FACE); exp.More(); exp.Next())
116  {
117  faces.push_back(TopoDS::Face(exp.Current()));
118  }
119  for (exp.Init(shape, TopAbs_EDGE); exp.More(); exp.Next())
120  {
121  edges.push_back(TopoDS::Edge(exp.Current()));
122  }
123  for (exp.Init(shape, TopAbs_VERTEX); exp.More(); exp.Next())
124  {
125  vertices.push_back(TopoDS::Vertex(exp.Current()));
126  }
127  }
128 
129 
130  void extract_compound_shapes(const TopoDS_Shape &shape,
131  std::vector<TopoDS_Compound> &compounds,
132  std::vector<TopoDS_CompSolid> &compsolids,
133  std::vector<TopoDS_Solid> &solids,
134  std::vector<TopoDS_Shell> &shells,
135  std::vector<TopoDS_Wire> &wires)
136  {
137  compounds.resize(0);
138  compsolids.resize(0);
139  solids.resize(0);
140  shells.resize(0);
141  wires.resize(0);
142 
143  TopExp_Explorer exp;
144  for (exp.Init(shape, TopAbs_COMPOUND); exp.More(); exp.Next())
145  {
146  compounds.push_back(TopoDS::Compound(exp.Current()));
147  }
148  for (exp.Init(shape, TopAbs_COMPSOLID); exp.More(); exp.Next())
149  {
150  compsolids.push_back(TopoDS::CompSolid(exp.Current()));
151  }
152  for (exp.Init(shape, TopAbs_SOLID); exp.More(); exp.Next())
153  {
154  solids.push_back(TopoDS::Solid(exp.Current()));
155  }
156  for (exp.Init(shape, TopAbs_SHELL); exp.More(); exp.Next())
157  {
158  shells.push_back(TopoDS::Shell(exp.Current()));
159  }
160  for (exp.Init(shape, TopAbs_WIRE); exp.More(); exp.Next())
161  {
162  wires.push_back(TopoDS::Wire(exp.Current()));
163  }
164  }
165 
166  template <int spacedim>
167  gp_Pnt point(const Point<spacedim> &p)
168  {
169  switch (spacedim)
170  {
171  case 1:
172  return gp_Pnt(p[0], 0, 0);
173  case 2:
174  return gp_Pnt(p[0], p[1], 0);
175  case 3:
176  return gp_Pnt(p[0], p[1], p[2]);
177  }
178  AssertThrow (false, ExcNotImplemented());
179  return {};
180  }
181 
182  template <int spacedim>
183  Point<spacedim> point(const gp_Pnt &p, const double &tolerance)
184  {
185  (void) tolerance;
186  switch (spacedim)
187  {
188  case 1:
189  Assert(std::abs(p.Y()) <= tolerance,
190  ExcMessage("Cannot convert OpenCASCADE point to 1d if p.Y() != 0."));
191  Assert(std::abs(p.Z()) <= tolerance,
192  ExcMessage("Cannot convert OpenCASCADE point to 1d if p.Z() != 0."));
193  return Point<spacedim>(p.X());
194  case 2:
195  Assert(std::abs(p.Z()) <= tolerance,
196  ExcMessage("Cannot convert OpenCASCADE point to 2d if p.Z() != 0."));
197  return Point<spacedim>(p.X(), p.Y());
198  case 3:
199  return Point<spacedim>(p.X(), p.Y(), p.Z());
200  }
201  AssertThrow (false, ExcNotImplemented());
202  return {};
203  }
204 
205  template<int dim>
206  bool point_compare(const Point<dim> &p1,
207  const Point<dim> &p2,
208  const Tensor<1,dim> &direction,
209  const double tolerance)
210  {
211  const double rel_tol=std::max(tolerance, std::max(p1.norm(), p2.norm())*tolerance);
212  if (direction.norm() > 0.0)
213  return (p1*direction < p2*direction-rel_tol);
214  else
215  for (int d=dim; d>=0; --d)
216  if (p1[d] < p2[d]-rel_tol)
217  return true;
218  else if (p2[d] < p1[d]-rel_tol)
219  return false;
220 
221  // If we got here, for all d, none of the conditions above was
222  // satisfied. The two points are equal up to tolerance
223  return false;
224  }
225 
226 
227  TopoDS_Shape read_IGES(const std::string &filename,
228  const double scale_factor)
229  {
230  IGESControl_Reader reader;
231  IFSelect_ReturnStatus stat;
232  stat = reader.ReadFile(filename.c_str());
233  AssertThrow(stat == IFSelect_RetDone,
234  ExcMessage("Error in reading file!"));
235 
236  Standard_Boolean failsonly = Standard_False;
237  IFSelect_PrintCount mode = IFSelect_ItemsByEntity;
238  reader.PrintCheckLoad (failsonly, mode);
239 
240  Standard_Integer nRoots = reader.TransferRoots();
241  //selects all IGES entities (including non visible ones) in the
242  //file and puts them into a list called MyList,
243 
244  AssertThrow(nRoots > 0,
245  ExcMessage("Read nothing from file."));
246 
247  // Handle IGES Scale here.
248  gp_Pnt Origin;
249  gp_Trsf scale;
250  scale.SetScale (Origin, scale_factor);
251 
252  TopoDS_Shape sh = reader.OneShape();
253  BRepBuilderAPI_Transform trans(sh, scale);
254 
255  return trans.Shape(); // this is the actual translation
256  }
257 
258  void write_IGES(const TopoDS_Shape &shape,
259  const std::string &filename)
260  {
261  IGESControl_Controller::Init();
262  IGESControl_Writer ICW ("MM", 0);
263  Standard_Boolean ok = ICW.AddShape (shape);
264  AssertThrow(ok, ExcMessage("Failed to add shape to IGES controller."));
265  ICW.ComputeModel();
266  Standard_Boolean OK = ICW.Write (filename.c_str());
267  AssertThrow(OK, ExcMessage("Failed to write IGES file."));
268  }
269 
270  TopoDS_Shape read_STEP(const std::string &filename,
271  const double scale_factor)
272  {
273  STEPControl_Reader reader;
274  IFSelect_ReturnStatus stat;
275  stat = reader.ReadFile(filename.c_str());
276  AssertThrow(stat == IFSelect_RetDone,
277  ExcMessage("Error in reading file!"));
278 
279  Standard_Boolean failsonly = Standard_False;
280  IFSelect_PrintCount mode = IFSelect_ItemsByEntity;
281  reader.PrintCheckLoad (failsonly, mode);
282 
283  Standard_Integer nRoots = reader.TransferRoots();
284  //selects all IGES entities (including non visible ones) in the
285  //file and puts them into a list called MyList,
286 
287  AssertThrow(nRoots > 0,
288  ExcMessage("Read nothing from file."));
289 
290  // Handle STEP Scale here.
291  gp_Pnt Origin;
292  gp_Trsf scale;
293  scale.SetScale (Origin, scale_factor);
294 
295  TopoDS_Shape sh = reader.OneShape();
296  BRepBuilderAPI_Transform trans(sh, scale);
297 
298  return trans.Shape(); // this is the actual translation
299  }
300 
301  void write_STEP(const TopoDS_Shape &shape,
302  const std::string &filename)
303  {
304  STEPControl_Controller::Init();
305  STEPControl_Writer SCW;
306  IFSelect_ReturnStatus status;
307  status = SCW.Transfer(shape, STEPControl_AsIs);
308  AssertThrow(status == IFSelect_RetDone, ExcMessage("Failed to add shape to STEP controller."));
309 
310  status = SCW.Write(filename.c_str());
311 
312  AssertThrow(status == IFSelect_RetDone, ExcMessage("Failed to write translated shape to STEP file."));
313  }
314 
315  double get_shape_tolerance(const TopoDS_Shape &shape)
316  {
317  double tolerance = 0.0;
318 
319  std::vector<TopoDS_Face> faces;
320  std::vector<TopoDS_Edge> edges;
321  std::vector<TopoDS_Vertex> vertices;
322 
324  faces,
325  edges,
326  vertices);
327 
328  for (unsigned int i=0; i<vertices.size(); ++i)
329  tolerance = fmax(tolerance,BRep_Tool::Tolerance(vertices[i]));
330 
331  for (unsigned int i=0; i<edges.size(); ++i)
332  tolerance = fmax(tolerance,BRep_Tool::Tolerance(edges[i]));
333 
334  for (unsigned int i=0; i<faces.size(); ++i)
335  tolerance = fmax(tolerance,BRep_Tool::Tolerance(faces[i]));
336 
337 
338  return tolerance;
339  }
340 
341  TopoDS_Shape intersect_plane(const TopoDS_Shape &in_shape,
342  const double c_x,
343  const double c_y,
344  const double c_z,
345  const double c,
346  const double /*tolerance*/)
347  {
348  Handle(Geom_Plane) plane = new Geom_Plane(c_x,c_y,c_z,c);
349  BRepAlgo_Section section(in_shape, plane);
350  TopoDS_Shape edges = section.Shape();
351  return edges;
352  }
353 
354  TopoDS_Edge join_edges(const TopoDS_Shape &in_shape,
355  const double tolerance)
356  {
357  TopoDS_Edge out_shape;
358  const TopoDS_Shape &edges = in_shape;
359  std::vector<Handle_Geom_BoundedCurve> intersections;
360  TopLoc_Location L;
361  Standard_Real First;
362  Standard_Real Last;
363  gp_Pnt PIn(0.0,0.0,0.0);
364  gp_Pnt PFin(0.0,0.0,0.0);
365  gp_Pnt PMid(0.0,0.0,0.0);
366  TopExp_Explorer edgeExplorer(edges, TopAbs_EDGE);
367  TopoDS_Edge edge;
368  while (edgeExplorer.More())
369  {
370  edge = TopoDS::Edge(edgeExplorer.Current());
371  Handle(Geom_Curve) curve = BRep_Tool::Curve(edge,L,First,Last);
372  intersections.push_back(Handle(Geom_BoundedCurve)::DownCast(curve));
373  edgeExplorer.Next();
374  }
375 
376  // Now we build a single bspline out of all the geometrical
377  // curves, in Lexycographical order
378  unsigned int numIntersEdges = intersections.size();
379  Assert(numIntersEdges>0, ExcMessage("No curves to process!"));
380 
381  GeomConvert_CompCurveToBSplineCurve convert_bspline(intersections[0]);
382 
383  bool check = false, one_added = true, one_failed=true;
384  std::vector<bool> added(numIntersEdges, false);
385  added[0] = true;
386  while (one_added == true)
387  {
388  one_added = false;
389  one_failed = false;
390  for (unsigned int i=1; i<numIntersEdges; ++i)
391  if (added[i] == false)
392  {
393  Handle(Geom_Curve) curve = intersections[i];
394  Handle(Geom_BoundedCurve) bcurve = Handle(Geom_BoundedCurve)::DownCast(curve);
395  check = convert_bspline.Add(bcurve,tolerance,false,true,0);
396  if (check == false) // If we failed, try again with the reversed curve
397  {
398  curve->Reverse();
399  Handle(Geom_BoundedCurve) bcurve = Handle(Geom_BoundedCurve)::DownCast(curve);
400  check = convert_bspline.Add(bcurve,tolerance,false,true,0);
401  }
402  one_failed = one_failed || (check == false);
403  one_added = one_added || (check == true);
404  added[i] = check;
405  }
406  }
407 
408  Assert(one_failed == false,
409  ExcMessage("Joining some of the Edges failed."));
410 
411  Handle(Geom_Curve) bspline = convert_bspline.BSplineCurve();
412 
413  out_shape = BRepBuilderAPI_MakeEdge(bspline);
414  return out_shape;
415  }
416 
417  template <int dim>
418  Point<dim> line_intersection(const TopoDS_Shape &in_shape,
419  const Point<dim> &origin,
420  const Tensor<1,dim> &direction,
421  const double tolerance)
422  {
423  // translating original Point<dim> to gp point
424 
425  gp_Pnt P0 = point(origin);
426  gp_Ax1 gpaxis(P0, gp_Dir(direction[0], dim > 1 ? direction[1] : 0, dim>2 ? direction[2] : 0));
427  gp_Lin line(gpaxis);
428 
429  // destination point
430  gp_Pnt Pproj(0.0,0.0,0.0);
431 
432  // we prepare now the surface for the projection we get the whole
433  // shape from the iges model
434  IntCurvesFace_ShapeIntersector Inters;
435  Inters.Load(in_shape,tolerance);
436 
437  // Keep in mind: PerformNearest sounds pretty but DOESN'T WORK!!!
438  // The closest point must be found by hand
439  Inters.Perform(line,-RealLast(),+RealLast());
440  Assert(Inters.IsDone(), ExcMessage("Could not project point."));
441 
442  double minDistance = 1e7;
443  Point<dim> result;
444  for (int i=0; i<Inters.NbPnt(); ++i)
445  {
446  const double distance = point(origin).Distance(Inters.Pnt(i+1));
447  //cout<<"Point "<<i<<": "<<point(Inters.Pnt(i+1))<<" distance: "<<distance<<endl;
448  if (distance < minDistance)
449  {
450  minDistance = distance;
451  result = point<dim>(Inters.Pnt(i+1));
452  }
453  }
454 
455  return result;
456  }
457 
458  template <int dim>
459  TopoDS_Edge interpolation_curve(std::vector<Point<dim> > &curve_points,
460  const Tensor<1,dim> &direction,
461  const bool closed,
462  const double tolerance)
463  {
464 
465  unsigned int n_vertices = curve_points.size();
466 
467  if (direction*direction > 0)
468  {
469  std::sort(curve_points.begin(), curve_points.end(),
470  [&](const Point<dim> &p1, const Point<dim> &p2)
471  {
472  return OpenCASCADE::point_compare(p1, p2, direction, tolerance);
473  });
474  }
475 
476  // set up array of vertices
477  Handle(TColgp_HArray1OfPnt) vertices = new TColgp_HArray1OfPnt(1,n_vertices);
478  for (unsigned int vertex=0; vertex<n_vertices; ++vertex)
479  {
480  vertices->SetValue(vertex+1,point(curve_points[vertex]));
481  }
482 
483 
484  GeomAPI_Interpolate bspline_generator(vertices, closed, tolerance);
485  bspline_generator.Perform();
486  Assert( (bspline_generator.IsDone()), ExcMessage("Interpolated bspline generation failed"));
487 
488  Handle(Geom_BSplineCurve) bspline = bspline_generator.Curve();
489  TopoDS_Edge out_shape = BRepBuilderAPI_MakeEdge(bspline);
490  return out_shape;
491  }
492 
493 
494 
495  template<int spacedim>
496  std::vector<TopoDS_Edge> create_curves_from_triangulation_boundary
497  (const Triangulation<2, spacedim> &triangulation,
498  const Mapping<2, spacedim> &mapping)
499 
500  {
501  // store maps from global vertex index to pairs of global face indices
502  // and from global face index to pairs of global vertex indices
503  std::map<unsigned int, std::pair<unsigned int,unsigned int> > vert_to_faces;
504  std::map<unsigned int, std::pair<unsigned int,unsigned int> > face_to_verts;
505  std::map<unsigned int, bool> visited_faces;
506  std::map<unsigned int, Point<spacedim> > vert_to_point;
507 
508  unsigned int face_index;
509 
510  for (auto cell: triangulation.active_cell_iterators())
511  for (unsigned int f=0; f<GeometryInfo<2>::faces_per_cell; ++f)
512  if (cell->face(f)->at_boundary())
513  {
514  // get global face and vertex indices
515  face_index = cell->face(f)->index();
516  const unsigned int v0 = cell->face(f)->vertex_index(0);
517  const unsigned int v1 = cell->face(f)->vertex_index(1);
518  face_to_verts[face_index].first = v0;
519  face_to_verts[face_index].second = v1;
520  visited_faces[face_index] = false;
521 
522  // extract mapped vertex locations
523  std::array<Point<spacedim>,GeometryInfo<2>::vertices_per_cell> verts = mapping.get_vertices(cell);
524  vert_to_point[v0]=verts[GeometryInfo<2>::face_to_cell_vertices(f,0,true,false,false)];
525  vert_to_point[v1]=verts[GeometryInfo<2>::face_to_cell_vertices(f,1,true,false,false)];
526 
527  // distribute indices into maps
528  if (vert_to_faces.find(v0) == vert_to_faces.end())
529  {
530  vert_to_faces[v0].first = face_index;
531  }
532  else
533  {
534  vert_to_faces[v0].second = face_index;
535  }
536  if (vert_to_faces.find(v1) == vert_to_faces.end())
537  {
538  vert_to_faces[v1].first = face_index;
539  }
540  else
541  {
542  vert_to_faces[v1].second = face_index;
543  }
544  }
545 
546  // run through maps in an orderly fashion, i.e., through the
547  // boundary in one cycle and add points to pointlist.
548  std::vector<TopoDS_Edge> interpolation_curves;
549  bool finished = (face_to_verts.size() == 0);
550  face_index = finished ? 0 : face_to_verts.begin()->first;
551 
552  while (finished == false)
553  {
554  const unsigned int start_point_index = face_to_verts[face_index].first;
555  unsigned int point_index = start_point_index;
556 
557  // point_index and face_index always run together
558  std::vector<Point<spacedim> > pointlist;
559  do
560  {
561  visited_faces[face_index] = true;
562  auto current_point = vert_to_point[point_index];
563  pointlist.push_back(current_point);
564 
565  // Get next point
566  if (face_to_verts[face_index].first != point_index )
567  point_index = face_to_verts[face_index].first;
568  else
569  point_index = face_to_verts[face_index].second;
570 
571  // Get next face
572  if (vert_to_faces[point_index].first != face_index)
573  face_index = vert_to_faces[point_index].first;
574  else
575  face_index = vert_to_faces[point_index].second;
576  }
577  while (point_index != start_point_index);
578 
579  interpolation_curves.push_back(interpolation_curve(pointlist, Tensor<1,spacedim>(), true));
580 
581  finished = true;
582  for (const auto &f : visited_faces)
583  if (f.second == false)
584  {
585  face_index = f.first;
586  finished = false;
587  break;
588  }
589  }
590  return interpolation_curves;
591  }
592 
593 
594  template<int dim>
595  std::tuple<Point<dim>, TopoDS_Shape, double, double> project_point_and_pull_back(const TopoDS_Shape &in_shape,
596  const Point<dim> &origin,
597  const double tolerance)
598  {
599  TopExp_Explorer exp;
600  gp_Pnt Pproj = point(origin);
601 
602  double minDistance = 1e7;
603  gp_Pnt tmp_proj(0.0,0.0,0.0);
604 
605  unsigned int counter = 0;
606  unsigned int face_counter = 0;
607 
608  TopoDS_Shape out_shape;
609  double u=0;
610  double v=0;
611 
612  for (exp.Init(in_shape, TopAbs_FACE); exp.More(); exp.Next())
613  {
614  TopoDS_Face face = TopoDS::Face(exp.Current());
615 
616  // the projection function needs a surface, so we obtain the
617  // surface upon which the face is defined
618  Handle(Geom_Surface) SurfToProj = BRep_Tool::Surface(face);
619 
620  ShapeAnalysis_Surface projector(SurfToProj);
621  gp_Pnt2d proj_params = projector.ValueOfUV(point(origin), tolerance);
622 
623  SurfToProj->D0(proj_params.X(),proj_params.Y(),tmp_proj);
624 
625  double distance = point<dim>(tmp_proj).distance(origin);
626  if (distance < minDistance)
627  {
628  minDistance = distance;
629  Pproj = tmp_proj;
630  out_shape = face;
631  u=proj_params.X();
632  v=proj_params.Y();
633  ++counter;
634  }
635  ++face_counter;
636  }
637 
638  // face counter tells us if the shape contained faces: if it does, there is no need
639  // to loop on edges. Even if the closest point lies on the boundary of a parametric surface,
640  // we need in fact to retain the face and both u and v, if we want to use this method to
641  // retrieve the surface normal
642  if (face_counter==0)
643  for (exp.Init(in_shape, TopAbs_EDGE); exp.More(); exp.Next())
644  {
645  TopoDS_Edge edge = TopoDS::Edge(exp.Current());
646  if (!BRep_Tool::Degenerated(edge))
647  {
648  TopLoc_Location L;
649  Standard_Real First;
650  Standard_Real Last;
651 
652  // the projection function needs a Curve, so we obtain the
653  // curve upon which the edge is defined
654  Handle(Geom_Curve) CurveToProj = BRep_Tool::Curve(edge,L,First,Last);
655 
656  GeomAPI_ProjectPointOnCurve Proj(point(origin),CurveToProj);
657  unsigned int num_proj_points = Proj.NbPoints();
658  if ((num_proj_points > 0) && (Proj.LowerDistance() < minDistance))
659  {
660  minDistance = Proj.LowerDistance();
661  Pproj = Proj.NearestPoint();
662  out_shape = edge;
663  u=Proj.LowerDistanceParameter();
664  ++counter;
665  }
666  }
667  }
668 
669  Assert(counter > 0, ExcMessage("Could not find projection points."));
670  return std::tuple<Point<dim>, TopoDS_Shape, double, double>
671  (point<dim>(Pproj),out_shape, u, v);
672  }
673 
674 
675  template<int dim>
676  Point<dim> closest_point(const TopoDS_Shape &in_shape,
677  const Point<dim> &origin,
678  const double tolerance)
679  {
680  std::tuple<Point<dim>, TopoDS_Shape, double, double>
681  ref = project_point_and_pull_back(in_shape, origin, tolerance);
682  return std::get<0>(ref);
683  }
684 
685  std::tuple<Point<3>, Tensor<1,3>, double, double>
686  closest_point_and_differential_forms(const TopoDS_Shape &in_shape,
687  const Point<3> &origin,
688  const double tolerance)
689 
690  {
691  std::tuple<Point<3>, TopoDS_Shape, double, double>
692  shape_and_params = project_point_and_pull_back(in_shape,
693  origin,
694  tolerance);
695 
696  TopoDS_Shape &out_shape = std::get<1>(shape_and_params);
697  double &u = std::get<2>(shape_and_params);
698  double &v = std::get<3>(shape_and_params);
699 
700  // just a check here: the number of faces in out_shape must be 1, otherwise
701  // something is wrong
702  std::tuple<unsigned int, unsigned int, unsigned int> numbers =
703  count_elements(out_shape);
704  (void)numbers;
705 
706  Assert(std::get<0>(numbers) > 0,
707  ExcMessage("Could not find normal: the shape containing the closest point has 0 faces."));
708  Assert(std::get<0>(numbers) < 2,
709  ExcMessage("Could not find normal: the shape containing the closest point has more than 1 face."));
710 
711 
712  TopExp_Explorer exp;
713  exp.Init(out_shape, TopAbs_FACE);
714  TopoDS_Face face = TopoDS::Face(exp.Current());
715  return push_forward_and_differential_forms(face, u, v, tolerance);
716  }
717 
718  template<int dim>
719  Point<dim> push_forward(const TopoDS_Shape &in_shape,
720  const double u,
721  const double v)
722  {
723  switch (in_shape.ShapeType())
724  {
725  case TopAbs_FACE:
726  {
727  BRepAdaptor_Surface surf(TopoDS::Face(in_shape));
728  return point<dim>(surf.Value(u,v));
729  }
730  case TopAbs_EDGE:
731  {
732  BRepAdaptor_Curve curve(TopoDS::Edge(in_shape));
733  return point<dim>(curve.Value(u));
734  }
735  default:
736  Assert(false, ExcUnsupportedShape());
737  }
738  return Point<dim>();
739  }
740 
741  std::tuple<Point<3>, Tensor<1,3>, double, double>
742  push_forward_and_differential_forms(const TopoDS_Face &face,
743  const double u,
744  const double v,
745  const double /*tolerance*/)
746  {
747  Handle(Geom_Surface) SurfToProj = BRep_Tool::Surface(face);
748  GeomLProp_SLProps props(SurfToProj, u, v, 1, 1e-7);
749  gp_Pnt Value = props.Value();
750  Assert(props.IsNormalDefined(), ExcMessage("Normal is not well defined!"));
751  gp_Dir Normal = props.Normal();
752  Assert(props.IsCurvatureDefined(), ExcMessage("Curvature is not well defined!"));
753  Standard_Real Min_Curvature = props.MinCurvature();
754  Standard_Real Max_Curvature = props.MaxCurvature();
755  Tensor<1,3> normal = Point<3>(Normal.X(),Normal.Y(),Normal.Z());
756 
757  // In the case your manifold changes from convex to concave or viceversa
758  // the normal could jump from "inner" to "outer" normal.
759  // However, you should be able to change the normal sense preserving
760  // the manifold orientation:
761  if (face.Orientation()==TopAbs_REVERSED)
762  {
763  normal *= -1;
764  Min_Curvature *= -1;
765  Max_Curvature *= -1;
766  }
767 
768  return std::tuple<Point<3>, Tensor<1,3>, double, double>(point<3>(Value), normal, Min_Curvature, Max_Curvature);
769  }
770 
771 
772 
773  template<int spacedim>
774  void create_triangulation(const TopoDS_Face &face,
776  {
777  BRepAdaptor_Surface surf(face);
778  const double u0 = surf.FirstUParameter();
779  const double u1 = surf.LastUParameter();
780  const double v0 = surf.FirstVParameter();
781  const double v1 = surf.LastVParameter();
782 
783  std::vector<CellData<2> > cells;
784  std::vector<Point<spacedim> > vertices;
785  SubCellData t;
786 
787  vertices.push_back(point<spacedim>(surf.Value(u0,v0)));
788  vertices.push_back(point<spacedim>(surf.Value(u1,v0)));
789  vertices.push_back(point<spacedim>(surf.Value(u0,v1)));
790  vertices.push_back(point<spacedim>(surf.Value(u1,v1)));
791 
792  CellData<2> cell;
793  for (unsigned int i=0; i<4; ++i)
794  cell.vertices[i] = i;
795 
796  cells.push_back(cell);
797  tria.create_triangulation(vertices, cells, t);
798  }
799 
800 #include "utilities.inst"
801 
802 } // end namespace
803 
804 DEAL_II_NAMESPACE_CLOSE
805 
806 #endif
std::tuple< unsigned int, unsigned int, unsigned int > count_elements(const TopoDS_Shape &shape)
Definition: utilities.cc:89
TopoDS_Shape read_IGES(const std::string &filename, const double scale_factor=1e-3)
Definition: utilities.cc:227
Point< dim > push_forward(const TopoDS_Shape &in_shape, const double u, const double v)
Definition: utilities.cc:719
static unsigned int face_to_cell_vertices(const unsigned int face, const unsigned int vertex, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
TopoDS_Shape intersect_plane(const TopoDS_Shape &in_shape, const double c_x, const double c_y, const double c_z, const double c, const double tolerance=1e-7)
Definition: utilities.cc:341
Point< spacedim > point(const gp_Pnt &p, const double &tolerance=1e-10)
Definition: utilities.cc:183
TopoDS_Shape read_STEP(const std::string &filename, const double scale_factor=1e-3)
Definition: utilities.cc:270
TopoDS_Edge interpolation_curve(std::vector< Point< dim > > &curve_points, const Tensor< 1, dim > &direction=Tensor< 1, dim >(), const bool closed=false, const double tolerance=1e-7)
Definition: utilities.cc:459
virtual std::array< Point< spacedim >, GeometryInfo< dim >::vertices_per_cell > get_vertices(const typename Triangulation< dim, spacedim >::cell_iterator &cell) const
Definition: mapping.cc:25
Point< dim > line_intersection(const TopoDS_Shape &in_shape, const Point< dim > &origin, const Tensor< 1, dim > &direction, const double tolerance=1e-7)
Definition: utilities.cc:418
bool point_compare(const Point< dim > &p1, const Point< dim > &p2, const Tensor< 1, dim > &direction=Tensor< 1, dim >(), const double tolerance=1e-10)
Definition: utilities.cc:206
std::tuple< Point< 3 >, Tensor< 1, 3 >, double, double > push_forward_and_differential_forms(const TopoDS_Face &face, const double u, const double v, const double tolerance=1e-7)
Definition: utilities.cc:742
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
numbers::NumberTraits< Number >::real_type norm() const
Definition: tensor.h:1273
void write_IGES(const TopoDS_Shape &shape, const std::string &filename)
Definition: utilities.cc:258
void create_triangulation(const TopoDS_Face &face, Triangulation< 2, spacedim > &tria)
Definition: utilities.cc:774
static ::ExceptionBase & ExcMessage(std::string arg1)
void write_STEP(const TopoDS_Shape &shape, const std::string &filename)
Definition: utilities.cc:301
#define Assert(cond, exc)
Definition: exceptions.h:1142
Abstract base class for mapping classes.
Definition: dof_tools.h:46
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
Definition: tria.cc:9240
Point< dim > closest_point(const TopoDS_Shape &in_shape, const Point< dim > &origin, const double tolerance=1e-7)
Definition: utilities.cc:676
void extract_compound_shapes(const TopoDS_Shape &shape, std::vector< TopoDS_Compound > &compounds, std::vector< TopoDS_CompSolid > &compsolids, std::vector< TopoDS_Solid > &solids, std::vector< TopoDS_Shell > &shells, std::vector< TopoDS_Wire > &wires)
Definition: utilities.cc:130
std::tuple< Point< dim >, TopoDS_Shape, double, double > project_point_and_pull_back(const TopoDS_Shape &in_shape, const Point< dim > &origin, const double tolerance=1e-7)
Definition: utilities.cc:595
double get_shape_tolerance(const TopoDS_Shape &shape)
Definition: utilities.cc:315
TopoDS_Edge join_edges(const TopoDS_Shape &in_shape, const double tolerance=1e-7)
Definition: utilities.cc:354
void extract_geometrical_shapes(const TopoDS_Shape &shape, std::vector< TopoDS_Face > &faces, std::vector< TopoDS_Edge > &edges, std::vector< TopoDS_Vertex > &vertices)
Definition: utilities.cc:105
std::vector< TopoDS_Edge > create_curves_from_triangulation_boundary(const Triangulation< 2, spacedim > &triangulation, const Mapping< 2, spacedim > &mapping=StaticMappingQ1< 2, spacedim >::mapping)
Definition: utilities.cc:497
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcUnsupportedShape()
std::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:686
unsigned int vertices[GeometryInfo< structdim >::vertices_per_cell]
Definition: tria.h:132