96e4de5b164d47fd3da03d4bc4108d648b76f037
[occt.git] / src / BRepFill / BRepFill_SectionPlacement.cxx
1 // Created on: 1998-02-11
2 // Created by: Philippe MANGIN
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <BRepFill_SectionPlacement.ixx>
24
25 #include <TopExp_Explorer.hxx>
26 #include <TopExp.hxx>
27 #include <TopAbs_ShapeEnum.hxx>
28 #include <TopoDS_Edge.hxx>
29 #include <TopoDS_Vertex.hxx>
30 #include <TopoDS.hxx>
31 #include <BRep_Tool.hxx>
32 #include <BRepAdaptor_HCurve.hxx>
33 #include <BRepAdaptor_HCompCurve.hxx>
34 #include <BRepExtrema_DistShapeShape.hxx>
35 #include <BRepExtrema_SupportType.hxx>
36
37 #include <Geom_Curve.hxx>
38 #include <Geom_CartesianPoint.hxx>
39 #include <Geom_TrimmedCurve.hxx>
40 #include <Geom_Line.hxx>
41 #include <Geom_BSplineCurve.hxx>
42 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
43 #include <GeomAdaptor_HCurve.hxx>
44 #include <GeomFill_SectionPlacement.hxx>
45 #include <GeomFill_LocationLaw.hxx>
46
47 #include <Standard_ConstructionError.hxx>
48 #include <Standard_NotImplemented.hxx>
49 #include <TColStd_Array1OfReal.hxx>
50 #include <TColStd_Array1OfInteger.hxx>
51 #include <Precision.hxx>
52
53 #if DEB
54 static Standard_Boolean myDebug = Standard_False;
55 #endif
56
57 static Standard_Real SearchParam(const Handle(BRepFill_LocationLaw)& Law,
58                                  const Standard_Integer Ind,
59                                  const TopoDS_Vertex& TheV)
60 {
61   Standard_Real t;
62   TopoDS_Edge E;
63   E = Law->Edge(Ind);
64   t = BRep_Tool::Parameter(TheV, E);
65   if (E.Orientation() == TopAbs_REVERSED) {
66     Standard_Real f, l, Lf, Ll;
67     Handle(Geom_Curve) C;
68     C = BRep_Tool::Curve(E,f,l);
69     Lf = Law->Law(Ind)->GetCurve()->FirstParameter();
70     Ll = Law->Law(Ind)->GetCurve()->LastParameter();
71     t = Ll - (t-f)*(Ll-Lf)/(l-f);
72   }
73   return t;
74 }
75                                  
76                                  
77
78 BRepFill_SectionPlacement::
79 BRepFill_SectionPlacement(const Handle(BRepFill_LocationLaw)& Law,
80                           const TopoDS_Shape& Section,
81                           const Standard_Boolean WithContact,
82                           const Standard_Boolean WithCorrection) :
83                           myLaw(Law), mySection(Section)
84 {
85  TopoDS_Vertex VNull;
86  VNull.Nullify();
87  Perform(WithContact, WithCorrection, VNull);
88 }
89
90 BRepFill_SectionPlacement::
91 BRepFill_SectionPlacement(const Handle(BRepFill_LocationLaw)& Law,
92                           const TopoDS_Shape& Section,
93                           const TopoDS_Shape& Vertex,
94                           const Standard_Boolean WithContact,
95                           const Standard_Boolean WithCorrection) :
96                           myLaw(Law), mySection(Section)
97 {
98  Perform(WithContact, WithCorrection, Vertex);
99 }
100
101  void BRepFill_SectionPlacement::Perform(const Standard_Boolean WithContact,
102                                          const Standard_Boolean WithCorrection,
103                                          const TopoDS_Shape& Vertex) 
104 {
105   TopoDS_Vertex TheV; 
106   TheV = TopoDS::Vertex(Vertex);
107   Standard_Integer ii; 
108   Standard_Integer Ind1 = 0, Ind2 = 0;
109   Standard_Boolean Bof, isVertex = Standard_False;
110   Standard_Real First, Last;
111   TopExp_Explorer Ex;
112   TopoDS_Edge E;
113   TopoDS_Vertex V;
114   Handle(Geom_Curve) C;
115   Handle(Geom_TrimmedCurve) TC; 
116
117   // modified by NIZHNY-OCC629  Thu Jul 24 14:11:45 2003
118   Standard_Boolean isFound = Standard_False;
119   Ex.Init(mySection, TopAbs_EDGE);
120   for(; Ex.More(); Ex.Next()) {
121     E = TopoDS::Edge(Ex.Current());
122     // avoid null, degenerated edges
123     if( E.IsNull() || BRep_Tool::Degenerated(E) ) continue;
124     C = BRep_Tool::Curve(E, First, Last);
125     if( C.IsNull() ) continue;
126     isFound = Standard_True;
127     break;
128   }
129   if( !isFound )
130     isVertex = Standard_True;
131   else
132     {
133       TC = new (Geom_TrimmedCurve)(C, First, Last);
134       Ex.Next();
135       
136       if( Ex.More() ) {
137         Standard_Real tolrac, epsV, tol = Precision::Confusion();
138         GeomConvert_CompCurveToBSplineCurve Conv(TC);
139         for (; Ex.More(); Ex.Next()) {
140           E = TopoDS::Edge(Ex.Current());
141           // avoid null, degenerated edges
142           if( E.IsNull() || BRep_Tool::Degenerated(E) ) continue;
143           TopoDS_Vertex VFirst, VLast;
144           TopExp::Vertices(E,VFirst, VLast);
145           epsV = Max(BRep_Tool::Tolerance(VFirst), BRep_Tool::Tolerance(VLast));
146           C = BRep_Tool::Curve(E, First, Last);
147           if( C.IsNull() ) continue;
148           TC = new (Geom_TrimmedCurve)(C, First, Last);
149           tolrac = Min(tol,epsV);
150           Bof = Conv.Add(TC, tolrac);
151           if (!Bof) {
152             tolrac = Max(tol,epsV);
153             Bof = Conv.Add(TC, tolrac);
154           }
155         }
156         C = Conv.BSplineCurve();
157       }
158       else C = TC; // On garde l'unique courbe
159     }
160
161   // modified by NIZHNY-629  Fri Jul 25 11:10:27 2003 b
162
163 //   // punctual section
164 //  Ex.Init(mySection, TopAbs_EDGE);
165 //   Standard_Boolean isPonctual = Standard_False;
166 //  if (Ex.More()) {
167 //    E = TopoDS::Edge(Ex.Current());
168 //    isPonctual = BRep_Tool::Degenerated(E);
169 //  }
170
171 //   Ex.Init(mySection, TopAbs_EDGE);
172 //   if (Ex.More()&&!isPonctual) { 
173 //     E = TopoDS::Edge(Ex.Current());
174 //     C = BRep_Tool::Curve(E, First, Last);
175 //     TC = new (Geom_TrimmedCurve)(C, First, Last);
176 //     Ex.Next();
177 //     if (Ex.More()) { // On essai d'avoir un echantillon representatif
178 //       Standard_Real tolrac, epsV, tol = Precision::Confusion();
179 //       GeomConvert_CompCurveToBSplineCurve Conv(TC);
180 //       for (; Ex.More(); Ex.Next()) {
181 //      E = TopoDS::Edge(Ex.Current());
182 //      TopoDS_Vertex VFirst, VLast;
183 //      TopExp::Vertices(E,VFirst, VLast);
184 //      epsV = Max(BRep_Tool::Tolerance(VFirst), BRep_Tool::Tolerance(VLast));
185 //      C = BRep_Tool::Curve(E, First, Last);
186 //      TC = new (Geom_TrimmedCurve)(C, First, Last);
187 //      tolrac = Min(tol,epsV);
188 //      Bof = Conv.Add(TC, tolrac);
189 //      if (!Bof) {
190 //        tolrac = Max(tol,epsV);
191 //        Bof = Conv.Add(TC, tolrac);
192 //      }
193 //       }
194 //       C = Conv.BSplineCurve();
195 //     }
196 //     else C = TC; // On garde l'unique courbe
197 //   }
198 //   else {
199 //     // Localisation par distance Shape/Shape
200 //     Standard_Real Tpos;
201 //     BRepExtrema_DistShapeShape Ext(mySection, myLaw->Wire());
202     
203 //     if (! Ext.IsDone()) 
204 //        Standard_ConstructionError::Raise("Distance Vertex/Spine");
205
206 //     if (Ext.SupportTypeShape2(1) == BRepExtrema_IsOnEdge) {
207 //       TopoDS_Shape sbis = Ext.SupportOnShape2(1);
208 //       E = TopoDS::Edge(sbis);
209 //       Ext.ParOnEdgeS2(1, Tpos); 
210 //     }
211 //     else {
212 //       TopoDS_Vertex Vf, Vl,V;
213 //       TopoDS_Shape sbis = Ext.SupportOnShape2(1);
214 //       V = TopoDS::Vertex(sbis);
215 //       for (ii=1, Ind1=0 ; ii<=myLaw->NbLaw(); ii++) {
216 //      E = myLaw->Edge(ii);
217 //      TopExp::Vertices(E, Vf, Vl);
218 //      if ((V.IsSame(Vf)) || (V.IsSame(Vl))) {
219 //        if (Ind1 == 0) Ind1 = ii;
220 //        else Ind2 = ii;
221 //      }
222 //       }
223       
224 //       // On invente une section
225 //       gp_Dir D(0, 0, 1);
226 //       gp_Pnt Origine, PV;
227 //       Origine = BRep_Tool::Pnt(V);
228 //       Standard_Real length;
229
230 //       if (Ext.SupportTypeShape1(1) == BRepExtrema_IsVertex) {
231 //      TopoDS_Shape aLocalShape = Ext.SupportOnShape1(1);
232 //         PV = BRep_Tool::Pnt(TopoDS::Vertex(aLocalShape));
233 // //        PV = BRep_Tool::Pnt(TopoDS::Vertex(Ext.SupportOnShape1(1)));
234 //       }
235 //       else {
236 //         PV = BRep_Tool::Pnt(TopoDS::Vertex(mySection));
237 //       }
238 //       length = Origine.Distance(PV);
239 //       if (length > Precision::Confusion()) {
240 //      gp_Vec theVec(Origine, PV);
241 //      D.SetXYZ(theVec.XYZ());
242 //       }
243 //       else length = 10*Precision::Confusion();
244 //       Handle(Geom_Line) CL = new (Geom_Line) (Origine, D);
245 //       TC = new (Geom_TrimmedCurve)(CL, 0., length);
246 //       C = TC; 
247 //       isVertex = Standard_True;
248 //     }
249 //   }
250
251 //   // Recherche du Vertex de positionnement
252 //   if (!TheV.IsNull()) {
253 //     Standard_Integer NbV = myLaw->NbLaw()+1;
254 //     for (ii=1, Ind1=0; ii<=NbV && (!Ind1); ii++)
255 //       if (TheV.IsSame(myLaw->Vertex(ii))) Ind1 = ii;
256     
257 //     if (Ind1 != 0) {
258 //       Ind2 =0;
259 //       isVertex = Standard_True;
260 //       if (Ind1==1) {
261 //      if (myLaw->IsClosed()) Ind2 =  NbV-1;
262 //       }
263 //       else {
264 //      Ind1--;
265 //      if (Ind1 < NbV-1)
266 //        Ind2 = Ind1+1;
267 //       }
268 //     }
269 //     else {
270 //       TheV.Nullify(); // On oublie cette option...
271 //     }
272 //   }
273
274   // modified by NIZHNY-629  Fri Jul 25 11:11:06 2003 e
275
276
277   // Construction
278   Handle(Geom_Geometry) theSection = C;
279   if (isVertex)
280     {
281       Ex.Init(mySection, TopAbs_VERTEX);
282       TopoDS_Vertex theVertex = TopoDS::Vertex(Ex.Current());
283       gp_Pnt thePoint = BRep_Tool::Pnt(theVertex);
284       theSection = new Geom_CartesianPoint(thePoint);
285     }
286
287   GeomFill_SectionPlacement Place(myLaw->Law(1), theSection);
288
289   // In the general case : Localisation via concatenation of the spine
290   TColStd_Array1OfReal SuperKnot(1, myLaw->NbLaw()+1); 
291   TColStd_Array1OfInteger Index(1, myLaw->NbLaw()); 
292   for (ii=1; ii<=myLaw->NbLaw(); ii++) {
293     SuperKnot(ii+1) = Index(ii) = ii;
294   }
295   SuperKnot(1) = 0;
296   
297   Handle(BRepAdaptor_HCompCurve) adpPath = 
298     new (BRepAdaptor_HCompCurve) (myLaw->Wire());
299   
300   Place.Perform(adpPath, Precision::Confusion());
301   
302   Standard_Real theParam = Place.ParameterOnPath(), 
303                 eps = Precision::PConfusion();
304
305 #if DEB
306   if (myDebug) {
307     gp_Pnt P_Path;
308     P_Path = adpPath->Value(theParam);
309     cout << "Point on Path" << P_Path.X() << ", " 
310       <<  P_Path.Y() << ", " << P_Path.Z() << ", " << endl; 
311   }
312 #endif
313   
314   for (ii=1, Bof=Standard_True; ii<=myLaw->NbLaw() && Bof; ii++) {
315     Bof = !((SuperKnot(ii)-eps<=theParam) && 
316             (SuperKnot(ii+1)+eps>= theParam));
317     if (!Bof) {
318       Ind1 = ii;
319       if ( (Abs(theParam-SuperKnot(ii))<eps) && (ii>1) ) Ind2 = ii-1;
320         else if ((Abs(theParam-SuperKnot(ii+1))<eps) && 
321                  (ii<myLaw->NbLaw()) ) Ind2 = ii+1;
322     }
323   }
324   
325   if (Bof) Standard_ConstructionError::Raise("Interval non trouve !!");
326   Ind1 = Index(Ind1);
327   if (Ind2) Ind2 = Index(Ind2);
328   
329   // Positioning on the localized edge (or 2 Edges)
330   Standard_Real Angle;
331   Place.SetLocation(myLaw->Law(Ind1));
332   if(TheV.IsNull())
333     Place.Perform(Precision::Confusion());
334   else {
335     Place.Perform(SearchParam(myLaw, Ind1, TheV), 
336                   Precision::Confusion());    
337   }
338
339   myTrsf = Place.Transformation(WithContact, WithCorrection);
340   myIndex = Ind1;
341   myParam = Place.ParameterOnPath();
342   Angle =  Place.Angle();
343
344   if (Ind2) {
345     Place.SetLocation(myLaw->Law(Ind2));
346     if (TheV.IsNull())
347       Place.Perform(Precision::Confusion());
348     else {
349       if (Ind1 == Ind2) TheV.Reverse();
350       Place.Perform(SearchParam(myLaw, Ind2,TheV), 
351                     Precision::Confusion()); 
352     }
353     if (Place.Angle() > Angle) {
354       myTrsf = Place.Transformation(WithContact, WithCorrection);
355       myIndex = Ind2;
356       myParam = Place.ParameterOnPath();
357     }                                                   
358   }
359 }
360
361  const gp_Trsf& BRepFill_SectionPlacement::Transformation() const
362 {
363   return myTrsf;
364 }
365
366  Standard_Real BRepFill_SectionPlacement::AbscissaOnPath()
367 {
368   return myLaw->Abscissa(myIndex, myParam);
369 }