WaveBEM: Unsteady Nonlinear Potential Flow Solver for Ship-Wave Interaction.
occ_line_smoothing.cc
Go to the documentation of this file.
1 #include "occ_line_smoothing.h"
2 
3 #include <fstream>
4 #include <map>
6 #include <deal.II/grid/tria.h>
12 
13 #include <IGESControl_Reader.hxx>
14 #include <IGESControl_Controller.hxx>
15 #include <IGESControl_Writer.hxx>
16 #include <gp_Pnt.hxx>
17 #include <gp_Dir.hxx>
18 #include <gp_Ax2.hxx>
19 #include <GC_MakeCircle.hxx>
20 #include <BRepBuilderAPI_MakeEdge.hxx>
21 #include <BRepBuilderAPI_MakeFace.hxx>
22 #include <BRepBuilderAPI_MakeWire.hxx>
23 #include <TopoDS.hxx>
24 #include <TopoDS_Wire.hxx>
25 #include <TopoDS_Edge.hxx>
26 #include <TopoDS_Face.hxx>
27 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
28 #include <Geom_BoundedCurve.hxx>
29 #include <Geom_TrimmedCurve.hxx>
30 #include <Geom_BSplineCurve.hxx>
31 #include <GeomLib_Tool.hxx>
32 #include <GeomAdaptor_Curve.hxx>
33 #include <GCPnts_AbscissaPoint.hxx>
34 #include <GC_MakeArcOfCircle.hxx>
35 #include <ShapeAnalysis_Curve.hxx>
36 #include <GeomAPI_IntCS.hxx>
37 #include <BRepAdaptor_Curve.hxx>
38 
39 // all include files you need here
40 
42 #include <deal.II/dofs/dof_tools.h>
43 #include <deal.II/fe/fe_q.h>
44 #include <deal.II/fe/fe_system.h>
45 #include <deal.II/fe/mapping_q1.h>
47 
48 #include "occ_utilities.h"
49 
50 using namespace dealii;
51 using namespace std;
52 using namespace OpenCascade;
53 
54 
55 namespace OpenCascade
56 {
57  LineSmoothing::LineSmoothing(Vector<double> &euler_vector,
58  Handle(Geom_Curve) ref_curve,
59  TopLoc_Location *curr_loc,
60  const DoFHandler<2,3> &dh,
61  const vector<bool> &smoothing_dofs,
62  const unsigned int b_point_id,
63  const unsigned int d_point_id,
64  const double tolerance) :
65  euler_vector(euler_vector),
66  ref_curve(ref_curve),
67  curr_location(curr_loc),
68  curve(ref_curve),
69  projection(BRepBuilderAPI_MakeEdge(ref_curve)),
70  dh(dh),
71  smoothing_dofs(smoothing_dofs),
72  tolerance(tolerance)
73  {
74  if (curr_location)
75  {
78  }
79  else
80  {
81  ref_location.Identity();
82  used_location.Identity();
83  }
84  update_reference(b_point_id, d_point_id);
85  }
86 
87  void LineSmoothing::update_reference(unsigned int bid, unsigned int did)
88  {
89  base_point_id = bid;
90  driving_point_id = did;
91 
92  smoothing_list.clear();
93 
94  TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(ref_curve);
95  edge.Location(ref_location);
96  BRepAdaptor_Curve AC(edge);
97  //GeomAdaptor_Curve AC(ref_curve);
98 
99 
100  // Compute the reference support
101  // points.
102  support_points.resize(dh.n_dofs());
103  //cout<<"dimension "<<dh.n_dofs()<<endl;
104  DoFTools::map_dofs_to_support_points<2,3>(StaticMappingQ1<2,3>::mapping,
105  dh, support_points);
106 
107  // Store the base point
108  // parameter.
109  gp_Pnt proj;
110  ShapeAnalysis_Curve curve_analysis;
111  double off = curve_analysis.Project(AC, Pnt(support_points[3*base_point_id]), tolerance, proj, occ_base_t, Standard_True);
112  //cout<<"base_point_id "<<base_point_id<<" (of "<<dh.n_dofs()<<") "<<support_points[3*base_point_id]<<" vs "<<Pnt(proj)<<" off: "<<off<<endl;
113  AssertThrow( (off < tolerance), ExcMessage("Base point is not on curve."));
114 
115  // Store all parameters and
116  // distances from the base point.
117 //IGESControl_Controller::Init();
118 //IGESControl_Writer ICW ("MM", 0);
119 //Standard_Boolean ok = ICW.AddGeom (AC);
120 //ICW.ComputeModel();
121 //Standard_Boolean OK = ICW.Write ("MyFile2.igs");
122 
123 //cout<<"*"<<endl;
124  for (unsigned int i=0; i<dh.n_dofs()/3; ++i)
125  if (smoothing_dofs[3*i] == true)
126  {
127  Point<3> p = support_points[3*i];
128  gp_Pnt P = Pnt(p);
129  double t;
130  off = curve_analysis.Project(AC, P, tolerance, proj, t, Standard_True);
131  //cout<<"in "<<3*i<<"-> p("<<support_points[3*i]<<") proj="<<Pnt(proj)<<" off "<<off<<endl;
132  AssertThrow( (off < tolerance), ExcMessage("Point is not on ref curve!"));
133  double dist = GCPnts_AbscissaPoint::Length(AC,t,occ_base_t);
134  smoothing_list[std::pair<double, double >(t, dist)]=i;
135  //cout<<"in "<<3*i<<"-> p("<<support_points[3*i]<<") t="<<t<<" dist="<<dist<<" off "<<off<<endl;
136  }
137 
138  // Store the new Reference length
139  iterator endmap = smoothing_list.end();
140  endmap--;
141  ref_L = endmap->first.second;
142 
145  node_indices.resize(smoothing_list.size());
147 
148  unsigned int count = 0;
149  for (iterator it = smoothing_list.begin(); it != smoothing_list.end(); ++it)
150  {
151  fixed_length_ratios(count) = (it->first.second)/ref_L;
152  node_indices[count] = it->second;
153  //cout<<count<<" "<<node_indices[count]<<" "<<fixed_length_ratios(count)<<endl;
154  count++;
155  }
156 
157 
158  // Sanity check: the base point
159  // has to have zero length
160  AssertThrow( smoothing_list.begin()->first.second < tolerance, ExcInternalError());
161 
162  }
163 
164  void LineSmoothing::smooth(bool maintain_on_original_curve)
165  {
167  for (unsigned int i=0; i<3; ++i)
168  dP0(i) += euler_vector(3*driving_point_id+i);
169  //cout<<driving_point_id<<endl;
170 
171  if (maintain_on_original_curve == true)
172  {
173  curve = ref_curve;
174 
176  // general procedure
177  //projection.normal_projection(dP, dP0);
179 
180  // procedure only needed for waveBem
182  //this is the horizontal plane
183  TopLoc_Location L_inv = used_location.Inverted();
184 
185  Handle(Geom_Plane) horPlane = new Geom_Plane(0.,0.,1.,-dP0(2));
186  horPlane->Transform(L_inv.Transformation());
187  GeomAPI_IntCS Intersector(ref_curve, horPlane);
188  int npoints = Intersector.NbPoints();
189  AssertThrow((npoints != 0), ExcMessage("Reference curve is not intersecting with horizontal plane!"));
190  double minDistance=1e7;
191  for (int i=0; i<npoints; ++i)
192  {
193  gp_Pnt inters_point = Intersector.Point(i+1);
194  inters_point.Transform(used_location.Transformation());
195  Point<3> inters = Pnt(inters_point);
196  if (dP0.distance(inters) < minDistance)
197  {
198  minDistance = dP0.distance(inters);
199  dP = inters;
200  }
201  }
202  //*/
204  }
205  else
206  {
207  dP = dP0;
208 
209  std::vector<Point<3> > current_points;
210  Point<3> direction(1.0,0.0,0.0);
211  for (iterator it = smoothing_list.begin(); it != smoothing_list.end(); ++it)
212  {
213  unsigned int id=it->second;
214  Point<3> p = support_points[3*id];
215  for (unsigned int d=0; d<3; ++d)
216  p(d) += euler_vector(3*id+d);
217  current_points.push_back(p);
218  }
219  // Get the current curve
220  curve = interpolation_curve(current_points);
221  used_location.Identity();
222 
223  Point<3> base_point;
224  base_point = support_points[base_point_id*3];
225  for (unsigned int i=0; i<3; ++i)
226  base_point(i) += euler_vector(3*base_point_id+i);
227  gp_Pnt occ_driving_point = Pnt(dP);
228 
229  gp_Pnt proj;
230  ShapeAnalysis_Curve curve_analysis;
231  double off;
232  off = curve_analysis.Project(curve, Pnt(base_point), tolerance, proj, occ_base_t, Standard_True);
233  //cout<<"Point: "<<support_points[base_point_id*3]<<" Proj: "<<Pnt(proj)<<" Off: "<<off<<endl;
234  AssertThrow( (off < tolerance), ExcMessage("Base point is not on curve."));
235 
236 
237  // These lines can be used to dump the bslpine on an .igs file
238  //IGESControl_Controller::Init();
239  //IGESControl_Writer ICW ("MM", 0);
240  //Standard_Boolean ok = ICW.AddGeom (curve);
241  //ICW.ComputeModel();
242  //Standard_Boolean OK = ICW.Write ("MyCurve.igs");
243 
244  }
245  // Create a geometry adaptor on
246  // the current curve
247  TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(curve);
248  edge.Location(used_location);
249  BRepAdaptor_Curve AC(edge);
250  Point<3> driving_point =dP;
251 
252  double off;
253  gp_Pnt proj;
254  ShapeAnalysis_Curve curve_analysis;
255  off = curve_analysis.Project(AC, Pnt(driving_point), tolerance, proj, occ_driving_t, Standard_True);
256  AssertThrow((off < tolerance), ExcMessage("Driving point is not on curve!"));
257 
258  // Total length
259  double L = GCPnts_AbscissaPoint::Length(AC,occ_driving_t,occ_base_t);
260 
261  double direction = occ_driving_t > occ_base_t ? 1.0 : -1.0;
262 
263  // Now perform the smoothing
264  unsigned int counter = 0;
265  for (iterator it = smoothing_list.begin(); it != smoothing_list.end(); ++it)
266  {
267  unsigned int i=it->second;
268  double dist=it->first.second;
269  Point<3> p = support_points[3*i];
270  for (unsigned int d=0; d<3; ++d)
271  p(d) += euler_vector(3*i+d);
272  // we now must compute where the old p lies on the curve (its parameter)
273  // to be able to record the old length, useful for possible
274  // interpolation of functions which might reconstruct the
275  // new function values at the nodes after they have been moved by smoothing
276  double old_t;
277  off = curve_analysis.Project(AC, Pnt(p), tolerance, proj, old_t, Standard_True);
278  //cout<<"Smoothing point distance from curve: "<<off<<" Point: "<<p<<" vs "<<Pnt(proj)<<endl;
279  AssertThrow( (off <L), ExcMessage("Smoothing point waaay off the curve."));
280  lengths_before_smoothing(counter) = GCPnts_AbscissaPoint::Length(AC,old_t,occ_base_t);
281  node_indices[counter] = i;
282  //cout<<"out "<<3*i<<"--> p("<<p<<") t="<<t<<" dist="<<dist<<endl;
283  double new_dist = direction*fixed_length_ratios(counter)*L;
284  lengths_after_smoothing(counter) = new_dist;
285  GCPnts_AbscissaPoint AP(AC, new_dist, occ_base_t);
286  double new_t = AP.Parameter();
287  Point<3> pnew = Pnt(AC.Value(new_t));
288  //cout<<"pnew("<<pnew<<") tnew="<<new_t<<" distnew="<<new_dist<<endl;
289  // Euler distance
290  pnew -= support_points[3*i];
291  for (unsigned int j=0; j<3; ++j)
292  {
293  //cout<<3*i+j<<" "<<pnew(j)<<endl;
294  euler_vector(3*i+j) = pnew(j);
295  }
296  counter++;
297  }
298  }
299 
300 }
301 
302 
303 void LineSmoothing::get_curve_tangent_vectors_at_smoothing_dofs(Vector<double> &tangents)
304 {
305  AssertThrow(tangents.size()==dh.n_dofs(),
306  ExcMessage("Tangent vector has wrong size"));
307 
308  TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(curve);
309  edge.Location(used_location);
310  BRepAdaptor_Curve AC(edge);
311 
312  for (iterator it = smoothing_list.begin(); it != smoothing_list.end(); ++it)
313  {
314  unsigned int i=it->second;
315  double t=it->first.first;
316  gp_Pnt P;
317  gp_Vec V1;
318  AC.D1(t,P,V1);
319 
320  tangents[3*i] = V1.X();
321  tangents[3*i+1] = V1.Y();
322  tangents[3*i+2] = V1.Z();
323  }
324 
325 }
326 
328 {
329  AssertThrow(length_ratios.size()==dh.n_dofs(),
330  ExcMessage("Length ratios vector has wrong size"));
331  // Create a geometry adaptor on
332  // the current curve
333  TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(curve);
334  edge.Location(used_location);
335  BRepAdaptor_Curve AC(edge);
336  // Total length
337  double L = GCPnts_AbscissaPoint::Length(AC,occ_driving_t,occ_base_t);
338 
339  for (iterator it = smoothing_list.begin(); it != smoothing_list.end(); ++it)
340  {
341  unsigned int i=it->second;
342  double dist = it->first.second;
343 
344  for (unsigned int j=0; j<3; ++j)
345  length_ratios(3*i+j) = dist/L;
346  }
347 }
std::vector< unsigned int > node_indices
void get_curve_length_ratios_at_smoothing_dofs(Vector< double > &length_ratios)
Handle_Geom_Curve interpolation_curve(std::vector< Point< 3 > > &curve_points)
Vector< double > lengths_after_smoothing
void smooth(bool maintain_on_original_curve=true)
Perform the actual smoothing.
Vector< double > & euler_vector
STL namespace.
numbers::NumberTraits< double >::real_type distance(const Point< dim, double > &p) const
#define AssertThrow(cond, exc)
void update_reference(unsigned int base_point_id, unsigned int driving_point_id)
Handle(Geom_Curve) get_curve()
std::map< std::pair< double, double >, unsigned int, comp_points_on_curve > smoothing_list
static::ExceptionBase & ExcMessage(std::string arg1)
types::global_dof_index n_dofs() const
std::vector< Point< 3 > > support_points
Vector< double > fixed_length_ratios
std::map< std::pair< double, double >, unsigned int, comp_points_on_curve >::iterator iterator
const DoFHandler< 2, 3 > & dh
std::size_t size() const
const std::vector< bool > & smoothing_dofs
Vector< double > lengths_before_smoothing
dealii::Point< 3 > Pnt(const gp_Pnt &p)
Convert OpenCascade point into.
Definition: occ_utilities.h:76
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
We collect in this namespace all utilities which operate on OpenCascade entities which don't need cla...
Handle(Geom_Curve) NumericalTowingTank
static::ExceptionBase & ExcInternalError()