0022731: Error on attempt to write in IGES 5.3 the attached brep model
[occt.git] / src / IGESControl / IGESControl_IGESBoundary.cxx
1 // File:        IGESControl_IGESBoundary.cxx
2 // Created:     Sat Feb  5 16:35:04 2000
3 // Author:      data exchange team
4 //              <det@kinox>
5
6 //06.01.99 pdn renaming ShapeFix_Wire::FixLittle to ShapeFix_Wire::FixSmall
7 //:n1 abv 20.01.99: BUC60328.rle (loopback): call FixSmall with Max(1.,preci)
8 //smh #1  11.03.99 PRO15640/15641, szv#2 PRO17393: call FixSameParameter after BuildCurve3d
9 //#74 rln 10.03.99 S4135: handling use of BRepLib::SameParameter by new static parameter
10 // pdn 18.03.99 S4135: using mintol instead of resolution from IGES file
11 // pdn 18.03.99 S4135: projecting with resolution from IGES file.
12 //%14 pdn 06.03.99 implementing fixFace in IGES
13 // S4135 pdn improvements in using of stdsameparameter flag
14 //#21 gka 12.04.99 CSR UKI60998 entities number - 13, 24 lost of boundaries during translation of tabulated cylinders
15 //S4181 pdn 15.04.99 implementing of reading IGES elementary surfaces. (instead of shift, reverce and 
16 //scale factors the transformation matrix and scale factor used)
17
18 #include <IGESControl_IGESBoundary.ixx>
19 #include <TColStd_HSequenceOfTransient.hxx>
20 #include <Geom2d_Curve.hxx>
21 #include <Geom_Curve.hxx>
22 #include <Geom_Plane.hxx>
23 #include <GeomAdaptor_Curve.hxx>
24 #include <Precision.hxx>
25 #include <TopoDS_Edge.hxx>
26 #include <TopoDS_Wire.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRep_Tool.hxx>
29 #include <ShapeBuild_Edge.hxx>
30 #include <ShapeAnalysis_Wire.hxx>
31 #include <ShapeAnalysis_ShapeTolerance.hxx>
32 #include <ShapeFix_Edge.hxx>
33 #include <ShapeFix_Wire.hxx>
34 #include <ShapeFix_ShapeTolerance.hxx>
35 #include <IGESToBRep.hxx>
36 #include <IGESToBRep_TopoCurve.hxx>
37 #include <Message_Msg.hxx>
38 #include <Interface_Static.hxx>
39 #include <ShapeAlgo.hxx>
40 #include <ShapeAlgo_AlgoContainer.hxx>
41 #include <ShapeAlgo_ToolContainer.hxx>
42 #include <IGESGeom_BSplineCurve.hxx>
43
44
45 //=======================================================================
46 //function : IGESControl_IGESBoundary
47 //purpose  : 
48 //=======================================================================
49
50 IGESControl_IGESBoundary::IGESControl_IGESBoundary() : IGESToBRep_IGESBoundary()
51 {
52 }
53
54 //=======================================================================
55 //function : IGESControl_IGESBoundary
56 //purpose  : 
57 //=======================================================================
58
59 IGESControl_IGESBoundary::IGESControl_IGESBoundary(const IGESToBRep_CurveAndSurface& CS) :
60        IGESToBRep_IGESBoundary (CS)
61 {
62 }
63
64 //=======================================================================
65 //function : Check
66 //purpose  : 
67 //=======================================================================
68
69  void IGESControl_IGESBoundary::Check(const Standard_Boolean result,const Standard_Boolean checkclosure,
70                                       const Standard_Boolean aokCurve3d, const Standard_Boolean aokCurve2d) 
71 {
72   Standard_Boolean Result = result;
73   Standard_Boolean okCurve3d = aokCurve3d, okCurve2d = aokCurve2d; 
74   Standard_Real maxtol = myCS.GetMaxTol();
75   
76   if (Result && checkclosure) {
77     //USA60022 7277 check of closure
78     Handle(ShapeAnalysis_Wire) saw = new ShapeAnalysis_Wire;
79     saw->Load (mysewd);
80     saw->SetPrecision (maxtol);
81     saw->CheckConnected (1);
82     if (saw->LastCheckStatus (ShapeExtend_FAIL)) {
83       saw->Load (mysewd3d);
84       saw->CheckConnected (1);
85       if (saw->LastCheckStatus (ShapeExtend_FAIL)) okCurve3d = Standard_False;
86       else                                         okCurve2d = Standard_False;
87       Result = Standard_False;
88     }
89   }
90   if (!Result) {
91     mysewd->Clear();
92     if (okCurve3d && mysewd3d->NbEdges() > 0) {
93       Message_Msg Msg1070("IGES_1070");//"Representations in the file are inconsistent. Recomputation from 3d"
94       Msg1070.Arg(3);
95       myCS.SendWarning(myentity,Msg1070);
96       mysewd = mysewd3d;
97     }
98     else if (okCurve2d && mysewd2d->NbEdges() > 0) {
99       Message_Msg Msg1070("IGES_1070");//"Representations in the file are inconsistent. Recomputation from 2d"
100       Msg1070.Arg(2);
101       myCS.SendWarning(myentity,Msg1070);
102       mysewd = mysewd2d;
103     }
104   }
105 }
106
107 //=======================================================================
108 //function : Transfer
109 //purpose  : 
110 //=======================================================================
111
112  Standard_Boolean IGESControl_IGESBoundary::Transfer(Standard_Boolean& okCurve,
113                                                      Standard_Boolean& okCurve3d,
114                                                      Standard_Boolean& okCurve2d,
115                                                      const Handle(IGESData_IGESEntity)& icurve3d,
116                                                      const Handle(ShapeExtend_WireData)& scurve3d,
117                                                      const Standard_Boolean usescurve,
118                                                      const Standard_Boolean toreverse3d,
119                                                      const Handle(IGESData_HArray1OfIGESEntity)& curves2d,
120                                                      const Standard_Boolean toreverse2d,
121                                                      const Standard_Integer number,
122                                                      Handle(ShapeExtend_WireData)& Gsewd) 
123 {
124   Gsewd                                = new ShapeExtend_WireData;//local translation (for mysewd)
125   Handle(ShapeExtend_WireData) Gsewd3d = new ShapeExtend_WireData;//local translation (for mysewd3d)
126   Handle(ShapeExtend_WireData) Gsewd2d = new ShapeExtend_WireData;//local translation (for mysewd2d)
127
128   Standard_Boolean revsewd, revnextsewd;
129   Standard_Real distmin, precision = myCS.GetEpsGeom() * myCS.GetUnitFactor(), maxtol = myCS.GetMaxTol();
130   
131   Handle(ShapeAnalysis_Wire) saw   = new ShapeAnalysis_Wire,
132                              saw3d = new ShapeAnalysis_Wire,
133                              saw2d = new ShapeAnalysis_Wire;
134   saw->Load   (Gsewd);   saw->SetPrecision   (precision);
135   saw3d->Load (Gsewd3d); saw3d->SetPrecision (precision);
136   saw2d->Load (Gsewd2d); saw2d->SetPrecision (precision);
137   
138   Standard_Boolean GTranslate3d = Standard_True, GTranslate2d = Standard_True,
139                    Preferred3d  = Standard_True, Preferred2d  = Standard_True;
140
141   Standard_Integer len3d = 0, len2d = 0;
142   Handle(TColStd_HSequenceOfTransient) seq3d, seq2d;
143   if (usescurve)
144     len3d = scurve3d->NbEdges();
145   else {
146     IGESToBRep::IGESCurveToSequenceOfIGESCurve (icurve3d, seq3d);
147       len3d = seq3d->Length();
148   }
149   if (!curves2d.IsNull()) {
150     for (Standard_Integer i = 1; i <= curves2d->Length(); i++)
151       IGESToBRep::IGESCurveToSequenceOfIGESCurve (curves2d->Value (i), seq2d);
152     len2d = seq2d->Length();
153   }
154
155   Standard_Integer surfcurv = myCS.GetSurfaceCurve();
156   if ((surfcurv == -2 && len2d > 0) || len3d == 0)
157     GTranslate3d = Standard_False;
158   else if (( surfcurv == -3 && len3d > 0) || len2d == 0)
159     GTranslate2d = Standard_False;
160  
161   if (GTranslate3d && GTranslate2d)
162     //Setting preference in the case of inconsitency between 3D and 2D
163     if      (surfcurv == 2)         Preferred3d = Standard_False;
164     else if (surfcurv == 3)         Preferred2d = Standard_False;
165     else if (myfilepreference == 2) Preferred3d = Standard_False;
166     else if (myfilepreference == 3) Preferred2d = Standard_False;
167     else                            Preferred3d = Standard_False;
168   
169   if (GTranslate3d && GTranslate2d && len3d != len2d) {
170     GTranslate3d = Preferred3d;
171     GTranslate2d = Preferred2d;
172   }
173     
174   IGESToBRep_TopoCurve TC (myCS);
175   
176   if (GTranslate3d && !GTranslate2d) {
177     if (usescurve) {
178       Gsewd->Add(scurve3d->Wire());
179     }
180     else {
181       TopoDS_Shape Sh = TC.TransferTopoCurve (icurve3d);
182       if (!Sh.IsNull()) {
183         Gsewd3d->Add (Sh);
184         if (toreverse3d) {
185           ReverseCurves3d (Gsewd3d);
186           Gsewd->Add (Gsewd3d->Wire());
187         }
188         else Gsewd->Add (Sh);//Gsewd = Gsewd3d is impossible to avoid sharing of sewd (UK1.igs entity 7)
189       }
190     }
191   }
192   else if (!GTranslate3d && GTranslate2d) {
193     for (Standard_Integer i = curves2d->Lower(); i <= curves2d->Upper(); i++) {
194       TopoDS_Shape Sh = TC.Transfer2dTopoCurve (Handle(IGESData_IGESEntity)::DownCast (curves2d->Value (i)),
195                                                 myface, mytrsf, myuFact);
196       if (!Sh.IsNull()) Gsewd2d->Add (Sh);
197     }
198     if (toreverse2d) {
199       ReverseCurves2d (Gsewd2d, myface);
200     }
201     Gsewd->Add (Gsewd2d->Wire());
202   }
203   else if( GTranslate3d && GTranslate2d ) {
204     //Translate both curves 3D and 2D
205     //Suppose that i-th segment in 2D curve corresponds to i-th segment in 3D curve
206     for (Standard_Integer i = 1; i <= len3d; i++) {
207       Standard_Boolean LTranslate3d = Standard_True, LTranslate2d = Standard_True;
208       
209       Handle(ShapeExtend_WireData) Lsewd3d = new ShapeExtend_WireData;
210       TC.SetBadCase (Standard_False); //:27
211       if (usescurve)
212         Lsewd3d->Add (scurve3d->Edge (i));
213       else {
214         TopoDS_Shape shape3d = TC.TransferTopoCurve (Handle(IGESData_IGESEntity)::DownCast (seq3d->Value (i)));
215         if (!shape3d.IsNull()) {
216           Lsewd3d->Add (shape3d);
217           if (toreverse3d) {
218             ReverseCurves3d (Lsewd3d);
219           }
220         }
221         else LTranslate3d = Standard_False;
222       }
223       Standard_Boolean bad3d = TC.BadCase(); //:27
224       okCurve3d = okCurve3d && ShapeAlgo::AlgoContainer()->ConnectNextWire (saw3d, Lsewd3d, maxtol, distmin, revsewd, revnextsewd);
225       
226       Handle(ShapeExtend_WireData) Lsewd2d = new ShapeExtend_WireData;
227       TC.SetBadCase (Standard_False); //:27
228       TopoDS_Shape shape2d = TC.Transfer2dTopoCurve (Handle(IGESData_IGESEntity)::DownCast (seq2d->Value (i)),
229                                                      myface, mytrsf, myuFact);
230       Standard_Boolean bad2d = TC.BadCase(); //:27
231       if (!shape2d.IsNull()) {
232         Lsewd2d->Add  (shape2d);
233         if (toreverse2d) {
234           ReverseCurves2d (Lsewd2d, myface);
235         }
236         okCurve2d = okCurve2d && ShapeAlgo::AlgoContainer()->ConnectNextWire (saw2d, Lsewd2d, maxtol, distmin, revsewd, revnextsewd);
237       }
238       else LTranslate2d = Standard_False;
239       
240 //     if (LTranslate3d && LTranslate2d && (Lsewd3d->NbEdges() != Lsewd2d->NbEdges() || bad3d || bad2d)) {
241       Standard_Boolean isBSpline = Standard_False;
242       if(!usescurve && !seq3d->Value (i).IsNull() && !seq2d->Value (i).IsNull())
243         isBSpline = seq3d->Value (i)->IsKind(STANDARD_TYPE(IGESGeom_BSplineCurve)) &&
244           seq2d->Value (i)->IsKind(STANDARD_TYPE(IGESGeom_BSplineCurve));
245       
246       if (LTranslate3d && LTranslate2d && 
247           (
248            (isBSpline && (Lsewd3d->NbEdges() != Lsewd2d->NbEdges())) ||
249            (!isBSpline && (Lsewd3d->NbEdges() != 1 || Lsewd2d->NbEdges() != 1)) ||
250            bad3d || bad2d
251            )) {
252         
253         LTranslate3d = Preferred3d;
254         LTranslate2d = Preferred2d;
255       }
256       Handle(ShapeExtend_WireData) Lsewd;//Lsewd3d or Lsewd2d or Lsewd3d+pcurve
257       if      ( LTranslate3d && !LTranslate2d) Lsewd = Lsewd3d;
258       else if (!LTranslate3d &&  LTranslate2d) Lsewd = Lsewd2d;
259       else {
260         Lsewd = Lsewd3d;
261         //copying pcurve to edge with 3D curve
262         Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
263         for (Standard_Integer iedge = 1; iedge <= Lsewd3d->NbEdges(); iedge++) {
264           TopoDS_Edge edge3d = Lsewd3d->Edge (iedge), edge2d = Lsewd2d->Edge (iedge);
265           if (!IGESToBRep::TransferPCurve (edge2d, edge3d, myface)) continue;
266           if (sfe->FixReversed2d (edge3d, myface)) {
267 #ifdef DEB
268             cout << "Warning: IGESToBRep_IGESBoundary: 2D curve of edge was reversed" << endl;
269 #endif
270           }
271           //#74 rln 10.03.99 S4135: handling use of BRepLib::SameParameter by new static parameter
272           if (Interface_Static::IVal ("read.stdsameparameter.mode")) {
273             Standard_Real first, last;
274             BRep_Tool::Range(edge3d,first,last);
275             // pdn 08.04.99 S4135 optimizing in computation of SPTol
276             //choosing tolerance according to Approx_SameParameter: 50 * 22
277             Standard_Real SPTol = Min (precision, Abs (last - first)/1000);
278             BRep_Builder B;
279             B.SameParameter (edge3d, Standard_False);
280             sfe->FixSameParameter (edge3d, SPTol);
281           }
282           else
283             sfe->FixSameParameter (edge3d);
284           Standard_Real maxdev = BRep_Tool::Tolerance (edge3d);
285           //pdn 08.04.99 S4135 recomputing only if deviation is greater than maxtol
286           if (maxdev > maxtol) { //:e2
287 #ifdef DEB
288             cout << "Warning: IGESToBRep_IGESBoundary: Deviation = " << maxdev << endl;
289 #endif
290             ShapeFix_ShapeTolerance().SetTolerance (edge3d, Precision::Confusion());
291             for (Standard_Integer ie = 1; ie <= iedge; ie++)
292               ShapeBuild_Edge().RemovePCurve (Lsewd3d->Edge (ie), myface);
293             if (Preferred3d) {
294 #ifdef DEB
295               cout << "Warning: IGESToBRep_IGESBoundary: 3D and 2D curves are inconsistent; 2D is ignored" << endl;
296 #endif
297             }
298             else {
299 #ifdef DEB
300               cout << "Warning: IGESToBRep_IGESBoundary: 3D and 2D curves are inconsistent; 3D is ignored" << endl;
301 #endif
302               Lsewd = Lsewd2d;
303             }
304             break;
305           }
306         }
307       }
308       okCurve = okCurve && ShapeAlgo::AlgoContainer()->ConnectNextWire (saw, Lsewd, maxtol, distmin, revsewd, revnextsewd);
309       if (!okCurve) {
310 #ifdef DEB
311         cout << "Warning: IGESToBRep_IGESBoundary: Curves " << i - 1 << " and " << i << " cannot be connected" << endl;
312 #endif
313         Gsewd3d = new ShapeExtend_WireData;
314         for (Standard_Integer i = 1; i <= len3d; i++) {
315           if (usescurve)
316             Gsewd3d->Add (scurve3d->Edge (i));
317           else {
318             TopoDS_Shape Sh =
319               TC.TransferTopoCurve (Handle(IGESData_IGESEntity)::DownCast (seq3d->Value (i)));
320             if (!Sh.IsNull()) Gsewd3d->Add (Sh);
321           }
322         }
323         if (toreverse3d) {
324           ReverseCurves3d(Gsewd3d);
325         }
326         Gsewd2d = new ShapeExtend_WireData;
327         for (Standard_Integer i = 1; i <= len2d; i++) {
328           TopoDS_Shape Sh = TC.Transfer2dTopoCurve (Handle(IGESData_IGESEntity)::DownCast (seq2d->Value (i)),
329                                                     myface, mytrsf, myuFact);
330           if (!Sh.IsNull()) Gsewd2d->Add (Sh);
331         }
332         if (toreverse2d) {
333           ReverseCurves2d (Gsewd2d, myface);
334         }
335         Handle(ShapeFix_Wire) sfw3 = new ShapeFix_Wire(Gsewd3d->Wire(),myface,precision);
336         sfw3->Perform();
337         TopoDS_Wire w3 = sfw3->Wire();
338         Handle(ShapeFix_Wire) sfw2 = new ShapeFix_Wire(Gsewd2d->Wire(),myface,precision);
339         sfw2->Perform();
340         TopoDS_Wire w2 = sfw2->Wire();
341         ShapeAnalysis_ShapeTolerance ST;
342         double tol3 = ST.Tolerance(w3,1);
343         double tol2 = ST.Tolerance(w2,1);
344         Gsewd3d = new ShapeExtend_WireData;
345         Gsewd2d = new ShapeExtend_WireData;
346         Gsewd3d->Add(w3);
347         Gsewd2d->Add(w3);
348         if(tol3<tol2)
349           Gsewd->Add(w3);
350         else
351           Gsewd->Add(w2);
352         okCurve = Standard_True;
353         okCurve2d = Standard_True;
354         okCurve3d = Standard_True;
355       }
356     }
357   }
358   
359   if (number > 1) {
360     saw->Load (mysewd);
361     okCurve   = okCurve &&
362       ShapeAlgo::AlgoContainer()->ConnectNextWire (saw, Gsewd, maxtol,
363                                                    distmin, revsewd, revnextsewd);
364     saw3d->Load (mysewd3d);
365     okCurve3d = okCurve3d &&
366       ShapeAlgo::AlgoContainer()->ConnectNextWire (saw3d, Gsewd3d, maxtol,
367                                                    distmin, revsewd, revnextsewd);
368     saw2d->Load (mysewd2d);
369     okCurve2d = okCurve2d &&
370       ShapeAlgo::AlgoContainer()->ConnectNextWire (saw2d, Gsewd2d, maxtol,
371                                                    distmin, revsewd, revnextsewd);
372   }
373   else {
374     mysewd   = Gsewd;
375     mysewd3d = Gsewd3d;
376     mysewd2d = Gsewd2d;
377   }
378   return okCurve;
379 }
380