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