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