2d637b603a0f7233649cd9e2023b7c9f034e3bcd
[occt.git] / src / BRepFill / BRepFill_NSections.cxx
1 // Created on: 1998-12-29
2 // Created by: Joelle CHAUVET
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Curve.hxx>
21 #include <BRepFill.hxx>
22 #include <BRepFill_NSections.hxx>
23 #include <BRepLib_MakeEdge.hxx>
24 #include <BRepLib_MakeWire.hxx>
25 #include <BRepLProp.hxx>
26 #include <BRepTools_WireExplorer.hxx>
27 #include <BSplCLib.hxx>
28 #include <Geom_BezierCurve.hxx>
29 #include <Geom_BSplineCurve.hxx>
30 #include <Geom_BSplineSurface.hxx>
31 #include <Geom_Conic.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom_Line.hxx>
34 #include <Geom_TrimmedCurve.hxx>
35 #include <GeomConvert.hxx>
36 #include <GeomConvert_ApproxCurve.hxx>
37 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
38 #include <GeomFill_AppSurf.hxx>
39 #include <GeomFill_EvolvedSection.hxx>
40 #include <GeomFill_HArray1OfSectionLaw.hxx>
41 #include <GeomFill_Line.hxx>
42 #include <GeomFill_NSections.hxx>
43 #include <GeomFill_SectionGenerator.hxx>
44 #include <GeomFill_SectionLaw.hxx>
45 #include <GeomFill_UniformSection.hxx>
46 #include <Precision.hxx>
47 #include <Standard_Type.hxx>
48 #include <TColGeom_SequenceOfCurve.hxx>
49 #include <TColgp_HArray1OfPnt.hxx>
50 #include <TColStd_HArray1OfInteger.hxx>
51 #include <TColStd_HArray1OfReal.hxx>
52 #include <TopExp.hxx>
53 #include <TopoDS.hxx>
54 #include <TopoDS_Shape.hxx>
55 #include <TopoDS_Vertex.hxx>
56 #include <TopoDS_Wire.hxx>
57 #include <TopTools_Array1OfShape.hxx>
58
59 #include <stdio.h>
60 IMPLEMENT_STANDARD_RTTIEXT(BRepFill_NSections,BRepFill_SectionLaw)
61
62 #ifdef OCCT_DEBUG
63 static Standard_Boolean Affich = 0;
64 #endif
65
66 #ifdef DRAW
67 #include <DrawTrSurf.hxx>
68 #include <DBRep.hxx>
69 #endif
70
71
72 //=======================================================================
73 //function : EdgeToBSpline
74 //purpose  : auxiliary -- get curve from edge and convert it to bspline
75 //           parameterized from 0 to 1
76 //=======================================================================
77
78 // NOTE: this code duplicates the same function in BRepOffsetAPI_ThruSections.cxx
79 static Handle(Geom_BSplineCurve) EdgeToBSpline (const TopoDS_Edge& theEdge)
80 {
81   Handle(Geom_BSplineCurve) aBSCurve;
82   if (BRep_Tool::Degenerated(theEdge)) {
83     // degenerated edge : construction of a point curve
84     TColStd_Array1OfReal aKnots (1,2);
85     aKnots(1) = 0.;
86     aKnots(2) = 1.;
87
88     TColStd_Array1OfInteger aMults (1,2);
89     aMults(1) = 2;
90     aMults(2) = 2;
91
92     TColgp_Array1OfPnt aPoles(1,2);
93     TopoDS_Vertex vf, vl;
94     TopExp::Vertices(theEdge,vl,vf);
95     aPoles(1) = BRep_Tool::Pnt(vf);
96     aPoles(2) = BRep_Tool::Pnt(vl);
97
98     aBSCurve = new Geom_BSplineCurve (aPoles, aKnots, aMults, 1);
99   }
100   else
101   {
102     // get the curve of the edge
103     TopLoc_Location aLoc;
104     Standard_Real aFirst, aLast;
105     Handle(Geom_Curve) aCurve = BRep_Tool::Curve (theEdge, aLoc, aFirst, aLast);
106
107     // convert its part used by edge to bspline; note that if edge curve is bspline,
108     // conversion made via trimmed curve is still needed -- it will copy it, segment 
109     // as appropriate, and remove periodicity if it is periodic (deadly for approximator)
110     Handle(Geom_TrimmedCurve) aTrimCurve = new Geom_TrimmedCurve (aCurve, aFirst, aLast);
111
112     // special treatment of conic curve
113     if (aTrimCurve->BasisCurve()->IsKind(STANDARD_TYPE(Geom_Conic)))
114     {
115       const Handle(Geom_Curve)& aCurveTemp = aTrimCurve; // to avoid ambiguity
116       GeomConvert_ApproxCurve anAppr (aCurveTemp, Precision::Confusion(), GeomAbs_C1, 16, 14);
117       if (anAppr.HasResult())
118         aBSCurve = anAppr.Curve();
119     }
120
121     // general case
122     if (aBSCurve.IsNull())
123       aBSCurve = GeomConvert::CurveToBSplineCurve (aTrimCurve);
124
125     // apply transformation if needed
126     if (! aLoc.IsIdentity())
127       aBSCurve->Transform (aLoc.Transformation());
128
129     // reparameterize to [0,1]
130     TColStd_Array1OfReal aKnots (1, aBSCurve->NbKnots());
131     aBSCurve->Knots (aKnots);
132     BSplCLib::Reparametrize (0., 1., aKnots);
133     aBSCurve->SetKnots (aKnots);
134   }
135
136   // reverse curve if edge is reversed
137   if (theEdge.Orientation() == TopAbs_REVERSED)
138     aBSCurve->Reverse();
139
140   return aBSCurve;
141 }
142
143 //=======================================================================
144 //function : totalsurf
145 //purpose  : 
146 //=======================================================================
147
148 static Handle(Geom_BSplineSurface) totalsurf(const TopTools_Array2OfShape& shapes,
149                                              const Standard_Integer NbSects,
150                                              const Standard_Integer NbEdges,
151                                              const TColStd_SequenceOfReal& params,
152                                              const Standard_Boolean w1Point,
153                                              const Standard_Boolean w2Point,
154                                              const Standard_Boolean uClosed,
155                                              const Standard_Boolean vClosed,
156                                              const Standard_Real myPres3d)
157 {
158   Standard_Integer i,j,jdeb=1,jfin=NbSects;
159   TopoDS_Edge edge;
160   TopoDS_Vertex vf,vl;
161
162   GeomFill_SectionGenerator section;
163   Handle(Geom_BSplineSurface) surface;
164   Handle(Geom_BSplineCurve) BS, BS1;
165
166   if (w1Point) {
167     jdeb++;
168     edge =  TopoDS::Edge(shapes.Value(1,1));
169     TopExp::Vertices(edge,vl,vf);
170     TColgp_Array1OfPnt Extremities(1,2);
171     Extremities(1) = BRep_Tool::Pnt(vf);
172     Extremities(2) = BRep_Tool::Pnt(vl);
173     TColStd_Array1OfReal Bounds(1,2);
174     Bounds(1) = 0.;
175     Bounds(2) = 1.;
176     TColStd_Array1OfInteger Mult(1,2);
177     Mult(1) = 2;
178     Mult(2) = 2;
179     Handle(Geom_BSplineCurve) BSPoint
180       = new Geom_BSplineCurve(Extremities,Bounds,Mult, 1);
181     section.AddCurve(BSPoint);
182   }
183
184   if (w2Point) {
185     jfin--;
186   }
187
188   for (j=jdeb; j<=jfin; j++) {
189
190     // case of looping sections
191     if (j==jfin && vClosed) {
192       section.AddCurve(BS1);
193     }
194
195     else {
196       // read the first edge to initialise CompBS;
197       TopoDS_Edge aPrevEdge = TopoDS::Edge (shapes.Value(1,j));
198       Handle(Geom_BSplineCurve) curvBS = EdgeToBSpline (aPrevEdge);
199       
200       // initialization
201       GeomConvert_CompCurveToBSplineCurve CompBS(curvBS);
202
203       for (i=2; i<=NbEdges; i++) {  
204         // read the edge
205         TopoDS_Edge aNextEdge = TopoDS::Edge (shapes.Value(i,j));
206         curvBS = EdgeToBSpline (aNextEdge);
207
208         // concatenation
209         TopoDS_Vertex ComV;
210         Standard_Real epsV;
211         Standard_Boolean Bof = TopExp::CommonVertex(aPrevEdge, aNextEdge, ComV);
212         if (Bof) epsV = BRep_Tool::Tolerance(ComV);
213         else epsV = Precision::Confusion();
214         Bof = CompBS.Add(curvBS, epsV, Standard_True, Standard_False, 1);
215         if (!Bof) Bof = CompBS.Add(curvBS, 200*epsV,
216                                    Standard_True, Standard_False, 1);
217
218         // remember previous edge
219         aPrevEdge = aNextEdge;
220       }
221
222       // return the final section
223       BS = CompBS.BSplineCurve();
224       section.AddCurve(BS);
225
226       // case of looping sections
227       if (j==jdeb && vClosed) {
228         BS1 = BS;
229       }
230
231     }
232   }
233
234   if (w2Point) {
235     edge =  TopoDS::Edge(shapes.Value(NbEdges,NbSects));
236     TopExp::Vertices(edge,vl,vf);
237     TColgp_Array1OfPnt Extremities(1,2);
238     Extremities(1) = BRep_Tool::Pnt(vf);
239     Extremities(2) = BRep_Tool::Pnt(vl);
240     TColStd_Array1OfReal Bounds(1,2);
241     Bounds(1) = 0.;
242     Bounds(2) = 1.;
243     TColStd_Array1OfInteger Mult(1,2);
244     Mult(1) = 2;
245     Mult(2) = 2;
246     Handle(Geom_BSplineCurve) BSPoint
247       = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
248     section.AddCurve(BSPoint);
249   }
250
251   Handle(TColStd_HArray1OfReal) HPar
252     = new TColStd_HArray1OfReal(1,params.Length());
253   for (i=1; i<=params.Length(); i++) {
254     HPar->SetValue(i,params(i));
255   }
256   section.SetParam(HPar);
257   section.Perform(Precision::PConfusion());
258   Handle(GeomFill_Line) line = new GeomFill_Line(NbSects);
259   Standard_Integer nbIt = 0, degmin = 2, degmax = 6;
260   Standard_Boolean knownP = Standard_True;
261   GeomFill_AppSurf anApprox(degmin, degmax, myPres3d, myPres3d, nbIt, knownP);
262   Standard_Boolean SpApprox = Standard_True;
263   anApprox.Perform(line, section, SpApprox);
264   Standard_Boolean uperiodic = uClosed;
265   Standard_Boolean vperiodic = vClosed;
266   Standard_Integer nup = anApprox.SurfPoles().ColLength(),
267                    nvp = anApprox.SurfPoles().RowLength();
268   TColStd_Array1OfInteger Umults(1,anApprox.SurfUKnots().Length());
269   Umults = anApprox.SurfUMults();
270   TColStd_Array1OfInteger Vmults(1,anApprox.SurfVKnots().Length());
271   Vmults = anApprox.SurfVMults();
272
273   if (uperiodic) {
274     Standard_Integer nbuk = anApprox.SurfUKnots().Length();
275     Umults(1) --;
276     Umults(nbuk) --;
277     nup --;
278   }
279
280   if (vperiodic) {
281     Standard_Integer nbvk = anApprox.SurfVKnots().Length();
282     Vmults(1) --;
283     Vmults(nbvk) --;
284     nvp --;
285   }
286
287   TColgp_Array2OfPnt   poles  (1, nup, 1, nvp);
288   TColStd_Array2OfReal weights(1, nup, 1, nvp);
289     for (j = 1; j <= nvp; j++) {
290       for (i = 1; i <= nup; i++) {
291         poles(i, j) = anApprox.SurfPoles()(i,j);
292         weights(i, j) = anApprox.SurfWeights()(i,j);
293       }
294     }
295
296   // To create non-rational surface if possible
297   Standard_Real TolEps = 1.e-13;
298   Standard_Boolean Vrational = Standard_False, Urational = Standard_False;
299   for (j = 1; j <= weights.UpperCol(); j++)
300     if (!Vrational)
301       for (i = 1; i <= weights.UpperRow()-1; i++)
302         {
303           //Standard_Real signeddelta = weights(i,j) - weights(i+1,j);
304           Standard_Real delta = Abs( weights(i,j) - weights(i+1,j) );
305 //        Standard_Real eps = Epsilon( Abs(weights(i,j)) );
306           if (delta > TolEps/* || delta > 3.*eps*/)
307             {
308               Vrational = Standard_True;
309               break;
310             }
311         }
312   for (i = 1; i <= weights.UpperRow(); i++)
313     if (!Urational)
314       for (j = 1; j <= weights.UpperCol()-1; j++)
315         {
316           //Standard_Real signeddelta = weights(i,j) - weights(i,j+1);
317           Standard_Real delta = Abs( weights(i,j) - weights(i,j+1) );
318 //        Standard_Real eps = Epsilon( Abs(weights(i,j)) );
319           if (delta > TolEps/* || delta > 3.*eps*/)
320             {
321               Urational = Standard_True;
322               break;
323             }
324         }
325   if (!Vrational && !Urational)
326     {
327       Standard_Real theWeight = weights(1,1);
328       for (i = 1; i <= weights.UpperRow(); i++)
329         for (j = 1; j <= weights.UpperCol(); j++)
330           weights(i,j) = theWeight;
331     }
332     
333   surface = 
334     new Geom_BSplineSurface(poles, weights,
335                             anApprox.SurfUKnots(), anApprox.SurfVKnots(),
336                             Umults, Vmults,
337                             anApprox.UDegree(), anApprox.VDegree(),
338                             uperiodic, vperiodic);
339   return surface;
340   
341 }
342
343
344 //=======================================================================
345 //function : Create
346 //purpose  : WSeq
347 //=======================================================================
348
349 BRepFill_NSections::BRepFill_NSections(const TopTools_SequenceOfShape& S,
350                                        const Standard_Boolean Build) 
351
352 {
353   myShapes = S;
354   VFirst = 0.;
355   VLast = 1.;
356   TColStd_SequenceOfReal par;
357   par.Clear();
358   for (Standard_Integer i=1;i<=S.Length();i++) {
359     par.Append(i-1);
360   }
361   myParams = par;
362   Init(par,Build);
363 }
364
365 //=======================================================================
366 //function : Create
367 //purpose  : WSeq + Param
368 //=======================================================================
369
370 BRepFill_NSections::BRepFill_NSections(const TopTools_SequenceOfShape& S,
371                                        const GeomFill_SequenceOfTrsf& Transformations,
372                                        const TColStd_SequenceOfReal & P,
373                                        const Standard_Real VF,
374                                        const Standard_Real VL,
375                                        const Standard_Boolean Build)
376
377 {
378 #ifdef OCCT_DEBUG
379   if ( Affich) {
380 #ifdef DRAW
381     Standard_Integer NBSECT = 0;
382     for (Standard_Integer i=1;i<=S.Length();i++) {
383       NBSECT++;
384       char name[256];
385       sprintf(name,"WIRE_%d",NBSECT);
386       DBRep::Set(name,TopoDS::Wire(S.Value(i)));
387     }
388 #endif
389   }
390 #endif
391   Standard_Boolean ok = Standard_True;
392   for (Standard_Integer iseq=1;iseq<P.Length();iseq++) {
393     ok = ok && (P.Value(iseq)<P.Value(iseq+1));
394   }
395   if (ok) {
396     myParams = P;
397     myShapes = S;
398     myTrsfs = Transformations;
399     VFirst = VF;
400     VLast = VL;
401     Init(P,Build);
402   }
403 }
404
405 //=======================================================================
406 //function : Init
407 //purpose  : Create a table of GeomFill_SectionLaw
408 //=======================================================================
409 void BRepFill_NSections::Init(const TColStd_SequenceOfReal & P,
410                               const Standard_Boolean Build)
411 {
412   BRepTools_WireExplorer wexp;
413 // Class BRep_Tool without fields and without Constructor :
414 //  BRep_Tool B;
415   TopoDS_Edge E;
416   Standard_Integer ii, NbEdge, jj, NbSects = P.Length();
417   Standard_Integer ideb = 1, ifin = NbSects;
418   Standard_Boolean wClosed, w1Point = Standard_True, 
419                             w2Point = Standard_True;
420   Standard_Real First, Last;
421   TopoDS_Wire W;
422
423   // Check if the start and end wires are punctual
424   W = TopoDS::Wire(myShapes(1));
425   for (wexp.Init(W); wexp.More(); wexp.Next()) 
426 //    w1Point = w1Point && B.Degenerated(wexp.Current());
427     w1Point = w1Point && BRep_Tool::Degenerated(wexp.Current());
428   if (w1Point) ideb++;
429   W = TopoDS::Wire(myShapes(NbSects));
430   for (wexp.Init(W); wexp.More(); wexp.Next()) 
431 //    w2Point = w2Point && B.Degenerated(wexp.Current());
432     w2Point = w2Point && BRep_Tool::Degenerated(wexp.Current());
433   if (w2Point) ifin--;
434
435   // Check if the start and end wires are identical
436   vclosed = myShapes(1).IsSame(myShapes(NbSects));
437
438   // Count the number of non-degenerated edges
439   W = TopoDS::Wire(myShapes(ideb));
440   for (NbEdge=0, wexp.Init(W); wexp.More(); wexp.Next()) 
441 //    if (! B.Degenerated(wexp.Current())) NbEdge++;
442     if (! BRep_Tool::Degenerated(wexp.Current())) NbEdge++;
443
444   myEdges = new (TopTools_HArray2OfShape) (1, NbEdge, 1, NbSects);
445   
446   // Fill tables
447   uclosed = Standard_True;
448   for (jj=ideb;jj<=ifin;jj++){
449
450     W = TopoDS::Wire(myShapes(jj));
451     
452     for (ii=1, wexp.Init(W); ii<=NbEdge ; wexp.Next(), ii++) {
453       E =  wexp.Current();
454       
455 //      if ( ! B.Degenerated(E)) {
456       if ( ! BRep_Tool::Degenerated(E)) {
457         myEdges->SetValue(ii,jj, E);
458       }
459     }
460
461   // Is the law closed by U ?
462
463     wClosed = W.Closed();
464     if (!wClosed) {
465       // if unsure about the flag, make check
466       TopoDS_Edge Edge1, Edge2;
467       TopoDS_Vertex V1,V2;
468       Edge1 = TopoDS::Edge (myEdges->Value(NbEdge,jj));
469       Edge2 = TopoDS::Edge (myEdges->Value(1,jj));
470       
471       if ( Edge1.Orientation() == TopAbs_REVERSED) {
472         V1 = TopExp::FirstVertex(Edge1);
473       }
474       else {
475         V1 = TopExp::LastVertex(Edge1);
476       }
477       if ( Edge2.Orientation() == TopAbs_REVERSED) {
478         V2 = TopExp::LastVertex(Edge2);
479       }
480       else {
481         V2 = TopExp::FirstVertex(Edge2);
482       } 
483       if (V1.IsSame(V2)) {
484         wClosed = Standard_True;
485       }
486       else {
487         BRepAdaptor_Curve Curve1(Edge1);
488         BRepAdaptor_Curve Curve2(Edge2);
489         Standard_Real U1 = BRep_Tool::Parameter(V1,Edge1);
490         Standard_Real U2 = BRep_Tool::Parameter(V2,Edge2);
491         Standard_Real Eps = BRep_Tool::Tolerance(V2) + 
492           BRep_Tool::Tolerance(V1);
493         
494         wClosed = Curve1.Value(U1).IsEqual(Curve2.Value(U2), Eps);
495       }
496     } 
497     if (!wClosed) uclosed = Standard_False;
498   }
499
500   // point sections at end
501   if (w1Point) {
502     W = TopoDS::Wire(myShapes(1));
503     wexp.Init(W);
504     E =  wexp.Current();
505     for (ii=1; ii<=NbEdge ; ii++) {
506       myEdges->SetValue(ii, 1, E);
507     }
508   }
509   
510   if (w2Point) {
511     W = TopoDS::Wire(myShapes(NbSects));
512     wexp.Init(W);
513     E =  wexp.Current();
514     for (ii=1; ii<=NbEdge ; ii++) {
515       myEdges->SetValue(ii, NbSects, E);
516     }
517   }
518   
519   
520   myLaws = new (GeomFill_HArray1OfSectionLaw) (1, NbEdge);
521
522   Standard_Real tol = Precision::Confusion();
523   mySurface = totalsurf(myEdges->Array2(),myShapes.Length(),NbEdge,
524                         myParams,w1Point,w2Point,uclosed,vclosed,tol);
525    
526   // Increase the degree so that the position D2 
527   // on GeomFill_NSections could be correct
528   // see comments in GeomFill_NSections
529   if (mySurface->VDegree()<2) {
530     mySurface->IncreaseDegree(mySurface->UDegree(),2);
531   }
532 #ifdef DRAW
533   if ( Affich) {
534     char*  name = new char[100];
535     sprintf(name,"Ref_Surf");
536     DrawTrSurf::Set(name,mySurface);
537   }
538 #endif
539
540   // Fill tables
541   if (Build) {
542     for (ii=1; ii<=NbEdge ; ii++) {
543       TColGeom_SequenceOfCurve NC;
544       NC.Clear();
545       for (jj=1;jj<=NbSects;jj++) {
546         E = TopoDS::Edge (myEdges->Value(ii,jj));
547         Handle(Geom_Curve) C;
548 //      if (B.Degenerated(E)) {
549         if (BRep_Tool::Degenerated(E)) {
550           TopoDS_Vertex vf,vl;
551           TopExp::Vertices(E,vl,vf);
552           TColgp_Array1OfPnt Extremities(1,2);
553           Extremities(1) = BRep_Tool::Pnt(vf);
554           Extremities(2) = BRep_Tool::Pnt(vl);
555           TColStd_Array1OfReal Bounds(1,2);
556           Bounds(1) = 0.;
557           Bounds(2) = 1.;
558           TColStd_Array1OfInteger Mult(1,2);
559           Mult(1) = 2;
560           Mult(2) = 2;
561           Handle(Geom_BSplineCurve) BSPoint
562             = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
563           C = BSPoint;
564         }
565         else {
566           C  = BRep_Tool::Curve(E,First,Last);
567         
568           if (E.Orientation() == TopAbs_REVERSED) {
569             Standard_Real aux;
570             Handle(Geom_Curve) CBis;
571             CBis = C->Reversed(); // To avoid the spoiling of the topology
572             aux = C->ReversedParameter(First);
573             First = C->ReversedParameter(Last);
574             Last = aux;
575             C =  CBis;
576           } 
577           if ((ii>1) || (!BRep_Tool::IsClosed(E)) ) { // Cut C
578             Handle(Geom_TrimmedCurve) TC = 
579               new (Geom_TrimmedCurve) (C,First, Last);
580             C  = TC;
581           } 
582           //  otherwise preserve the integrity of the curve
583         }
584         NC.Append(C);
585       }
586  
587       Standard_Real Ufirst = ii-1;
588       Standard_Real Ulast = ii;
589       myLaws->ChangeValue(ii) = new (GeomFill_NSections)(NC, myTrsfs, myParams,
590                                                          Ufirst,Ulast,
591                                                          VFirst,VLast,
592                                                          mySurface);
593     }
594  
595   } 
596  
597 }
598
599
600 //=======================================================================
601 //function : IsVertex
602 //purpose  :
603 //=======================================================================
604  Standard_Boolean BRepFill_NSections::IsVertex() const
605 {
606   return  Standard_False;
607 }
608
609 //=======================================================================
610 //function : IsConstant
611 //purpose  :
612 //=======================================================================
613  Standard_Boolean BRepFill_NSections::IsConstant() const
614 {
615   return Standard_False;
616 }
617
618 //=======================================================================
619 //function : Vertex
620 //purpose  : 
621 //=======================================================================
622  TopoDS_Vertex 
623  BRepFill_NSections::Vertex(const Standard_Integer Index, 
624                             const Standard_Real Param) const
625 {
626   BRep_Builder B;
627   TopoDS_Vertex V;
628   B.MakeVertex(V);
629   gp_Pnt P;
630
631   if (Index <= myEdges->ColLength()) {
632     Handle(Geom_BSplineCurve) Curve 
633       = Handle(Geom_BSplineCurve)::DownCast(myLaws->Value(Index)->
634                                             BSplineSurface()->VIso(Param));
635     Standard_Real first = Curve ->FirstParameter();
636     Curve->D0(first, P);
637     B.UpdateVertex(V, P, Precision::Confusion());
638   }
639   else if (Index == myEdges->ColLength()+1) {
640     Handle(Geom_BSplineCurve) Curve 
641       = Handle(Geom_BSplineCurve)::DownCast(myLaws->Value(Index-1)->
642                                             BSplineSurface()->VIso(Param));
643     Standard_Real last = Curve ->LastParameter();
644     Curve->D0(last, P);
645     B.UpdateVertex(V, P, Precision::Confusion());
646   }
647
648   return V;
649 }
650
651
652 ///=======================================================================
653 //function : VertexTol
654 //purpose  : Evaluate the hole between 2 edges of the section
655 //=======================================================================
656  Standard_Real BRepFill_NSections::VertexTol(const Standard_Integer Index,
657                                               const Standard_Real Param) const
658 {
659   Standard_Real Tol = Precision::Confusion();
660   Standard_Integer I1, I2;
661   if ( (Index==0) || (Index==myEdges->ColLength()) ) {
662     if (!uclosed) return Tol; //The least possible error
663     I1 = myEdges->ColLength();
664     I2 = 1;
665   }
666   else {
667     I1 = Index;
668     I2 = I1 +1;
669   } 
670
671   Handle(GeomFill_SectionLaw) Loi;
672   Standard_Integer NbPoles,  NbKnots, Degree;
673   Handle(TColgp_HArray1OfPnt) Poles;
674   Handle(TColStd_HArray1OfReal) Knots, Weigth;
675   Handle(TColStd_HArray1OfInteger) Mults;
676   Handle(Geom_BSplineCurve) BS;
677   gp_Pnt PFirst;
678
679   Loi = myLaws->Value(I1);
680   Loi->SectionShape( NbPoles,  NbKnots, Degree);
681   Poles = new (TColgp_HArray1OfPnt) (1, NbPoles);
682   Weigth = new  (TColStd_HArray1OfReal) (1, NbPoles);
683   Loi->D0(Param, Poles->ChangeArray1(), Weigth->ChangeArray1());
684   Knots = new  (TColStd_HArray1OfReal) (1, NbKnots);
685   Loi->Knots(Knots->ChangeArray1());
686   Mults = new (TColStd_HArray1OfInteger) (1, NbKnots);
687   Loi->Mults(Mults->ChangeArray1());
688   BS = new (Geom_BSplineCurve) (Poles->Array1(), 
689                                 Weigth->Array1(), 
690                                 Knots->Array1(), 
691                                 Mults->Array1(), 
692                                 Degree,
693                                 Loi->IsUPeriodic());
694   PFirst = BS->Value( Knots->Value(Knots->Length()) );
695
696   Loi = myLaws->Value(I2);
697   Loi->SectionShape( NbPoles,  NbKnots, Degree);
698   Poles = new (TColgp_HArray1OfPnt) (1, NbPoles);
699   Weigth = new  (TColStd_HArray1OfReal) (1, NbPoles);
700   Loi->D0(Param, Poles->ChangeArray1(), Weigth->ChangeArray1());
701   Knots = new  (TColStd_HArray1OfReal) (1, NbKnots);
702   Loi->Knots(Knots->ChangeArray1());
703   Mults = new (TColStd_HArray1OfInteger) (1, NbKnots);
704   Loi->Mults(Mults->ChangeArray1());
705   BS = new (Geom_BSplineCurve) (Poles->Array1(), 
706                                 Weigth->Array1(), 
707                                 Knots->Array1(), 
708                                 Mults->Array1(), 
709                                 Degree,
710                                 Loi->IsUPeriodic());
711   Tol += PFirst.Distance(BS->Value( Knots->Value(1)));
712   return Tol;
713 }
714
715 //=======================================================================
716 //function : ConcatenedLaw
717 //purpose  : 
718 //=======================================================================
719
720  Handle(GeomFill_SectionLaw) BRepFill_NSections::ConcatenedLaw() const
721 {
722   Handle(GeomFill_SectionLaw) Law;
723   if (myLaws->Length() == 1) 
724     return myLaws->Value(1);
725   else {
726     Standard_Real Ufirst, Ulast, Vfirst, Vlast;
727     mySurface->Bounds(Ufirst, Ulast, Vfirst, Vlast);
728     TColGeom_SequenceOfCurve NCompo;
729     NCompo.Clear();
730     for (Standard_Integer jj=1; jj<=myShapes.Length(); jj++) {
731       NCompo.Append(mySurface->VIso(myParams(jj)));
732     }
733     Law = new (GeomFill_NSections)(NCompo, myTrsfs, myParams, 
734                                    Ufirst, Ulast, 
735                                    Vfirst, Vlast,
736                                    mySurface);
737   }
738   return Law;
739 }
740
741 //=======================================================================
742 //function : Continuity
743 //purpose  : 
744 //=======================================================================
745  GeomAbs_Shape BRepFill_NSections::Continuity(const Standard_Integer Index,
746                                               const Standard_Real TolAngular) const
747 {
748
749  Standard_Integer jj;
750  GeomAbs_Shape cont_jj;
751  GeomAbs_Shape cont = GeomAbs_C0; 
752
753  for (jj=1; jj<=myShapes.Length(); jj++) {
754
755    TopoDS_Edge Edge1, Edge2;
756    if ( (Index==0) || (Index==myEdges->ColLength()) ) {
757      if (!uclosed) return GeomAbs_C0; //The least possible error
758      
759      Edge1 = TopoDS::Edge (myEdges->Value(myEdges->ColLength(),jj));
760      Edge2 = TopoDS::Edge (myEdges->Value(1,jj));
761    }
762    else {
763      Edge1 = TopoDS::Edge (myEdges->Value(Index,jj));
764      Edge2 = TopoDS::Edge (myEdges->Value(Index+1,jj));
765    } 
766    
767    TopoDS_Vertex V1,V2;
768    if ( Edge1.Orientation() == TopAbs_REVERSED) {
769      V1 = TopExp::FirstVertex(Edge1);
770    }
771    else {
772      V1 = TopExp::LastVertex(Edge1);
773    }
774    if ( Edge2.Orientation() == TopAbs_REVERSED) {
775      V2 = TopExp::LastVertex(Edge2);
776    }
777    else {
778      V2 = TopExp::FirstVertex(Edge2);
779    }
780    
781    if (BRep_Tool::Degenerated(Edge1) || BRep_Tool::Degenerated(Edge2))
782      cont_jj = GeomAbs_CN;
783    else
784      {
785        Standard_Real U1 = BRep_Tool::Parameter(V1,Edge1);
786        Standard_Real U2 = BRep_Tool::Parameter(V2,Edge2);
787        BRepAdaptor_Curve Curve1(Edge1);
788        BRepAdaptor_Curve Curve2(Edge2);
789        Standard_Real Eps = BRep_Tool::Tolerance(V2) +
790          BRep_Tool::Tolerance(V1);
791        cont_jj = BRepLProp::Continuity(Curve1,Curve2,U1,U2, Eps, TolAngular);
792      }
793
794    if (jj==1) cont = cont_jj;
795    if (cont>cont_jj) cont = cont_jj;
796
797  }
798    
799  return cont;
800 }
801
802 //=======================================================================
803 //function : D0
804 //purpose  : 
805 //=======================================================================
806  void BRepFill_NSections::D0(const Standard_Real V, TopoDS_Shape& S)
807 {
808   TopoDS_Wire W;
809   BRepLib_MakeWire MW;
810   Standard_Integer ii, NbEdge = myLaws->Length();
811   for (ii=1; ii<=NbEdge ; ii++) {
812     Handle(Geom_BSplineCurve) Curve 
813       = Handle(Geom_BSplineCurve)::DownCast(myLaws->Value(ii)->BSplineSurface()->VIso(V));
814     Standard_Real first = Curve ->FirstParameter(),
815     last = Curve ->LastParameter();
816     TopoDS_Edge E = BRepLib_MakeEdge(Curve,first,last);
817     MW.Add(E);
818   }
819   TopAbs_Orientation Orien = TopAbs_FORWARD;
820   TopoDS_Shape aLocalShape = MW.Wire().Oriented(Orien);
821   S = TopoDS::Wire(aLocalShape);
822 //  S = TopoDS::Wire(MW.Wire().Oriented(Orien));
823   
824
825