0023591: IGES Boundary Entity containing Composite Curve fails to translate
[occt.git] / src / IGESControl / IGESControl_IGESBoundary.cxx
1 // Created on: 2000-02-05
2 // Created by: data exchange team
3 // Copyright (c) 2000-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 //06.01.99 pdn renaming ShapeFix_Wire::FixLittle to ShapeFix_Wire::FixSmall
22 //:n1 abv 20.01.99: BUC60328.rle (loopback): call FixSmall with Max(1.,preci)
23 //smh #1  11.03.99 PRO15640/15641, szv#2 PRO17393: call FixSameParameter after BuildCurve3d
24 //#74 rln 10.03.99 S4135: handling use of BRepLib::SameParameter by new static parameter
25 // pdn 18.03.99 S4135: using mintol instead of resolution from IGES file
26 // pdn 18.03.99 S4135: projecting with resolution from IGES file.
27 //%14 pdn 06.03.99 implementing fixFace in IGES
28 // S4135 pdn improvements in using of stdsameparameter flag
29 //#21 gka 12.04.99 CSR UKI60998 entities number - 13, 24 lost of boundaries during translation of tabulated cylinders
30 //S4181 pdn 15.04.99 implementing of reading IGES elementary surfaces. (instead of shift, reverce and 
31 //scale factors the transformation matrix and scale factor used)
32
33 #include <IGESControl_IGESBoundary.ixx>
34 #include <TColStd_HSequenceOfTransient.hxx>
35 #include <Geom2d_Curve.hxx>
36 #include <Geom_Curve.hxx>
37 #include <Geom_Plane.hxx>
38 #include <GeomAdaptor_Curve.hxx>
39 #include <Precision.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Wire.hxx>
42 #include <BRep_Builder.hxx>
43 #include <BRep_Tool.hxx>
44 #include <ShapeBuild_Edge.hxx>
45 #include <ShapeAnalysis_Wire.hxx>
46 #include <ShapeAnalysis_ShapeTolerance.hxx>
47 #include <ShapeFix_Edge.hxx>
48 #include <ShapeFix_Wire.hxx>
49 #include <ShapeFix_ShapeTolerance.hxx>
50 #include <IGESToBRep.hxx>
51 #include <IGESToBRep_TopoCurve.hxx>
52 #include <Message_Msg.hxx>
53 #include <Interface_Static.hxx>
54 #include <ShapeAlgo.hxx>
55 #include <ShapeAlgo_AlgoContainer.hxx>
56 #include <ShapeAlgo_ToolContainer.hxx>
57 #include <IGESGeom_BSplineCurve.hxx>
58
59
60 //=======================================================================
61 //function : IGESControl_IGESBoundary
62 //purpose  : 
63 //=======================================================================
64
65 IGESControl_IGESBoundary::IGESControl_IGESBoundary() : IGESToBRep_IGESBoundary()
66 {
67 }
68
69 //=======================================================================
70 //function : IGESControl_IGESBoundary
71 //purpose  : 
72 //=======================================================================
73
74 IGESControl_IGESBoundary::IGESControl_IGESBoundary(const IGESToBRep_CurveAndSurface& CS) :
75        IGESToBRep_IGESBoundary (CS)
76 {
77 }
78
79 //=======================================================================
80 //function : Check
81 //purpose  : 
82 //=======================================================================
83
84  void IGESControl_IGESBoundary::Check(const Standard_Boolean result,const Standard_Boolean checkclosure,
85                                       const Standard_Boolean aokCurve3d, const Standard_Boolean aokCurve2d) 
86 {
87   Standard_Boolean Result = result;
88   Standard_Boolean okCurve3d = aokCurve3d, okCurve2d = aokCurve2d; 
89   Standard_Real maxtol = myCS.GetMaxTol();
90   
91   if (Result && checkclosure) {
92     //USA60022 7277 check of closure
93     Handle(ShapeAnalysis_Wire) saw = new ShapeAnalysis_Wire;
94     saw->Load (mysewd);
95     saw->SetPrecision (maxtol);
96     saw->CheckConnected (1);
97     if (saw->LastCheckStatus (ShapeExtend_FAIL)) {
98       saw->Load (mysewd3d);
99       saw->CheckConnected (1);
100       if (saw->LastCheckStatus (ShapeExtend_FAIL)) okCurve3d = Standard_False;
101       else                                         okCurve2d = Standard_False;
102       Result = Standard_False;
103     }
104   }
105   if (!Result) {
106     mysewd->Clear();
107     if (okCurve3d && mysewd3d->NbEdges() > 0) {
108       Message_Msg Msg1070("IGES_1070");//"Representations in the file are inconsistent. Recomputation from 3d"
109       Msg1070.Arg(3);
110       myCS.SendWarning(myentity,Msg1070);
111       mysewd = mysewd3d;
112     }
113     else if (okCurve2d && mysewd2d->NbEdges() > 0) {
114       Message_Msg Msg1070("IGES_1070");//"Representations in the file are inconsistent. Recomputation from 2d"
115       Msg1070.Arg(2);
116       myCS.SendWarning(myentity,Msg1070);
117       mysewd = mysewd2d;
118     }
119   }
120 }
121
122 //=======================================================================
123 //function : Connect
124 //purpose  : Connects theNextWD to theWD using theSAW. 
125 //           First, connects edges of theNextWD by calling ShapeFix_Wire::FixConnected(). This
126 //           is necessary when theNextWD was built using multiple curves from the Composite
127 //           Curve (as ShapeExtend_WireData::Wire() would otherwise produce a wrong 
128 //           disconnected TopoDS_Wire).
129 //           FixConnected() will only update the edges resulting from different composite
130 //           curve segments. Edges resulting from splitting C0 curve will already be
131 //           connected.
132 //=======================================================================
133 static Standard_Boolean Connect (const Handle(ShapeAnalysis_Wire)& theSAW,
134                                  const Handle(ShapeExtend_WireData)& theWD,
135                                  const Handle(ShapeExtend_WireData)& theNextWD,
136                                  const Standard_Boolean theConnectNextWD,
137                                  const Standard_Real theMaxTol,
138                                  Standard_Real& theDistMin,
139                                  Standard_Boolean& theReverseWD,
140                                  Standard_Boolean& theReverseNextWD)
141 {
142     theSAW->Load (theWD);
143     if (theConnectNextWD) {
144       Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
145       sfw->Load (theNextWD);
146       sfw->ClosedWireMode() = Standard_False; //internal connections are enough
147       sfw->FixConnected();
148     }
149     return ShapeAlgo::AlgoContainer()->ConnectNextWire (theSAW, theNextWD,
150       theMaxTol, theDistMin, theReverseWD, theReverseNextWD);
151 }
152
153 //=======================================================================
154 //function : Transfer
155 //purpose  : 
156 //=======================================================================
157
158  Standard_Boolean IGESControl_IGESBoundary::Transfer(Standard_Boolean& okCurve,
159                                                      Standard_Boolean& okCurve3d,
160                                                      Standard_Boolean& okCurve2d,
161                                                      const Handle(IGESData_IGESEntity)& icurve3d,
162                                                      const Handle(ShapeExtend_WireData)& scurve3d,
163                                                      const Standard_Boolean usescurve,
164                                                      const Standard_Boolean toreverse3d,
165                                                      const Handle(IGESData_HArray1OfIGESEntity)& curves2d,
166                                                      const Standard_Boolean toreverse2d,
167                                                      const Standard_Integer number,
168                                                      Handle(ShapeExtend_WireData)& Gsewd) 
169 {
170   Gsewd                                = new ShapeExtend_WireData;//local translation (for mysewd)
171   Handle(ShapeExtend_WireData) Gsewd3d = new ShapeExtend_WireData;//local translation (for mysewd3d)
172   Handle(ShapeExtend_WireData) Gsewd2d = new ShapeExtend_WireData;//local translation (for mysewd2d)
173
174   Standard_Boolean revsewd, revnextsewd;
175   Standard_Real distmin, precision = myCS.GetEpsGeom() * myCS.GetUnitFactor(), maxtol = myCS.GetMaxTol();
176   
177   Handle(ShapeAnalysis_Wire) saw   = new ShapeAnalysis_Wire,
178                              saw3d = new ShapeAnalysis_Wire,
179                              saw2d = new ShapeAnalysis_Wire;
180   saw->Load   (Gsewd);   saw->SetPrecision   (precision);
181   saw3d->Load (Gsewd3d); saw3d->SetPrecision (precision);
182   saw2d->Load (Gsewd2d); saw2d->SetPrecision (precision);
183   
184   Standard_Boolean GTranslate3d = Standard_True, GTranslate2d = Standard_True,
185                    Preferred3d  = Standard_True, Preferred2d  = Standard_True;
186
187   Standard_Integer len3d = 0, len2d = 0;
188   Handle(TColStd_HSequenceOfTransient) seq3d, seq2d;
189   if (usescurve)
190     len3d = scurve3d->NbEdges();
191   else {
192     IGESToBRep::IGESCurveToSequenceOfIGESCurve (icurve3d, seq3d);
193       len3d = seq3d->Length();
194   }
195   if (!curves2d.IsNull()) {
196     for (Standard_Integer i = 1; i <= curves2d->Length(); i++)
197       IGESToBRep::IGESCurveToSequenceOfIGESCurve (curves2d->Value (i), seq2d);
198     len2d = seq2d->Length();
199   }
200
201   Standard_Integer surfcurv = myCS.GetSurfaceCurve();
202   if ((surfcurv == -2 && len2d > 0) || len3d == 0)
203     GTranslate3d = Standard_False;
204   else if (( surfcurv == -3 && len3d > 0) || len2d == 0)
205     GTranslate2d = Standard_False;
206  
207   if (GTranslate3d && GTranslate2d)
208     //Setting preference in the case of inconsitency between 3D and 2D
209     if      (surfcurv == 2)         Preferred3d = Standard_False;
210     else if (surfcurv == 3)         Preferred2d = Standard_False;
211     else if (myfilepreference == 2) Preferred3d = Standard_False;
212     else if (myfilepreference == 3) Preferred2d = Standard_False;
213     else                            Preferred3d = Standard_False;
214   
215   if (GTranslate3d && GTranslate2d && len3d != len2d) {
216     GTranslate3d = Preferred3d;
217     GTranslate2d = Preferred2d;
218   }
219     
220   IGESToBRep_TopoCurve TC (myCS);
221   
222   if (GTranslate3d && !GTranslate2d) {
223     if (usescurve) {
224       Gsewd->Add(scurve3d->Wire());
225     }
226     else {
227       TopoDS_Shape Sh = TC.TransferTopoCurve (icurve3d);
228       if (!Sh.IsNull()) {
229         Gsewd3d->Add (Sh);
230         if (toreverse3d) {
231           ReverseCurves3d (Gsewd3d);
232           Gsewd->Add (Gsewd3d->Wire());
233         }
234         else Gsewd->Add (Sh);//Gsewd = Gsewd3d is impossible to avoid sharing of sewd (UK1.igs entity 7)
235       }
236     }
237   }
238   else if (!GTranslate3d && GTranslate2d) {
239     for (Standard_Integer i = curves2d->Lower(); i <= curves2d->Upper(); i++) {
240       TopoDS_Shape Sh = TC.Transfer2dTopoCurve (Handle(IGESData_IGESEntity)::DownCast (curves2d->Value (i)),
241                                                 myface, mytrsf, myuFact);
242       if (!Sh.IsNull()) Gsewd2d->Add (Sh);
243     }
244     if (toreverse2d) {
245       ReverseCurves2d (Gsewd2d, myface);
246     }
247     Gsewd->Add (Gsewd2d->Wire());
248   }
249   else if( GTranslate3d && GTranslate2d ) {
250     //Translate both curves 3D and 2D
251     //Suppose that i-th segment in 2D curve corresponds to i-th segment in 3D curve
252     for (Standard_Integer i = 1; i <= len3d; i++) {
253       Standard_Boolean LTranslate3d = Standard_True, LTranslate2d = Standard_True;
254       
255       Handle(ShapeExtend_WireData) Lsewd3d = new ShapeExtend_WireData;
256       TC.SetBadCase (Standard_False); //:27
257       if (usescurve)
258         Lsewd3d->Add (scurve3d->Edge (i));
259       else {
260         TopoDS_Shape shape3d = TC.TransferTopoCurve (Handle(IGESData_IGESEntity)::DownCast (seq3d->Value (i)));
261         if (!shape3d.IsNull()) {
262           Lsewd3d->Add (shape3d);
263           if (toreverse3d) {
264             ReverseCurves3d (Lsewd3d);
265           }
266         }
267         else LTranslate3d = Standard_False;
268       }
269       Standard_Boolean bad3d = TC.BadCase(); //:27
270       okCurve3d = okCurve3d && ShapeAlgo::AlgoContainer()->ConnectNextWire (saw3d, Lsewd3d, maxtol, distmin, revsewd, revnextsewd);
271       
272       Handle(ShapeExtend_WireData) Lsewd2d = new ShapeExtend_WireData;
273       TC.SetBadCase (Standard_False); //:27
274       TopoDS_Shape shape2d = TC.Transfer2dTopoCurve (Handle(IGESData_IGESEntity)::DownCast (seq2d->Value (i)),
275                                                      myface, mytrsf, myuFact);
276       Standard_Boolean bad2d = TC.BadCase(); //:27
277       if (!shape2d.IsNull()) {
278         Lsewd2d->Add  (shape2d);
279         if (toreverse2d) {
280           ReverseCurves2d (Lsewd2d, myface);
281         }
282         okCurve2d = okCurve2d && ShapeAlgo::AlgoContainer()->ConnectNextWire (saw2d, Lsewd2d, maxtol, distmin, revsewd, revnextsewd);
283       }
284       else LTranslate2d = Standard_False;
285       
286 //     if (LTranslate3d && LTranslate2d && (Lsewd3d->NbEdges() != Lsewd2d->NbEdges() || bad3d || bad2d)) {
287       Standard_Boolean isBSpline = Standard_False;
288       if(!usescurve && !seq3d->Value (i).IsNull() && !seq2d->Value (i).IsNull())
289         isBSpline = seq3d->Value (i)->IsKind(STANDARD_TYPE(IGESGeom_BSplineCurve)) &&
290           seq2d->Value (i)->IsKind(STANDARD_TYPE(IGESGeom_BSplineCurve));
291       
292       if (LTranslate3d && LTranslate2d && 
293           (
294            (isBSpline && (Lsewd3d->NbEdges() != Lsewd2d->NbEdges())) ||
295            (!isBSpline && (Lsewd3d->NbEdges() != 1 || Lsewd2d->NbEdges() != 1)) ||
296            bad3d || bad2d
297            )) {
298         
299         LTranslate3d = Preferred3d;
300         LTranslate2d = Preferred2d;
301       }
302       Handle(ShapeExtend_WireData) Lsewd;//Lsewd3d or Lsewd2d or Lsewd3d+pcurve
303       if      ( LTranslate3d && !LTranslate2d) Lsewd = Lsewd3d;
304       else if (!LTranslate3d &&  LTranslate2d) Lsewd = Lsewd2d;
305       else {
306         Lsewd = Lsewd3d;
307         //copying pcurve to edge with 3D curve
308         Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
309         for (Standard_Integer iedge = 1; iedge <= Lsewd3d->NbEdges(); iedge++) {
310           TopoDS_Edge edge3d = Lsewd3d->Edge (iedge), edge2d = Lsewd2d->Edge (iedge);
311           if (!IGESToBRep::TransferPCurve (edge2d, edge3d, myface)) continue;
312           if (sfe->FixReversed2d (edge3d, myface)) {
313 #ifdef DEB
314             cout << "Warning: IGESToBRep_IGESBoundary: 2D curve of edge was reversed" << endl;
315 #endif
316           }
317           //#74 rln 10.03.99 S4135: handling use of BRepLib::SameParameter by new static parameter
318           if (Interface_Static::IVal ("read.stdsameparameter.mode")) {
319             Standard_Real first, last;
320             BRep_Tool::Range(edge3d,first,last);
321             // pdn 08.04.99 S4135 optimizing in computation of SPTol
322             //choosing tolerance according to Approx_SameParameter: 50 * 22
323             Standard_Real SPTol = Min (precision, Abs (last - first)/1000);
324             BRep_Builder B;
325             B.SameParameter (edge3d, Standard_False);
326             sfe->FixSameParameter (edge3d, SPTol);
327           }
328           else
329             sfe->FixSameParameter (edge3d);
330           Standard_Real maxdev = BRep_Tool::Tolerance (edge3d);
331           //pdn 08.04.99 S4135 recomputing only if deviation is greater than maxtol
332           if (maxdev > maxtol) { //:e2
333 #ifdef DEB
334             cout << "Warning: IGESToBRep_IGESBoundary: Deviation = " << maxdev << endl;
335 #endif
336             ShapeFix_ShapeTolerance().SetTolerance (edge3d, Precision::Confusion());
337             for (Standard_Integer ie = 1; ie <= iedge; ie++)
338               ShapeBuild_Edge().RemovePCurve (Lsewd3d->Edge (ie), myface);
339             if (Preferred3d) {
340 #ifdef DEB
341               cout << "Warning: IGESToBRep_IGESBoundary: 3D and 2D curves are inconsistent; 2D is ignored" << endl;
342 #endif
343             }
344             else {
345 #ifdef DEB
346               cout << "Warning: IGESToBRep_IGESBoundary: 3D and 2D curves are inconsistent; 3D is ignored" << endl;
347 #endif
348               Lsewd = Lsewd2d;
349             }
350             break;
351           }
352         }
353       }
354       okCurve = okCurve && ShapeAlgo::AlgoContainer()->ConnectNextWire (saw, Lsewd, maxtol, distmin, revsewd, revnextsewd);
355       if (!okCurve) {
356 #ifdef DEB
357         cout << "Warning: IGESToBRep_IGESBoundary: Curves " << i - 1 << " and " << i << " cannot be connected" << endl;
358 #endif
359         Gsewd3d = new ShapeExtend_WireData;
360         for (Standard_Integer i = 1; i <= len3d; i++) {
361           if (usescurve)
362             Gsewd3d->Add (scurve3d->Edge (i));
363           else {
364             TopoDS_Shape Sh =
365               TC.TransferTopoCurve (Handle(IGESData_IGESEntity)::DownCast (seq3d->Value (i)));
366             if (!Sh.IsNull()) Gsewd3d->Add (Sh);
367           }
368         }
369         if (toreverse3d) {
370           ReverseCurves3d(Gsewd3d);
371         }
372         Gsewd2d = new ShapeExtend_WireData;
373         for (Standard_Integer i = 1; i <= len2d; i++) {
374           TopoDS_Shape Sh = TC.Transfer2dTopoCurve (Handle(IGESData_IGESEntity)::DownCast (seq2d->Value (i)),
375                                                     myface, mytrsf, myuFact);
376           if (!Sh.IsNull()) Gsewd2d->Add (Sh);
377         }
378         if (toreverse2d) {
379           ReverseCurves2d (Gsewd2d, myface);
380         }
381         Handle(ShapeFix_Wire) sfw3 = new ShapeFix_Wire(Gsewd3d->Wire(),myface,precision);
382         sfw3->Perform();
383         TopoDS_Wire w3 = sfw3->Wire();
384         Handle(ShapeFix_Wire) sfw2 = new ShapeFix_Wire(Gsewd2d->Wire(),myface,precision);
385         sfw2->Perform();
386         TopoDS_Wire w2 = sfw2->Wire();
387         ShapeAnalysis_ShapeTolerance ST;
388         double tol3 = ST.Tolerance(w3,1);
389         double tol2 = ST.Tolerance(w2,1);
390         Gsewd3d = new ShapeExtend_WireData;
391         Gsewd2d = new ShapeExtend_WireData;
392         Gsewd3d->Add(w3);
393         Gsewd2d->Add(w3);
394         if(tol3<tol2)
395           Gsewd->Add(w3);
396         else
397           Gsewd->Add(w2);
398         okCurve = Standard_True;
399         okCurve2d = Standard_True;
400         okCurve3d = Standard_True;
401       }
402     }
403   }
404   
405   if (number > 1) {
406     okCurve   = okCurve && Connect (saw, mysewd, Gsewd, (len3d > 1) || (len2d > 1), maxtol,
407       distmin, revsewd, revnextsewd);
408     okCurve3d = okCurve3d && Connect (saw3d, mysewd3d, Gsewd3d, len3d > 1, maxtol,
409       distmin, revsewd, revnextsewd);
410     okCurve2d = okCurve2d && Connect (saw2d, mysewd2d, Gsewd2d, len2d > 1, maxtol,
411       distmin, revsewd, revnextsewd);
412   }
413   else {
414     mysewd   = Gsewd;
415     mysewd3d = Gsewd3d;
416     mysewd2d = Gsewd2d;
417   }
418   return okCurve;
419 }
420