1 // Created on: 2000-01-19
2 // Created by: data exchange team
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
17 #include <BRep_Builder.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepBuilderAPI_MakeEdge.hxx>
20 #include <Geom2d_Curve.hxx>
21 #include <Geom_Curve.hxx>
22 #include <Geom_Surface.hxx>
24 #include <gp_Pnt2d.hxx>
25 #include <Interface_Static.hxx>
26 #include <Message_ListIteratorOfListOfMsg.hxx>
27 #include <Message_ListOfMsg.hxx>
28 #include <Message_Msg.hxx>
29 #include <Message_ProgressIndicator.hxx>
30 #include <Resource_Manager.hxx>
31 #include <ShapeAlgo.hxx>
32 #include <ShapeAlgo_AlgoContainer.hxx>
33 #include <ShapeAlgo_ToolContainer.hxx>
34 #include <ShapeAnalysis_Edge.hxx>
35 #include <ShapeBuild_Edge.hxx>
36 #include <ShapeBuild_ReShape.hxx>
37 #include <ShapeCustom.hxx>
38 #include <ShapeExtend_DataMapOfShapeListOfMsg.hxx>
39 #include <ShapeExtend_MsgRegistrator.hxx>
40 #include <ShapeFix_Edge.hxx>
41 #include <ShapeFix_Shape.hxx>
42 #include <ShapeProcess.hxx>
43 #include <ShapeProcess_ShapeContext.hxx>
44 #include <Standard_ErrorHandler.hxx>
45 #include <Standard_Failure.hxx>
46 #include <Standard_Transient.hxx>
47 #include <Standard_Type.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopoDS_Face.hxx>
52 #include <TopoDS_Iterator.hxx>
53 #include <TopoDS_Shape.hxx>
54 #include <TopoDS_Vertex.hxx>
55 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
56 #include <TopTools_DataMapOfShapeShape.hxx>
57 #include <Transfer_FinderProcess.hxx>
58 #include <Transfer_TransientListBinder.hxx>
59 #include <Transfer_TransientProcess.hxx>
60 #include <TransferBRep.hxx>
61 #include <TransferBRep_ShapeBinder.hxx>
62 #include <TransferBRep_ShapeMapper.hxx>
63 #include <UnitsMethods.hxx>
64 #include <XSAlgo_AlgoContainer.hxx>
65 #include <XSAlgo_ToolContainer.hxx>
66 #include <TopExp_Explorer.hxx>
68 //=======================================================================
69 //function : XSAlgo_AlgoContainer
71 //=======================================================================
72 XSAlgo_AlgoContainer::XSAlgo_AlgoContainer()
74 myTC = new XSAlgo_ToolContainer;
77 //=======================================================================
78 //function : PrepareForTransfer
80 //=======================================================================
82 void XSAlgo_AlgoContainer::PrepareForTransfer() const
84 UnitsMethods::SetCasCadeLengthUnit ( Interface_Static::IVal("xstep.cascade.unit") );
87 //=======================================================================
88 //function : ProcessShape
90 //=======================================================================
92 TopoDS_Shape XSAlgo_AlgoContainer::ProcessShape (const TopoDS_Shape& shape,
93 const Standard_Real Prec,
94 const Standard_Real maxTol,
95 const Standard_CString prscfile,
96 const Standard_CString pseq,
97 Handle(Standard_Transient)& info,
98 const Handle(Message_ProgressIndicator)& progress) const
100 if ( shape.IsNull() ) return shape;
102 Handle(ShapeProcess_ShapeContext) context = Handle(ShapeProcess_ShapeContext)::DownCast(info);
103 if ( context.IsNull() )
105 Standard_CString rscfile = Interface_Static::CVal(prscfile);
108 context = new ShapeProcess_ShapeContext(shape, rscfile);
109 context->SetDetalisation(TopAbs_EDGE);
110 if ( !progress.IsNull() )
111 context->SetProgress(progress);
115 Standard_CString seq = Interface_Static::CVal ( pseq );
116 if ( ! seq ) seq = pseq;
118 // if resource file is not loaded or does not define <seq>.exec.op,
120 Handle(Resource_Manager) rsc = context->ResourceManager();
121 TCollection_AsciiString str ( seq );
123 if ( ! rsc->Find ( str.ToCString() ) ) {
126 static Standard_Integer time = 0;
128 cout << "Warning: XSAlgo_AlgoContainer::ProcessShape(): Sequence " << str.ToCString() <<
129 " is not defined in " << prscfile << " resource; do default processing" << endl;
133 // if reading, do default ShapeFix
134 if ( ! strncmp ( pseq, "read.", 5 ) ) {
137 Handle(ShapeExtend_MsgRegistrator) msg = new ShapeExtend_MsgRegistrator;
138 Handle(ShapeFix_Shape) sfs = ShapeAlgo::AlgoContainer()->ToolContainer()->FixShape();
140 sfs->SetMsgRegistrator ( msg );
141 sfs->SetPrecision ( Prec );
142 sfs->SetMaxTolerance ( maxTol );
143 sfs->FixFaceTool()->FixWireTool()->FixSameParameterMode() = Standard_False;
144 sfs->FixSolidTool()->CreateOpenSolidMode() = Standard_False;
145 sfs->Perform(progress);
147 TopoDS_Shape S = sfs->Shape();
148 if ( ! S.IsNull() && S != shape ) {
149 context->RecordModification ( sfs->Context(), msg );
150 context->SetResult ( S );
153 catch (Standard_Failure) {
155 cout << "Error: XSAlgo_AlgoContainer::ProcessShape(): Exception in ShapeFix::Shape" << endl;
156 Standard_Failure::Caught()->Print(cout); cout << endl;
159 return context->Result();
161 // for writing, define default sequence of DirectFaces
162 else if ( ! strncmp ( pseq, "write.", 6 ) ) {
163 rsc->SetResource ( str.ToCString(), "DirectFaces" );
167 // Define runtime tolerances and do Shape Processing
168 rsc->SetResource ( "Runtime.Tolerance", Prec );
169 rsc->SetResource ( "Runtime.MaxTolerance", maxTol );
171 if ( !ShapeProcess::Perform(context, seq) )
172 return shape; // return original shape
174 return context->Result();
177 //=======================================================================
178 //function : PerformFixShape
180 //=======================================================================
183 TopoDS_Shape XSAlgo_AlgoContainer::PerformFixShape(const TopoDS_Shape& S,
184 const Handle(Transfer_TransientProcess)& TP,
185 const Standard_Real Prec,
186 const Standard_Real MaxTol) const
188 if ( S.IsNull() ) return S;
190 TopoDS_Shape shape = S;
194 Handle(ShapeFix_Shape) sfs = ShapeAlgo::AlgoContainer()->ToolContainer()->FixShape();
196 sfs->SetMsgRegistrator ( new ShapeExtend_MsgRegistrator );
197 sfs->SetPrecision ( Prec );
198 sfs->SetMaxTolerance ( MaxTol );
199 sfs->FixFaceTool()->FixWireTool()->FixSameParameterMode() = Standard_False;
202 shape = sfs->Shape();
204 // to be removed when messages come
205 if ( shape == S || shape.IsNull() ) return S;
207 // update map to reflect the substitutions
208 Handle(ShapeBuild_ReShape) context = sfs->Context();
209 const ShapeExtend_DataMapOfShapeListOfMsg& msgmap =
210 Handle(ShapeExtend_MsgRegistrator)::DownCast (sfs->MsgRegistrator())->MapShape();
211 for ( Standard_Integer i=1; i <= TP->NbMapped(); i++ ) {
212 Handle(Transfer_Binder) bnd = TP->MapItem ( i );
213 Handle(TransferBRep_ShapeBinder) sb = Handle(TransferBRep_ShapeBinder)::DownCast ( bnd );
214 if ( sb.IsNull() || sb->Result().IsNull() ) continue;
216 TopoDS_Shape orig = sb->Result();
218 // update messages (messages must be taken from each level in the substitution map)
219 TopoDS_Shape cur, next = orig;
222 Message_ListOfMsg msglist;
223 if (msgmap.IsBound (cur)) {
224 msglist = msgmap.Find (cur);
225 for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
226 const Message_Msg& msg = iter.Value();
227 sb->AddWarning (msg.Value(), msg.Original());
230 next = context->Value (cur);
231 } while (cur != next);
235 if ( ! context->Status ( orig, res, Standard_True ) ) continue;
237 sb->SetResult ( res );
240 catch (Standard_Failure) {
242 cout << "Error: XSAlgo_AlgoContainer::PerformFixShape(): Exception in ShapeFix::Shape" << endl;
249 // ============================================================================
250 // Method : MakeEdgeOnCurve
251 // Purpose : for CheckPCurve
252 // ============================================================================
254 static TopoDS_Edge MakeEdgeOnCurve(const TopoDS_Edge edge)
257 //BRep_Builder B; // B not used - see below (skl)
258 Handle(Geom_Curve) C3d;
259 ShapeAnalysis_Edge sae;
260 Standard_Real cf, cl;
261 if (!sae.Curve3d (edge, C3d, cf, cl, Standard_False ))
263 gp_Pnt PV1 = C3d->Value(cf);
264 gp_Pnt PV2 = C3d->Value(cl);
265 BRepBuilderAPI_MakeEdge mkEdge(C3d, PV1, PV2, cf, cl);
266 //:S4136 Standard_Real tol = BRep_Tool::Tolerance (edge);
267 ShapeBuild_Edge SBE; //skl 10.07.2001
268 SBE.SetRange3d(mkEdge,cf,cl); //skl 10.07.2001
269 result = mkEdge.Edge();
270 //:S4136 B.UpdateEdge(result,tol);
274 //=======================================================================
275 //function : CheckPCurve
277 //=======================================================================
279 Standard_Boolean XSAlgo_AlgoContainer::CheckPCurve (const TopoDS_Edge& E,
280 const TopoDS_Face& face,
281 const Standard_Real preci,
282 const Standard_Boolean isSeam) const
284 Standard_Real w1, w2;
285 Handle(Geom2d_Curve) thePC;
286 ShapeAnalysis_Edge sae;
287 if ( ! sae.PCurve (E, face, thePC, w1, w2, Standard_False ) ) {
288 return Standard_False;
291 // Check for pcurve longer than surface
292 Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
293 Standard_Real UF,UL,VF,VL;
294 surf->Bounds (UF,UL,VF,VL);
296 PUV1 = thePC->Value(w1);
297 PUV2 = thePC->Value(w2);
298 // Multi-periodique ? mieux vaut jeter (attention aux valeurs infinies)
299 Standard_Real DU = Abs (PUV1.X() - PUV2.X());
300 Standard_Real DV = Abs (PUV1.Y() - PUV2.Y());
301 if ( DU/8. > (UL/6. - UF/6.) || DV/8. > (VL/6. - VF/6.) ) {
302 ShapeBuild_Edge().RemovePCurve(E,face);
304 cout<<"Removing pcuve periodic"<<endl;
306 return Standard_False;
309 // Second Check : 2D and 3D consistency (if the Pcurve has not been
311 // On verifie aussi qu on ne s enroule pas trop ...
312 // ex. : UVV en DEGRES sur une surface en RADIANS, recalee = 57 tours !
314 Handle(Geom_Curve) C3d;
315 Standard_Real cf1, cl1;
316 sae.Curve3d (E, C3d, cf1, cl1, Standard_False );
318 gp_Pnt P1 = surf->Value(PUV1.X(), PUV1.Y());
319 gp_Pnt P2 = surf->Value(PUV2.X(), PUV2.Y());
320 TopoDS_Vertex V1 = TopExp::FirstVertex(E);
321 TopoDS_Vertex V2 = TopExp::LastVertex(E);
322 gp_Pnt PV1 = ( C3d.IsNull() ? BRep_Tool::Pnt(V1) : C3d->Value(cf1) );
323 gp_Pnt PV2 = ( C3d.IsNull() ? BRep_Tool::Pnt(V2) : C3d->Value(cl1) );
324 Standard_Real Dist11 = PV1.Distance(P1), Dist22 = PV2.Distance(P2);
326 if (!((Dist11 <= preci) && (Dist22 <= preci))) {
327 ShapeBuild_Edge().RemovePCurve(E,face);
329 cout<<"Removing pcurve points"<<endl;
331 return Standard_False;
335 // pdn checking deviation between pcurve and 3D curve
338 // Make temporary edge for analysis
339 if ( C3d.IsNull() ) return Standard_False;
340 TopoDS_Edge edge = MakeEdgeOnCurve(E);
342 // fill it with pcurve(s)
344 Handle(Geom2d_Curve) seamPC;
347 TopoDS_Shape REdge = E.Reversed() ;
348 if ( ! sae.PCurve ( TopoDS::Edge ( REdge ),
349 face, seamPC, f, l, Standard_False ) ||
351 seamPC = Handle(Geom2d_Curve)::DownCast ( thePC->Copy() );
352 B.UpdateEdge ( edge, thePC, seamPC, face, 0.);
354 else B.UpdateEdge ( edge, thePC, face, 0.);
355 B.Range(edge,face,w1,w2);
356 B.SameRange(edge, Standard_False );
358 Standard_Integer SPmode = Interface_Static::IVal("read.stdsameparameter.mode");
360 B.SameParameter (edge, Standard_False );
362 // call FixSP to see what it will do
363 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
364 sfe->FixSameParameter(edge);
365 Standard_Real tol = BRep_Tool::Tolerance (edge);
366 // Standard_Real tolV1 = BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
367 // Standard_Real tolV2 = BRep_Tool::Tolerance(TopExp::LastVertex(edge));
368 Standard_Boolean sr = BRep_Tool::SameRange ( edge );
369 Standard_Boolean sp = BRep_Tool::SameParameter ( edge );
371 // if result is not nice, try to call projection and take the best
372 if ( tol > Min ( 1., 2.*preci ) || ! sr ) {
373 //pdn trying to recompute pcurve
374 TopoDS_Edge edgePr = MakeEdgeOnCurve(E);
375 sfe->FixAddPCurve(edgePr, face, isSeam, preci);
376 sfe->FixSameParameter(edgePr);
377 Standard_Real tolPr = BRep_Tool::Tolerance (edgePr);
378 //pdn choose the best pcurve
379 if ( tolPr < tol || ! sr ) {
380 // tolV1 = BRep_Tool::Tolerance(TopExp::FirstVertex(edgePr));
381 // tolV2 = BRep_Tool::Tolerance(TopExp::LastVertex(edgePr));
382 sr = BRep_Tool::SameRange ( edgePr );
383 sp = BRep_Tool::SameParameter ( edgePr );
389 // get corrected pcurve from the temporary edge, and put to original
390 sae.PCurve ( edge, face, thePC, w1, w2, Standard_False );
393 TopoDS_Shape REdge = edge.Reversed();
394 sae.PCurve ( TopoDS::Edge ( REdge ), face, seamPC, f, l, Standard_False );
395 if ( E.Orientation() == TopAbs_REVERSED ) //:abv 14.11.01: coneEl.sat loop
396 B.UpdateEdge ( E, seamPC, thePC, face, tol );
398 B.UpdateEdge ( E, thePC, seamPC, face, tol );
400 else B.UpdateEdge ( E, thePC, face, tol );
402 B.UpdateVertex(V1,tol);
403 B.UpdateVertex(V2,tol);
404 B.Range(E,face, w1, w2);
405 if(BRep_Tool::SameRange(E))
406 B.SameRange( E, sr );
407 if(BRep_Tool::SameParameter(E))
408 B.SameParameter ( E, sp );
410 return Standard_True;
413 //=======================================================================
414 //function : MergeTransferInfo
416 //=======================================================================
418 void XSAlgo_AlgoContainer::MergeTransferInfo(const Handle(Transfer_TransientProcess)& TP,
419 const Handle(Standard_Transient) &info,
420 const Standard_Integer startTPitem) const
422 Handle(ShapeProcess_ShapeContext) context = Handle(ShapeProcess_ShapeContext)::DownCast ( info );
423 if ( context.IsNull() ) return;
425 const TopTools_DataMapOfShapeShape &map = context->Map();
426 Handle(ShapeExtend_MsgRegistrator) msg = context->Messages();
427 if ( map.Extent() <=0 && ( msg.IsNull() || msg->MapShape().Extent() <=0 ) )
430 Standard_Integer i = ( startTPitem >0 ? startTPitem : 1 );
431 for ( ; i <= TP->NbMapped(); i++ )
433 Handle(Transfer_Binder) bnd = TP->MapItem ( i );
434 Handle(TransferBRep_ShapeBinder) sb = Handle(TransferBRep_ShapeBinder)::DownCast ( bnd );
435 if ( sb.IsNull() || sb->Result().IsNull() ) continue;
437 TopoDS_Shape orig = sb->Result();
439 if ( map.IsBound ( orig ) )
441 sb->SetResult ( map.Find ( orig ) );
443 else if ( !orig.Location().IsIdentity() )
445 TopLoc_Location aNullLoc;
446 TopoDS_Shape atmpSh = orig.Located(aNullLoc);
447 if ( map.IsBound ( atmpSh ) ) sb->SetResult ( map.Find ( atmpSh ) );
451 // Some of edges may be modified.
452 BRepTools_ReShape aReShape;
453 Standard_Boolean hasModifiedEdges = Standard_False;
454 TopExp_Explorer anExpSE(orig, TopAbs_EDGE);
456 // Remember modifications.
457 for( ; anExpSE.More() ; anExpSE.Next() )
459 if ( map.IsBound ( anExpSE.Current() ) )
461 hasModifiedEdges = Standard_True;
462 TopoDS_Shape aModifiedShape = map.Find( anExpSE.Current() );
463 aReShape.Replace(anExpSE.Current(), aModifiedShape);
467 // Apply modifications and store result in binder.
468 if (hasModifiedEdges)
470 TopoDS_Shape aRes = aReShape.Apply(orig);
471 sb->SetResult ( aRes );
477 if ( ! msg.IsNull() ) {
478 const ShapeExtend_DataMapOfShapeListOfMsg& msgmap = msg->MapShape();
479 if ( msgmap.IsBound (orig) ) {
480 const Message_ListOfMsg &msglist = msgmap.Find (orig);
481 for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
482 const Message_Msg& mess = iter.Value();
483 sb->AddWarning (TCollection_AsciiString(mess.Value()).ToCString(),
484 TCollection_AsciiString(mess.Original()).ToCString());
491 //=======================================================================
492 //function : MergeTransferInfo
494 //=======================================================================
496 void XSAlgo_AlgoContainer::MergeTransferInfo(const Handle(Transfer_FinderProcess)& FP,
497 const Handle(Standard_Transient) &info) const
499 Handle(ShapeProcess_ShapeContext) context = Handle(ShapeProcess_ShapeContext)::DownCast ( info );
500 if ( context.IsNull() ) return;
502 const TopTools_DataMapOfShapeShape &map = context->Map();
503 TopTools_DataMapIteratorOfDataMapOfShapeShape ShapeShapeIterator(map);
504 Handle(ShapeExtend_MsgRegistrator) msg = context->Messages();
506 for ( ; ShapeShapeIterator.More(); ShapeShapeIterator.Next() ) {
508 TopoDS_Shape orig = ShapeShapeIterator.Key(), res = ShapeShapeIterator.Value();
509 Handle(TransferBRep_ShapeMapper) resMapper = TransferBRep::ShapeMapper ( FP, res );
510 Handle(Transfer_Binder) resBinder = FP->Find ( resMapper );
512 if (resBinder.IsNull()) {
513 resBinder = new TransferBRep_ShapeBinder(res);
514 //if <orig> shape was splitted, put entities corresponding to new shapes
515 // into Transfer_TransientListBinder.
516 if ( orig.ShapeType() > res.ShapeType() ) {
518 Handle(Transfer_TransientListBinder) TransientListBinder = new Transfer_TransientListBinder;
519 for (TopoDS_Iterator it(res); it.More(); it.Next()) {
520 Handle(Transfer_Finder) subMapper = TransferBRep::ShapeMapper ( FP, it.Value());
521 if (subMapper.IsNull()) continue;
523 Handle(Standard_Transient) tr = FP->FindTransient ( subMapper );
524 if (tr.IsNull()) continue;
525 TransientListBinder->AddResult(tr);
528 if ( TransientListBinder->NbTransients() == 1 ) resBinder = new TransferBRep_ShapeBinder(sub);
529 else if ( TransientListBinder->NbTransients() > 1 ) {
530 resBinder->AddResult(TransientListBinder);
531 // resBinder->SetNext(TransientListBinder, Standard_True);
533 cout<<"Info: TransientListBinder created for splitted shape"<<endl;
536 cout<<"Warning: XSAlgo_AlgoContainer::MergeTransferInfo() "
537 <<"No results were found for splitted shape. "<<endl;
538 //<<"Transfer_FinderProcess->NbMapped() = "<<FP->NbMapped()<<endl;
544 Handle(TransferBRep_ShapeMapper) origMapper= TransferBRep::ShapeMapper ( FP, orig);
545 Handle(Transfer_Binder) origBinder = FP->Find ( origMapper );
546 if ( origBinder.IsNull() ) {
547 FP->Bind(origMapper, resBinder);
550 origBinder->AddResult ( resBinder );
554 if ( ! msg.IsNull() ) {
555 const ShapeExtend_DataMapOfShapeListOfMsg& msgmap = msg->MapShape();
556 if ( msgmap.IsBound (orig) ) {
557 const Message_ListOfMsg &msglist = msgmap.Find (orig);
558 for (Message_ListIteratorOfListOfMsg iter (msglist); iter.More(); iter.Next()) {
559 const Message_Msg& mess = iter.Value();
560 resBinder->AddWarning (TCollection_AsciiString(mess.Value()).ToCString(),
561 TCollection_AsciiString(mess.Original()).ToCString());