0022726: Exception on restoring shape
[occt.git] / src / XSAlgo / XSAlgo_AlgoContainer.cxx
CommitLineData
7fd59977 1// File: XSAlgo_AlgoContainer.cxx
2// Created: Wed Jan 19 17:52:41 2000
3// Author: data exchange team
4// <det@nnov>
5
6
7#include <XSAlgo_AlgoContainer.ixx>
8
9#include <Standard_ErrorHandler.hxx>
10#include <Standard_Failure.hxx>
11
12#include <Message_ListOfMsg.hxx>
13#include <Message_ListIteratorOfListOfMsg.hxx>
14
15#include <gp_Pnt.hxx>
16#include <gp_Pnt2d.hxx>
17#include <Geom_Curve.hxx>
18#include <Geom_Surface.hxx>
19#include <Geom2d_Curve.hxx>
20#include <TopoDS.hxx>
21#include <TopoDS_Vertex.hxx>
22#include <TopoDS_Iterator.hxx>
23#include <TopExp.hxx>
24#include <BRep_Tool.hxx>
25#include <BRep_Builder.hxx>
26#include <BRepBuilderAPI_MakeEdge.hxx>
27#include <TopTools_DataMapOfShapeShape.hxx>
28#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
29
30#include <ShapeProcess.hxx>
31#include <ShapeProcess_ShapeContext.hxx>
32#include <ShapeAlgo.hxx>
33#include <ShapeAlgo_AlgoContainer.hxx>
34#include <ShapeAlgo_ToolContainer.hxx>
35#include <ShapeBuild_ReShape.hxx>
36#include <ShapeExtend_DataMapOfShapeListOfMsg.hxx>
37#include <ShapeExtend_MsgRegistrator.hxx>
38#include <ShapeFix_Shape.hxx>
39#include <ShapeBuild_Edge.hxx>
40#include <ShapeAnalysis_Edge.hxx>
41#include <ShapeFix_Edge.hxx>
42#include <UnitsMethods.hxx>
43#include <ShapeCustom.hxx>
44
45#include <TransferBRep.hxx>
46#include <TransferBRep_ShapeMapper.hxx>
47#include <TransferBRep_ShapeBinder.hxx>
48#include <Transfer_TransientListBinder.hxx>
49#include <Resource_Manager.hxx>
50#include <Interface_Static.hxx>
51#include <Message_Msg.hxx>
52
53//=======================================================================
54//function : XSAlgo_AlgoContainer
55//purpose :
56//=======================================================================
57
58XSAlgo_AlgoContainer::XSAlgo_AlgoContainer()
59{
60 myTC = new XSAlgo_ToolContainer;
61}
62
63//=======================================================================
64//function : PrepareForTransfer
65//purpose :
66//=======================================================================
67
68void XSAlgo_AlgoContainer::PrepareForTransfer() const
69{
70 UnitsMethods::SetCasCadeLengthUnit ( Interface_Static::IVal("xstep.cascade.unit") );
71}
72
73//=======================================================================
74//function : ProcessShape
75//purpose :
76//=======================================================================
77
78TopoDS_Shape XSAlgo_AlgoContainer::ProcessShape (const TopoDS_Shape& shape,
79 const Standard_Real Prec,
80 const Standard_Real maxTol,
81 const Standard_CString prscfile,
82 const Standard_CString pseq,
83 Handle(Standard_Transient)& info) const
84{
85 if ( shape.IsNull() ) return shape;
86
87 Handle(ShapeProcess_ShapeContext) context = Handle(ShapeProcess_ShapeContext)::DownCast ( info );
88 if ( context.IsNull() ) {
89 Standard_CString rscfile = Interface_Static::CVal ( prscfile );
90 if ( ! rscfile ) rscfile = prscfile;
91 context = new ShapeProcess_ShapeContext (shape, rscfile);
92 context->SetDetalisation ( TopAbs_EDGE );
93 }
94 info = context;
95
96 Standard_CString seq = Interface_Static::CVal ( pseq );
97 if ( ! seq ) seq = pseq;
98
99 // if resource file is not loaded or does not define <seq>.exec.op,
100 // do default fixes
101 Handle(Resource_Manager) rsc = context->ResourceManager();
102 TCollection_AsciiString str ( seq );
103 str += ".exec.op";
104 if ( ! rsc->Find ( str.ToCString() ) ) {
105#ifdef DEB
106 {
107 static Standard_Integer time = 0;
108 if ( ! time )
109 cout << "Warning: XSAlgo_AlgoContainer::ProcessShape(): Sequence " << str.ToCString() <<
110 " is not defined in " << prscfile << " resource; do default processing" << endl;
111 time++;
112 }
113#endif
114 // if FromSTEP or FromIGES, do default ShapeFix
115 if ( ! strncmp ( pseq, "read.", 5 ) ) {
116 try {
117 OCC_CATCH_SIGNALS
118 Handle(ShapeExtend_MsgRegistrator) msg = new ShapeExtend_MsgRegistrator;
119 Handle(ShapeFix_Shape) sfs = ShapeAlgo::AlgoContainer()->ToolContainer()->FixShape();
120 sfs->Init ( shape );
121 sfs->SetMsgRegistrator ( msg );
122 sfs->SetPrecision ( Prec );
123 sfs->SetMaxTolerance ( maxTol );
124 sfs->FixFaceTool()->FixWireTool()->FixSameParameterMode() = Standard_False;
125 sfs->FixSolidTool()->CreateOpenSolidMode() = Standard_False;
126 sfs->Perform();
127
128 TopoDS_Shape S = sfs->Shape();
129 if ( ! S.IsNull() && S != shape ) {
130 context->RecordModification ( sfs->Context(), msg );
131 context->SetResult ( S );
132 }
133 }
134 catch (Standard_Failure) {
135#ifdef DEB
136 cout << "Error: XSAlgo_AlgoContainer::ProcessShape(): Exception in ShapeFix::Shape" << endl;
137 Standard_Failure::Caught()->Print(cout); cout << endl;
138#endif
139 }
140 return context->Result();
141 }
142 // if ToSTEP or ToIGES, define sequence of DirectFaces
143 else if ( ! strcmp ( pseq, "write.step.sequence" ) ) {
144 rsc->SetResource ( str.ToCString(), "DirectFaces" );
145 }
146 else if ( ! strcmp ( pseq, "write.iges.sequence" ) ) {
147 rsc->SetResource ( str.ToCString(), "DirectFaces" );
148 }
149 }
150
151 // Define runtime tolerances and do Shape Processing
152 rsc->SetResource ( "Runtime.Tolerance", Prec );
153 rsc->SetResource ( "Runtime.MaxTolerance", maxTol );
154 ShapeProcess::Perform ( context, seq );
155
156 return context->Result();
157}
158
159//=======================================================================
160//function : PerformFixShape
161//purpose :
162//=======================================================================
163
164/*
165TopoDS_Shape XSAlgo_AlgoContainer::PerformFixShape(const TopoDS_Shape& S,
166 const Handle(Transfer_TransientProcess)& TP,
167 const Standard_Real Prec,
168 const Standard_Real MaxTol) const
169{
170 if ( S.IsNull() ) return S;
171
172 TopoDS_Shape shape = S;
173 // fixing shape
174 try {
175 OCC_CATCH_SIGNALS
176 Handle(ShapeFix_Shape) sfs = ShapeAlgo::AlgoContainer()->ToolContainer()->FixShape();
177 sfs->Init ( S );
178 sfs->SetMsgRegistrator ( new ShapeExtend_MsgRegistrator );
179 sfs->SetPrecision ( Prec );
180 sfs->SetMaxTolerance ( MaxTol );
181 sfs->FixFaceTool()->FixWireTool()->FixSameParameterMode() = Standard_False;
182 sfs->Perform();
183
184 shape = sfs->Shape();
185
186 // to be removed when messages come
187 if ( shape == S || shape.IsNull() ) return S;
188
189 // update map to reflect the substitutions
190 Handle(ShapeBuild_ReShape) context = sfs->Context();
191 const ShapeExtend_DataMapOfShapeListOfMsg& msgmap =
192 Handle(ShapeExtend_MsgRegistrator)::DownCast (sfs->MsgRegistrator())->MapShape();
193 for ( Standard_Integer i=1; i <= TP->NbMapped(); i++ ) {
194 Handle(Transfer_Binder) bnd = TP->MapItem ( i );
195 Handle(TransferBRep_ShapeBinder) sb = Handle(TransferBRep_ShapeBinder)::DownCast ( bnd );
196 if ( sb.IsNull() || sb->Result().IsNull() ) continue;
197
198 TopoDS_Shape orig = sb->Result();
199
200 // update messages (messages must be taken from each level in the substitution map)
201 TopoDS_Shape cur, next = orig;
202 do {
203 cur = next;
204 Message_ListOfMsg msglist;
205 if (msgmap.IsBound (cur)) {
206 msglist = msgmap.Find (cur);
207 for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
208 const Message_Msg& msg = iter.Value();
209 sb->AddWarning (msg.Value(), msg.Original());
210 }
211 }
212 next = context->Value (cur);
213 } while (cur != next);
214
215 // update shapes
216 TopoDS_Shape res;
217 if ( ! context->Status ( orig, res, Standard_True ) ) continue;
218
219 sb->SetResult ( res );
220 }
221 }
222 catch (Standard_Failure) {
223#ifdef DEB
224 cout << "Error: XSAlgo_AlgoContainer::PerformFixShape(): Exception in ShapeFix::Shape" << endl;
225#endif
226 }
227 return shape;
228}
229*/
230
231// ============================================================================
232// Method : MakeEdgeOnCurve
233// Purpose : for CheckPCurve
234// ============================================================================
235
236static TopoDS_Edge MakeEdgeOnCurve(const TopoDS_Edge edge)
237{
238 TopoDS_Edge result;
239 //BRep_Builder B; // B not used - see below (skl)
240 Handle(Geom_Curve) C3d;
241 ShapeAnalysis_Edge sae;
242 Standard_Real cf, cl;
243 if (!sae.Curve3d (edge, C3d, cf, cl, Standard_False ))
244 return result;
245 gp_Pnt PV1 = C3d->Value(cf);
246 gp_Pnt PV2 = C3d->Value(cl);
247 BRepBuilderAPI_MakeEdge mkEdge(C3d, PV1, PV2, cf, cl);
248//:S4136 Standard_Real tol = BRep_Tool::Tolerance (edge);
249 ShapeBuild_Edge SBE; //skl 10.07.2001
250 SBE.SetRange3d(mkEdge,cf,cl); //skl 10.07.2001
251 result = mkEdge.Edge();
252//:S4136 B.UpdateEdge(result,tol);
253 return result;
254}
255
256//=======================================================================
257//function : CheckPCurve
258//purpose :
259//=======================================================================
260
261Standard_Boolean XSAlgo_AlgoContainer::CheckPCurve (const TopoDS_Edge& E,
262 const TopoDS_Face& face,
263 const Standard_Real preci,
264 const Standard_Boolean isSeam) const
265{
266 Standard_Real w1, w2;
267 Handle(Geom2d_Curve) thePC;
268 ShapeAnalysis_Edge sae;
269 if ( ! sae.PCurve (E, face, thePC, w1, w2, Standard_False ) ) {
270 return Standard_False;
271 }
272
273 // Check for pcurve longer than surface
274 Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
275 Standard_Real UF,UL,VF,VL;
276 surf->Bounds (UF,UL,VF,VL);
277 gp_Pnt2d PUV1, PUV2;
278 PUV1 = thePC->Value(w1);
279 PUV2 = thePC->Value(w2);
280 // Multi-periodique ? mieux vaut jeter (attention aux valeurs infinies)
281 Standard_Real DU = Abs (PUV1.X() - PUV2.X());
282 Standard_Real DV = Abs (PUV1.Y() - PUV2.Y());
283 if ( DU/8. > (UL/6. - UF/6.) || DV/8. > (VL/6. - VF/6.) ) {
284 ShapeBuild_Edge().RemovePCurve(E,face);
285#ifdef DEBUG
286 cout<<"Removing pcuve periodic"<<endl;
287#endif
288 return Standard_False;
289 }
290
291 // Second Check : 2D and 3D consistency (if the Pcurve has not been
292 // dropped)
293 // On verifie aussi qu on ne s enroule pas trop ...
294 // ex. : UVV en DEGRES sur une surface en RADIANS, recalee = 57 tours !
295
296 Handle(Geom_Curve) C3d;
297 Standard_Real cf1, cl1;
298 sae.Curve3d (E, C3d, cf1, cl1, Standard_False );
299
300 gp_Pnt P1 = surf->Value(PUV1.X(), PUV1.Y());
301 gp_Pnt P2 = surf->Value(PUV2.X(), PUV2.Y());
302 TopoDS_Vertex V1 = TopExp::FirstVertex(E);
303 TopoDS_Vertex V2 = TopExp::LastVertex(E);
304 gp_Pnt PV1 = ( C3d.IsNull() ? BRep_Tool::Pnt(V1) : C3d->Value(cf1) );
305 gp_Pnt PV2 = ( C3d.IsNull() ? BRep_Tool::Pnt(V2) : C3d->Value(cl1) );
306 Standard_Real Dist11 = PV1.Distance(P1), Dist22 = PV2.Distance(P2);
307
308 if (!((Dist11 <= preci) && (Dist22 <= preci))) {
309 ShapeBuild_Edge().RemovePCurve(E,face);
310#ifdef DEBUG
311 cout<<"Removing pcurve points"<<endl;
312#endif
313 return Standard_False;
314 }
315
316 //
317 // pdn checking deviation between pcurve and 3D curve
318 //
319
320 // Make temporary edge for analysis
321 if ( C3d.IsNull() ) return Standard_False;
322 TopoDS_Edge edge = MakeEdgeOnCurve(E);
323
324 // fill it with pcurve(s)
325 BRep_Builder B;
326 Handle(Geom2d_Curve) seamPC;
327 if ( isSeam ) {
328 Standard_Real f, l;
329 TopoDS_Shape REdge = E.Reversed() ;
330 if ( ! sae.PCurve ( TopoDS::Edge ( REdge ),
331 face, seamPC, f, l, Standard_False ) ||
332 seamPC == thePC )
333 seamPC = Handle(Geom2d_Curve)::DownCast ( thePC->Copy() );
334 B.UpdateEdge ( edge, thePC, seamPC, face, 0.);
335 }
336 else B.UpdateEdge ( edge, thePC, face, 0.);
337 B.Range(edge,face,w1,w2);
338 B.SameRange(edge, Standard_False );
339 //:S4136
340 Standard_Integer SPmode = Interface_Static::IVal("read.stdsameparameter.mode");
341 if ( SPmode )
342 B.SameParameter (edge, Standard_False );
343
344 // call FixSP to see what it will do
345 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
346 sfe->FixSameParameter(edge);
347 Standard_Real tol = BRep_Tool::Tolerance (edge);
348 // Standard_Real tolV1 = BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
349 // Standard_Real tolV2 = BRep_Tool::Tolerance(TopExp::LastVertex(edge));
350 Standard_Boolean sr = BRep_Tool::SameRange ( edge );
351 Standard_Boolean sp = BRep_Tool::SameParameter ( edge );
352
353 // if result is not nice, try to call projection and take the best
354 if ( tol > Min ( 1., 2.*preci ) || ! sr ) {
355 //pdn trying to recompute pcurve
356 TopoDS_Edge edgePr = MakeEdgeOnCurve(E);
357 sfe->FixAddPCurve(edgePr, face, isSeam, preci);
358 sfe->FixSameParameter(edgePr);
359 Standard_Real tolPr = BRep_Tool::Tolerance (edgePr);
360 //pdn choose the best pcurve
361 if ( tolPr < tol || ! sr ) {
362 // tolV1 = BRep_Tool::Tolerance(TopExp::FirstVertex(edgePr));
363 // tolV2 = BRep_Tool::Tolerance(TopExp::LastVertex(edgePr));
364 sr = BRep_Tool::SameRange ( edgePr );
365 sp = BRep_Tool::SameParameter ( edgePr );
366 tol = tolPr;
367 edge = edgePr;
368 }
369 }
370
371 // get corrected pcurve from the temporary edge, and put to original
372 sae.PCurve ( edge, face, thePC, w1, w2, Standard_False );
373 if ( isSeam ) {
374 Standard_Real f, l;
375 TopoDS_Shape REdge = edge.Reversed();
376 sae.PCurve ( TopoDS::Edge ( REdge ), face, seamPC, f, l, Standard_False );
377 if ( E.Orientation() == TopAbs_REVERSED ) //:abv 14.11.01: coneEl.sat loop
378 B.UpdateEdge ( E, seamPC, thePC, face, tol );
379 else
380 B.UpdateEdge ( E, thePC, seamPC, face, tol );
381 }
382 else B.UpdateEdge ( E, thePC, face, tol );
383
384 B.UpdateVertex(V1,tol);
385 B.UpdateVertex(V2,tol);
386 B.Range(E,face, w1, w2);
387 if(BRep_Tool::SameRange(E))
388 B.SameRange( E, sr );
389 if(BRep_Tool::SameParameter(E))
390 B.SameParameter ( E, sp );
391
392 return Standard_True;
393}
394
395//=======================================================================
396//function : MergeTransferInfo
397//purpose :
398//=======================================================================
399
400void XSAlgo_AlgoContainer::MergeTransferInfo(const Handle(Transfer_TransientProcess)& TP,
401 const Handle(Standard_Transient) &info,
402 const Standard_Integer startTPitem) const
403{
404 Handle(ShapeProcess_ShapeContext) context = Handle(ShapeProcess_ShapeContext)::DownCast ( info );
405 if ( context.IsNull() ) return;
406
407 const TopTools_DataMapOfShapeShape &map = context->Map();
408 Handle(ShapeExtend_MsgRegistrator) msg = context->Messages();
409 if ( map.Extent() <=0 && ( msg.IsNull() || msg->MapShape().Extent() <=0 ) )
410 return;
411
412 Standard_Integer i = ( startTPitem >0 ? startTPitem : 1 );
413 for ( ; i <= TP->NbMapped(); i++ ) {
414 Handle(Transfer_Binder) bnd = TP->MapItem ( i );
415 Handle(TransferBRep_ShapeBinder) sb = Handle(TransferBRep_ShapeBinder)::DownCast ( bnd );
416 if ( sb.IsNull() || sb->Result().IsNull() ) continue;
417
418 TopoDS_Shape orig = sb->Result();
419 if ( map.IsBound ( orig ) ) sb->SetResult ( map.Find ( orig ) );
420 else if ( !orig.Location().IsIdentity() )
421 {
422 TopLoc_Location aNullLoc;
423 TopoDS_Shape atmpSh = orig.Located(aNullLoc);
424 if ( map.IsBound ( atmpSh ) ) sb->SetResult ( map.Find ( atmpSh ) );
425 }
426
427 // update messages
428 if ( ! msg.IsNull() ) {
429 const ShapeExtend_DataMapOfShapeListOfMsg& msgmap = msg->MapShape();
430 if ( msgmap.IsBound (orig) ) {
431 const Message_ListOfMsg &msglist = msgmap.Find (orig);
432 for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
433 const Message_Msg& mess = iter.Value();
434 sb->AddWarning (TCollection_AsciiString(mess.Value()).ToCString(),
435 TCollection_AsciiString(mess.Original()).ToCString());
436 }
437 }
438 }
439 }
440}
441
442//=======================================================================
443//function : MergeTransferInfo
444//purpose :
445//=======================================================================
446
447void XSAlgo_AlgoContainer::MergeTransferInfo(const Handle(Transfer_FinderProcess)& FP,
448 const Handle(Standard_Transient) &info) const
449{
450 Handle(ShapeProcess_ShapeContext) context = Handle(ShapeProcess_ShapeContext)::DownCast ( info );
451 if ( context.IsNull() ) return;
452
453 const TopTools_DataMapOfShapeShape &map = context->Map();
454 TopTools_DataMapIteratorOfDataMapOfShapeShape ShapeShapeIterator(map);
455 Handle(ShapeExtend_MsgRegistrator) msg = context->Messages();
456
457 for ( ; ShapeShapeIterator.More(); ShapeShapeIterator.Next() ) {
458
459 TopoDS_Shape orig = ShapeShapeIterator.Key(), res = ShapeShapeIterator.Value();
460 Handle(TransferBRep_ShapeMapper) resMapper = TransferBRep::ShapeMapper ( FP, res );
461 Handle(Transfer_Binder) resBinder = FP->Find ( resMapper );
462
463 if (resBinder.IsNull()) {
464 resBinder = new TransferBRep_ShapeBinder(res);
465 //if <orig> shape was splitted, put entities corresponding to new shapes
466 // into Transfer_TransientListBinder.
467 if ( orig.ShapeType() > res.ShapeType() ) {
468 TopoDS_Shape sub;
469 Handle(Transfer_TransientListBinder) TransientListBinder = new Transfer_TransientListBinder;
470 for (TopoDS_Iterator it(res); it.More(); it.Next()) {
471 Handle(Transfer_Finder) subMapper = TransferBRep::ShapeMapper ( FP, it.Value());
472 if (subMapper.IsNull()) continue;
473
474 Handle(Standard_Transient) tr = FP->FindTransient ( subMapper );
475 if (tr.IsNull()) continue;
476 TransientListBinder->AddResult(tr);
477 sub = it.Value();
478 }
479 if ( TransientListBinder->NbTransients() == 1 ) resBinder = new TransferBRep_ShapeBinder(sub);
480 else if ( TransientListBinder->NbTransients() > 1 ) {
481 resBinder->AddResult(TransientListBinder);
482// resBinder->SetNext(TransientListBinder, Standard_True);
483#ifdef DEB
484 cout<<"Info: TransientListBinder created for splitted shape"<<endl;
485 }
486 else {
487 cout<<"Warning: XSAlgo_AlgoContainer::MergeTransferInfo() "
488 <<"No results were found for splitted shape. "<<endl;
489 //<<"Transfer_FinderProcess->NbMapped() = "<<FP->NbMapped()<<endl;
490#endif
491 }
492 }
493 }
494
495 Handle(TransferBRep_ShapeMapper) origMapper= TransferBRep::ShapeMapper ( FP, orig);
496 Handle(Transfer_Binder) origBinder = FP->Find ( origMapper );
497 if ( origBinder.IsNull() ) {
498 FP->Bind(origMapper, resBinder);
499 }
500 else {
501 origBinder->AddResult ( resBinder );
502 }
503
504 // update messages
505 if ( ! msg.IsNull() ) {
506 const ShapeExtend_DataMapOfShapeListOfMsg& msgmap = msg->MapShape();
507 if ( msgmap.IsBound (orig) ) {
508 const Message_ListOfMsg &msglist = msgmap.Find (orig);
509 for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
510 const Message_Msg& mess = iter.Value();
511 resBinder->AddWarning (TCollection_AsciiString(mess.Value()).ToCString(),
512 TCollection_AsciiString(mess.Original()).ToCString());
513 }
514 }
515 }
516 }
517}