1 // Created on: 1997-10-14
2 // Created by: Olga KOULECHOVA
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAlgo.hxx>
21 #include <BRepAlgoAPI_Common.hxx>
22 #include <BRepAlgoAPI_Cut.hxx>
23 #include <BRepAlgoAPI_Section.hxx>
24 #include <BRepBuilderAPI_MakeFace.hxx>
25 #include <BRepBuilderAPI_Transform.hxx>
26 #include <BRepExtrema_ExtCF.hxx>
27 #include <BRepExtrema_ExtPC.hxx>
28 #include <BRepFeat.hxx>
29 #include <BRepFeat_MakeRevolutionForm.hxx>
30 #include <BRepLib_MakeEdge.hxx>
31 #include <BRepLib_MakeFace.hxx>
32 #include <BRepLib_MakeVertex.hxx>
33 #include <BRepPrimAPI_MakeBox.hxx>
34 #include <BRepTools.hxx>
35 #include <BRepTools_Modifier.hxx>
36 #include <BRepTools_TrsfModification.hxx>
37 #include <BRepTools_WireExplorer.hxx>
38 #include <BRepTopAdaptor_FClass2d.hxx>
39 #include <CSLib.hxx>
40 #include <ElCLib.hxx>
41 #include <ElSLib.hxx>
42 #include <Geom2d_Curve.hxx>
43 #include <Geom2d_Line.hxx>
44 #include <Geom2dAPI_ExtremaCurveCurve.hxx>
45 #include <Geom2dAPI_InterCurveCurve.hxx>
46 #include <Geom_Circle.hxx>
47 #include <Geom_ConicalSurface.hxx>
48 #include <Geom_Curve.hxx>
49 #include <Geom_CylindricalSurface.hxx>
50 #include <Geom_Line.hxx>
51 #include <Geom_Plane.hxx>
52 #include <Geom_RectangularTrimmedSurface.hxx>
53 #include <Geom_Surface.hxx>
54 #include <Geom_ToroidalSurface.hxx>
55 #include <Geom_TrimmedCurve.hxx>
56 #include <GeomAPI.hxx>
57 #include <GeomAPI_ProjectPointOnCurve.hxx>
58 #include <GeomLProp_CLProps.hxx>
59 #include <GeomProjLib.hxx>
60 #include <gp_Ax1.hxx>
61 #include <gp_Lin.hxx>
62 #include <gp_Pln.hxx>
63 #include <gp_Pnt.hxx>
64 #include <gp_Pnt2d.hxx>
65 #include <gp_Vec.hxx>
66 #include <gp_Vec2d.hxx>
67 #include <IntRes2d_IntersectionPoint.hxx>
68 #include <LocOpe.hxx>
69 #include <LocOpe_CSIntersector.hxx>
70 #include <LocOpe_FindEdges.hxx>
71 #include <LocOpe_Gluer.hxx>
72 #include <LocOpe_PntFace.hxx>
73 #include <LocOpe_RevolutionForm.hxx>
74 #include <Precision.hxx>
75 #include <Standard_ConstructionError.hxx>
76 #include <TColGeom_Array1OfCurve.hxx>
77 #include <TColGeom_SequenceOfCurve.hxx>
78 #include <TColgp_Array1OfPnt.hxx>
79 #include <TColgp_SequenceOfPnt.hxx>
80 #include <TColStd_Array1OfReal.hxx>
81 #include <TopExp.hxx>
82 #include <TopExp_Explorer.hxx>
83 #include <TopoDS.hxx>
84 #include <TopoDS_Edge.hxx>
85 #include <TopoDS_Face.hxx>
86 #include <TopoDS_Shape.hxx>
87 #include <TopoDS_Wire.hxx>
88 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
89 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
90 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
91 #include <TopTools_ListIteratorOfListOfShape.hxx>
92 #include <TopTools_ListOfShape.hxx>
93 #include <TopTools_MapIteratorOfMapOfShape.hxx>
94 #include <TopTools_MapOfShape.hxx>
95
96 #ifdef OCCT_DEBUG
97 extern Standard_Boolean BRepFeat_GettraceFEAT();
98 extern Standard_Boolean BRepFeat_GettraceFEATRIB();
99 #endif
100
101 static void MajMap(const TopoDS_Shape&, // base
102 const LocOpe_RevolutionForm&,
103 TopTools_DataMapOfShapeListOfShape&, // myMap
104 TopoDS_Shape&, // myFShape
105 TopoDS_Shape&); // myLShape
106
107 static void SetGluedFaces(const TopTools_DataMapOfShapeListOfShape& theSlmap,
108 LocOpe_RevolutionForm&,
109 const TopTools_DataMapOfShapeListOfShape& SlidingMap,
110 TopTools_DataMapOfShapeShape&);
111
112 //=======================================================================
113 //function : Init
114 //purpose :
115 //=======================================================================
116
Init(const TopoDS_Shape & Sbase,const TopoDS_Wire & W,const Handle (Geom_Plane)& Plane,const gp_Ax1 & Axis,const Standard_Real H1,const Standard_Real H2,const Standard_Integer Mode,Standard_Boolean & Modify)117 void BRepFeat_MakeRevolutionForm::Init(const TopoDS_Shape& Sbase,
118 const TopoDS_Wire& W,
119 const Handle(Geom_Plane)& Plane,
120 const gp_Ax1& Axis,
121 const Standard_Real H1,
122 const Standard_Real H2,
123 const Standard_Integer Mode,
124 Standard_Boolean& Modify)
125 {
126 #ifdef OCCT_DEBUG
127 Standard_Boolean trc = BRepFeat_GettraceFEAT();
128 if (trc) std::cout << "BRepFeat_MakeRevolutionForm::Init" << std::endl;
129 #endif
130 Standard_Boolean RevolRib = Standard_True;
131 Done();
132
133 // modify = 0 if it is not required to make sliding
134 // = 1 if it is intended to try to make sliding
135 Standard_Boolean Sliding = Modify;
136
137 myAxe = Axis;
138 Handle(Geom_Line) Line = new Geom_Line(Axis);
139 Standard_Real LineFirst, LineLast;
140
141 LocOpe_CSIntersector ASI(Sbase);
142 TColGeom_SequenceOfCurve scur;
143 scur.Clear();
144 scur.Append(Line);
145 ASI.Perform(scur);
146 if(ASI.IsDone() && ASI.NbPoints(1) >= 2) {
147 LineLast = ASI.Point(1, ASI.NbPoints(1)).Parameter();
148 LineFirst = ASI.Point(1, 1).Parameter();
149 }
150 else {
151 LineFirst = RealFirst();
152 LineLast = RealLast();
153 }
154
155 Handle(Geom2d_Curve) ln2d = GeomAPI::To2d(Line, Plane->Pln());
156
157 TopExp_Explorer exx;
158 Standard_Real Rad = RealLast();
159
160 exx.Init(W, TopAbs_EDGE);
161 for(; exx.More(); exx.Next()) {
162 const TopoDS_Edge& e = TopoDS::Edge(exx.Current());
163 Standard_Real f, l;
164 Handle(Geom_Curve) c = BRep_Tool::Curve(e, f, l);
165 Handle(Geom2d_Curve) c2d = GeomAPI::To2d(c, Plane->Pln());
166 Geom2dAPI_ExtremaCurveCurve extr(ln2d, c2d, LineFirst, LineLast,f,l);
167 Standard_Real L = RealLast();
168 if(extr.NbExtrema() >= 1) {
169 L = extr.LowerDistance();
170 }
171 gp_Pnt p1 = c->Value(f);
172 gp_Pnt p2 = c->Value(l);
173 GeomAPI_ProjectPointOnCurve proj1(p1, Line);
174 GeomAPI_ProjectPointOnCurve proj2(p2, Line);
175 if(proj1.NbPoints() < 1 || proj2.NbPoints() < 1) {
176 #ifdef OCCT_DEBUG
177 if (trc) std::cout << " No projection points" << std::endl;
178 #endif
179 myStatusError = BRepFeat_NoProjPt;
180 NotDone();
181 return;
182 }
183 Standard_Real par1 = proj1.Distance(1);
184 Standard_Real par2 = proj2.Distance(1);
185 Standard_Real Par = Min(par1, par2);
186 if(Par<L) L = Par;
187 if(L<Rad && L > 0.) Rad = L;
188 }
189
190 Standard_Real height = Min(H1, H2);
191
192 if(Rad <= height) Rad = height + 0.01*height;
193
194 myAngle1 = asin(H1/Rad) + M_PI/10.;
195 myAngle2 = asin(H2/Rad) + M_PI/10.;
196
197 if((myAngle1 - M_PI/2) > Precision::Confusion())
198 myAngle1 = M_PI/2;
199 if((myAngle2 - M_PI/2) > Precision::Confusion())
200 myAngle2 = M_PI/2;
201
202 mySkface.Nullify();
203 myPbase.Nullify();
204
205 if(Mode == 0)
206 myFuse = Standard_False;
207 else // if(Mode == 1)
208 myFuse = Standard_True;
209 #ifdef OCCT_DEBUG
210 if (trc) {
211 if (myFuse) std::cout << " Fuse" << std::endl;
212 if (!myFuse) std::cout << " Cut" << std::endl;
213 }
214 #endif
215
216 // ---Determination Tolerance : tolerance max on parameters
217 myTol = Precision::Confusion();
218
219 exx.Init(W, TopAbs_VERTEX);
220 for(; exx.More(); exx.Next()) {
221 const Standard_Real& tol = BRep_Tool::
222 Tolerance(TopoDS::Vertex(exx.Current()));
223 if(tol > myTol) myTol = tol;
224 }
225
226 exx.Init(Sbase, TopAbs_VERTEX);
227 for(; exx.More(); exx.Next()) {
228 const Standard_Real& tol = BRep_Tool::
229 Tolerance(TopoDS::Vertex(exx.Current()));
230 if(tol > myTol) myTol = tol;
231 }
232
233 TopoDS_Shape aLocalShapeW = W.Oriented(TopAbs_FORWARD);
234 myWire = TopoDS::Wire(aLocalShapeW);
235 // myWire = TopoDS::Wire(W.Oriented(TopAbs_FORWARD));
236 myPln = Plane;
237 myHeight1 = H1;
238 myHeight2 = H2;
239
240 mySbase = Sbase;
241 mySlface.Clear();
242 myShape.Nullify();
243 myMap.Clear();
244 myFShape.Nullify();
245 myLShape.Nullify();
246
247 // ---Calculate bounding box
248 BRep_Builder BB;
249
250 TopTools_ListOfShape theList;
251
252 TopoDS_Shape U;
253 U.Nullify();
254 gp_Pnt FirstCorner, LastCorner;
255 Standard_Real bnd = HeightMax(mySbase, U, FirstCorner, LastCorner);
256 myBnd = bnd;
257
258 BRepPrimAPI_MakeBox Bndbox(FirstCorner, LastCorner);
259 TopoDS_Solid BndBox = Bndbox.Solid();
260
261
262 // ---Construction of the working plane face (section bounding box)
263 BRepLib_MakeFace PlaneF(myPln->Pln(), -6.*myBnd,
264 6.*myBnd, -6.*myBnd, 6.*myBnd);
265 TopoDS_Face PlaneFace = TopoDS::Face(PlaneF.Shape());
266
267 BRepAlgoAPI_Common PlaneS(BndBox, PlaneFace);
268 TopExp_Explorer EXP;
269 TopoDS_Shape PlaneSect = PlaneS.Shape();
270 EXP.Init(PlaneSect, TopAbs_WIRE);
271 TopoDS_Wire www = TopoDS::Wire(EXP.Current());
272 BRepLib_MakeFace Bndface(myPln->Pln(), www, Standard_True);
273 TopoDS_Face BndFace = TopoDS::Face(Bndface.Shape());
274
275
276 // ---Find base faces of the rib
277 TopoDS_Edge FirstEdge, LastEdge;
278 TopoDS_Face FirstFace, LastFace;
279 TopoDS_Vertex FirstVertex, LastVertex;
280
281 Standard_Boolean OnFirstFace = Standard_False;
282 Standard_Boolean OnLastFace = Standard_False;
283 Standard_Boolean PtOnFirstEdge = Standard_False;
284 Standard_Boolean PtOnLastEdge = Standard_False;
285 TopoDS_Edge OnFirstEdge, OnLastEdge;
286 OnFirstEdge.Nullify();
287 OnLastEdge.Nullify();
288
289 Standard_Boolean Data = ExtremeFaces(RevolRib, myBnd, myPln, FirstEdge, LastEdge,
290 FirstFace, LastFace, FirstVertex,
291 LastVertex, OnFirstFace, OnLastFace,
292 PtOnFirstEdge, PtOnLastEdge,
293 OnFirstEdge, OnLastEdge);
294
295 if(!Data) {
296 #ifdef OCCT_DEBUG
297 if (trc) std::cout << " No Extreme faces" << std::endl;
298 #endif
299 myStatusError = BRepFeat_NoExtFace;
300 NotDone();
301 return;
302 }
303
304
305 // ---Proofing Point for the side of the wire to be filled - material side
306 gp_Pnt CheckPnt = CheckPoint(FirstEdge, bnd/10., myPln);
307
308 // Standard_Real f, l;
309
310 // ---Control sliding valid
311 // Many cases when the sliding is abandoned
312 Standard_Integer Concavite = 3; // a priori the profile is not concave
313
314 myFirstPnt = BRep_Tool::Pnt(FirstVertex);
315 myLastPnt = BRep_Tool::Pnt(LastVertex);
316
317 // SliList : list of faces concerned by the rib
318 TopTools_ListOfShape SliList;
319 SliList.Append(FirstFace);
320
321 if(Sliding) { // sliding
322 #ifdef OCCT_DEBUG
323 if (trc) std::cout << " Sliding" << std::endl;
324 #endif
325 Handle(Geom_Surface) s = BRep_Tool::Surface(FirstFace);
326 if (s->DynamicType() ==
327 STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
328 s = Handle(Geom_RectangularTrimmedSurface)::
329 DownCast(s)->BasisSurface();
330 }
331 if(s->DynamicType() != STANDARD_TYPE(Geom_Plane) &&
332 s->DynamicType() != STANDARD_TYPE(Geom_CylindricalSurface) &&
333 s->DynamicType() != STANDARD_TYPE(Geom_ConicalSurface) &&
334 s->DynamicType() != STANDARD_TYPE(Geom_ToroidalSurface))
335 Sliding = Standard_False;
336 }
337
338 if(Sliding) { // sliding
339 Handle(Geom_Surface) ss = BRep_Tool::Surface(LastFace);
340 if (ss->DynamicType() ==
341 STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
342 ss = Handle(Geom_RectangularTrimmedSurface)::
343 DownCast(ss)->BasisSurface();
344 }
345 if(ss->DynamicType() != STANDARD_TYPE(Geom_Plane) &&
346 ss->DynamicType() != STANDARD_TYPE(Geom_CylindricalSurface) &&
347 ss->DynamicType() != STANDARD_TYPE(Geom_ConicalSurface) &&
348 ss->DynamicType() != STANDARD_TYPE(Geom_ToroidalSurface))
349 Sliding = Standard_False;
350 }
351
352 // Control only start and end points no control at the middle to improve
353 // If make a control between Surface and segment 2 points limited
354 // -> too expensive - to improve
355 //gp_Pnt FirstCenter, LastCenter;
356 gp_Circ FirstCircle, LastCircle;
357 Handle(Geom_Curve) FirstCrv, LastCrv;
358
359 if(Sliding) { // sliding
360 GeomAPI_ProjectPointOnCurve proj(myFirstPnt, Line);
361 if(proj.NbPoints() < 1) {
362 #ifdef OCCT_DEBUG
363 if (trc) std::cout << " No First Point projection" << std::endl;
364 #endif
365 myStatusError = BRepFeat_NoProjPt;
366 NotDone();
367 return;
368 }
369 Standard_Real FirstRayon = proj.Distance(1);
370 gp_Pnt FirstCenter = proj.Point(1);
371
372 GeomAPI_ProjectPointOnCurve proj1(myLastPnt, Line);
373 if(proj.NbPoints() < 1) {
374 #ifdef OCCT_DEBUG
375 if (trc) std::cout << " No Last Point projection" << std::endl;
376 #endif
377 myStatusError = BRepFeat_NoProjPt;
378 NotDone();
379 return;
380 }
381 Standard_Real LastRayon = proj1.Distance(1);
382 gp_Pnt LastCenter = proj1.Point(1);
383
384 gp_Vec axv(myAxe.Direction());
385 gp_Ax2 ax2(FirstCenter, axv);
386 gp_Ax2 ax2p(LastCenter, axv);
387 gp_Circ theFC(ax2, FirstRayon);
388 gp_Circ theLC(ax2p, LastRayon);
389
390 gp_Pnt RFirstPnt1 = myFirstPnt.Rotated(myAxe, myAngle1);
391 gp_Pnt RLastPnt1 = myLastPnt.Rotated(myAxe, myAngle1);
392 gp_Pnt RFirstPnt2 = myFirstPnt.Rotated(myAxe, -myAngle2);
393 gp_Pnt RLastPnt2 = myLastPnt.Rotated(myAxe, -myAngle2);
394
395 BRep_Builder Bu;
396 TopoDS_Vertex v1, v2, v3, v4;
397 Bu.MakeVertex(v1, RFirstPnt2, Precision::Confusion());
398 Bu.MakeVertex(v2, RFirstPnt1, Precision::Confusion());
399 Bu.MakeVertex(v3, RLastPnt2, Precision::Confusion());
400 Bu.MakeVertex(v4, RLastPnt1, Precision::Confusion());
401
402 BRepLib_MakeEdge ee1(theFC, v1, v2);
403 BRepLib_MakeEdge ee2(theLC, v3, v4);
404
405 if(Sliding && !PtOnFirstEdge) {
406 BRepExtrema_ExtCF ext1(TopoDS::Edge(ee1.Shape()), FirstFace);
407 if(ext1.NbExt() < 1 || ext1.SquareDistance(1) > Precision::SquareConfusion())
408 Sliding = Standard_False;
409 }
410 if(Sliding && !PtOnLastEdge) {
411 BRepExtrema_ExtCF ext2(ee2, LastFace); // ExtCF : curves and surfaces
412 if(ext2.NbExt() < 1 || ext2.SquareDistance(1) > Precision::SquareConfusion())
413 Sliding = Standard_False;
414 }
415 if(Sliding && PtOnFirstEdge) {
416 Standard_Real f, l;
417 FirstCrv = BRep_Tool::Curve(OnFirstEdge, f, l);
418 if(FirstCrv->DynamicType() != STANDARD_TYPE(Geom_Circle))
419 Sliding = Standard_False;
420 else {
421 Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(FirstCrv);
422 gp_Circ Circ = C1->Circ();
423 FirstCircle = Circ;
424 gp_Ax1 circax = FirstCircle.Axis();
425 if(!circax.IsCoaxial(myAxe, Precision::Confusion(),
426 Precision::Confusion()))
427 Sliding = Standard_False;
428 else {
429 //#ifndef OCCT_DEBUG
430 if(fabs(FirstCircle.Radius()-FirstRayon) >=
431 //#else
432 // if(abs(FirstCircle.Radius()-FirstRayon) >=
433 //#endif
434 Precision::Confusion())
435 Sliding = Standard_False;
436 }
437 }
438 }
439
440 if(Sliding && PtOnLastEdge) {
441 Standard_Real f, l;
442 LastCrv = BRep_Tool::Curve(OnLastEdge, f, l);
443 if(LastCrv->DynamicType() != STANDARD_TYPE(Geom_Circle))
444 Sliding = Standard_False;
445 else {
446 Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(LastCrv);
447 gp_Circ Circ = C1->Circ();
448 LastCircle = Circ;
449 gp_Ax1 circax = LastCircle.Axis();
450 if(!circax.IsCoaxial(myAxe, Precision::Confusion(),
451 Precision::Confusion()))
452 Sliding = Standard_False;
453 else {
454 Standard_Real rad = LastCircle.Radius();
455 //#ifndef OCCT_DEBUG
456 if(fabs(rad - LastRayon) >= Precision::Confusion()) {
457 //#else
458 // if(abs(rad - LastRayon) >= Precision::Confusion()) {
459 //#endif
460 Sliding = Standard_False;
461 }
462 }
463 }
464 }
465 }
466
467
468 // Construct a great profile that goes till the bounding box
469 // -> by tangency with first and last edge of the Wire
470 // -> by normals to base faces : statistically better
471 // Intersect everything to find the final profile
472
473
474 // ---case of sliding : construction of the face profile
475 if(Sliding) {
476 #ifdef OCCT_DEBUG
477 if (trc) std::cout << " still Sliding" << std::endl;
478 #endif
479 TopoDS_Face Prof;
480 Standard_Boolean ProfileOK;
481 ProfileOK = SlidingProfile(Prof,RevolRib,myTol,Concavite,myPln,BndFace,CheckPnt,
482 FirstFace,LastFace,FirstVertex,LastVertex,
483 FirstEdge,LastEdge);
484
485 if (!ProfileOK) {
486 #ifdef OCCT_DEBUG
487 if (trc)
488 {
489 std::cout << "Not computable" << std::endl;
490 std::cout << "Face profile not computable" << std::endl;
491 }
492 #endif
493 myStatusError = BRepFeat_NoFaceProf;
494 NotDone();
495 return;
496 }
497
498
499 // ---Propagation on faces of the initial shape
500 // to find the faces concerned by the rib
501 Standard_Boolean falseside = Standard_True;
502 Sliding = Propagate(SliList, Prof, myFirstPnt, myLastPnt, falseside);
503 // Control if there is everything required to have the material at the proper side
504 if(falseside == Standard_False) {
505 #ifdef OCCT_DEBUG
506 std::cout << " Verify plane and wire orientation" << std::endl;
507 #endif
508 myStatusError = BRepFeat_FalseSide;
509 NotDone();
510 return;
511 }
512 }
513
514
515 // ---Generation of the base profile of the rib
516
517 TopoDS_Wire w;
518 BB.MakeWire(w);
519 TopoDS_Edge thePreviousEdge;
520 TopoDS_Vertex theFV;
521 thePreviousEdge.Nullify();
522
523 // counter of the number of edges to fill the map
524 Standard_Integer counter = 1;
525
526 // ---case of sliding
527 if(Sliding && !myListOfEdges.IsEmpty()) {
528 BRepTools_WireExplorer EX1(myWire);
529 for(; EX1.More(); EX1.Next()) {
530 const TopoDS_Edge& E = EX1.Current();
531 if(!myLFMap.IsBound(E)) {
532 TopTools_ListOfShape theTmpList;
533 myLFMap.Bind(E, theTmpList);
534 }
535 if(E.IsSame(FirstEdge)) {
536 Standard_Real f, l;
537 Handle(Geom_Curve) cc = BRep_Tool::Curve(E, f, l);
538 gp_Pnt pt;
539 if(!FirstEdge.IsSame(LastEdge)) {
540 pt = BRep_Tool::Pnt(TopExp::LastVertex(E,Standard_True));
541 }
542 else {
543 pt = myLastPnt;
544 Standard_Real fpar = IntPar(cc, myFirstPnt);
545 Standard_Real lpar = IntPar(cc, pt);
546 if(fpar > lpar) {
547 cc = cc->Reversed();
548 }
549 }
550 TopoDS_Edge ee1;
551 if(thePreviousEdge.IsNull()) {
552 BRepLib_MakeVertex v1(myFirstPnt);
553 BRepLib_MakeVertex v2(pt);
554 BRepLib_MakeEdge e(cc, v1, v2);
555 ee1 = TopoDS::Edge(e.Shape());
556 }
557 else {
558 const TopoDS_Vertex& v1 = TopExp::LastVertex(thePreviousEdge,Standard_True);
559 BRepLib_MakeVertex v2(pt);
560
561 BRepLib_MakeEdge e(cc, v1, v2);
562 ee1 = TopoDS::Edge(e.Shape());
563 }
564 TopoDS_Shape aLocalShape = ee1.Oriented(E.Orientation());
565 ee1 = TopoDS::Edge(aLocalShape);
566 // ee1 = TopoDS::Edge(ee1.Oriented(E.Orientation()));
567 if(counter == 1) theFV = TopExp::FirstVertex(ee1,Standard_True);
568 myLFMap(E).Append(ee1);
569 BB.Add(w, ee1);
570 thePreviousEdge = ee1;
571 counter++;
572 EX1.Next();
573 break;
574 }
575 }
576
577 // Case of several edges
578 if(!FirstEdge.IsSame(LastEdge)) {
579 for(; EX1.More(); EX1.Next()) {
580 const TopoDS_Edge& E = EX1.Current();
581 if(!myLFMap.IsBound(E)) {
582 TopTools_ListOfShape thelist1;
583 myLFMap.Bind(E, thelist1);
584 }
585 theList.Append(E);
586 Standard_Real f, l;
587 if(!E.IsSame(LastEdge)) {
588 Handle(Geom_Curve) ccc = BRep_Tool::Curve(E, f, l);
589 TopoDS_Vertex v1, v2;
590 if(!thePreviousEdge.IsNull()) {
591 v1 = TopExp::LastVertex(thePreviousEdge,Standard_True);
592 v2 = TopExp::LastVertex(E,Standard_True);
593 }
594 else {
595 // v1 = TopExp::LastVertex(E,Standard_True);
596 v1 = TopExp::FirstVertex(E,Standard_True);
597 v2 = TopExp::LastVertex(E,Standard_True);
598 }
599 BRepLib_MakeEdge E1(ccc, v1, v2);
600 TopoDS_Edge E11 = TopoDS::Edge(E1.Shape());
601 TopoDS_Shape aLocalShape = E11.Oriented(E.Orientation());
602 E11 = TopoDS::Edge(aLocalShape);
603 // E11 = TopoDS::Edge(E11.Oriented(E.Orientation()));
604 thePreviousEdge = E11;
605 myLFMap(E).Append(E11);
606 BB.Add(w, E11);
607 if(counter == 1) theFV = TopExp::FirstVertex(E11,Standard_True);
608 counter++;
609 }
610 else {
611 Handle(Geom_Curve) cc = BRep_Tool::Curve(E, f, l);
612 gp_Pnt pf = BRep_Tool::Pnt(TopExp::FirstVertex(E,Standard_True));
613 gp_Pnt pl = myLastPnt;
614 TopoDS_Edge ee;
615 if(thePreviousEdge.IsNull()) {
616 BRepLib_MakeEdge e(cc, pf , pl);
617 ee = TopoDS::Edge(e.Shape());
618 }
619 else {
620 const TopoDS_Vertex& v1 = TopExp::LastVertex(thePreviousEdge,Standard_True);
621 BRepLib_MakeVertex v2(pl);
622 BRepLib_MakeEdge e(cc, v1, v2);
623 ee = TopoDS::Edge(e.Shape());
624 }
625 TopoDS_Shape aLocalShape = ee.Oriented(E.Orientation());
626 ee = TopoDS::Edge(aLocalShape);
627 // ee = TopoDS::Edge(ee.Oriented(E.Orientation()));
628 BB.Add(w, ee);
629 myLFMap(E).Append(ee);
630 if(counter == 1) theFV = TopExp::FirstVertex(ee,Standard_True);
631 thePreviousEdge = ee;
632 counter++;
633 break;
634 }
635 }
636 }
637
638 TopTools_ListIteratorOfListOfShape it(myListOfEdges);
639 Standard_Boolean FirstOK = Standard_False;
640 Standard_Boolean LastOK = Standard_False;
641
642 gp_Pnt theLastPnt = myLastPnt;
643 Standard_Integer sens = 0;
644 TopoDS_Edge theEdge, theLEdge, theFEdge;
645 Standard_Integer counter1 = counter;
646 TopTools_ListOfShape NewListOfEdges;
647 NewListOfEdges.Clear();
648 while (!FirstOK) {
649 const TopoDS_Edge& edg = TopoDS::Edge(it.Value());
650 gp_Pnt fp, lp;
651 Standard_Real f, l;
652 Handle(Geom_Curve) ccc = BRep_Tool::Curve(edg, f, l);
653 Handle(Geom_TrimmedCurve) cc = new Geom_TrimmedCurve(ccc, f, l);
654 if ( edg.Orientation() == TopAbs_REVERSED) cc->Reverse();
655
656 fp = cc->Value(cc->FirstParameter());
657 lp = cc->Value(cc->LastParameter());
658 Standard_Real dist = fp.Distance(theLastPnt);
659 if(dist <= myTol) {
660 sens = 1;
661 LastOK = Standard_True;
662 }
663 else {
664 dist = lp.Distance(theLastPnt);
665 if(dist <= myTol) {
666 sens = 2;
667 LastOK = Standard_True;
668 cc->Reverse();
669 }
670 }
671 Standard_Integer FirstFlag = 0;
672 if(sens==1 && lp.Distance(myFirstPnt) <= myTol) {
673 FirstOK = Standard_True;
674 FirstFlag = 1;
675 }
676 else if(sens==2 && fp.Distance(myFirstPnt) <= myTol) {
677 FirstOK = Standard_True;
678 FirstFlag = 2;
679 }
680
681 if (LastOK) {
682 TopoDS_Edge eeee;
683 Standard_Real fpar = cc->FirstParameter();
684 Standard_Real lpar = cc->LastParameter();
685 if(!FirstOK) {
686 if(thePreviousEdge.IsNull()) {
687 BRepLib_MakeEdge e(cc, fpar, lpar);
688 eeee = TopoDS::Edge(e.Shape());
689 }
690 else {
691 const TopoDS_Vertex& v1 = TopExp::LastVertex(thePreviousEdge,Standard_True);
692 BRepLib_MakeVertex v2(cc->Value(lpar));
693 BRepLib_MakeEdge e(cc, v1, v2);
694 eeee = TopoDS::Edge(e.Shape());
695 }
696 }
697 else {
698 if(thePreviousEdge.IsNull()) {
699 BRepLib_MakeVertex v1(cc->Value(fpar));
700 BRepLib_MakeEdge e(cc, v1, theFV);
701 eeee = TopoDS::Edge(e.Shape());
702 }
703 else {
704 const TopoDS_Vertex& v1 = TopExp::LastVertex(thePreviousEdge,Standard_True);
705 BRepLib_MakeEdge e(cc, v1, theFV);
706 eeee = TopoDS::Edge(e.Shape());
707 }
708 }
709
710 thePreviousEdge = eeee;
711 BB.Add(w, eeee);
712 if(counter == 1) theFV = TopExp::FirstVertex(eeee,Standard_True);
713 counter1++;
714 NewListOfEdges.Append(edg);
715 theEdge = eeee;
716
717 if(dist <= myTol)
718 theFEdge = edg;
719 theLastPnt = BRep_Tool::Pnt(TopExp::LastVertex(theEdge,Standard_True));
720 }
721
722 if(FirstFlag == 1) {
723 theLEdge = edg;
724 }
725 else if(FirstFlag == 2) {
726 theLEdge = theEdge;
727 }
728
729 if(LastOK) {
730 it.Initialize(myListOfEdges);
731 LastOK = Standard_False;
732 }
733 else if(it.More()) it.Next();
734 else {
735 Sliding = Standard_False;
736 break;
737 }
738 sens = 0;
739 }
740
741
742 TopTools_DataMapOfShapeListOfShape SlidMap;
743 SlidMap.Clear();
744
745 if(Sliding && counter1 > counter) {
746 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm;
747 TopExp_Explorer EX2(w, TopAbs_EDGE);
748 Standard_Integer ii = 0;
749 for(; EX2.More(); EX2.Next()) {
750 const TopoDS_Edge& E = TopoDS::Edge(EX2.Current());
751 ii++;
752 if(ii >= counter && ii <= counter1) {
753 it.Initialize(NewListOfEdges);
754 Standard_Integer jj = 0;
755 for(; it.More(); it.Next()) {
756 const TopoDS_Edge& e2 = TopoDS::Edge(it.Value());
757 jj++;
758 if(jj== (ii - counter +1)) {
759 itm.Initialize(mySlface);
760 for(; itm.More(); itm.Next()) {
761 const TopoDS_Face& fac = TopoDS::Face(itm.Key());
762 const TopTools_ListOfShape& ledg = itm.Value();
763 TopTools_ListIteratorOfListOfShape itedg(ledg);
764 //Standard_Integer iiii = 0;
765 for(; itedg.More(); itedg.Next()) {
766 const TopoDS_Edge& e1 = TopoDS::Edge(itedg.Value());
767 if(e1.IsSame(e2)){
768 if(!SlidMap.IsBound(fac)) {
769 TopTools_ListOfShape thelist2;
770 SlidMap.Bind(fac, thelist2);
771 }
772 SlidMap(fac).Append(E);
773 }
774 }
775 }
776 }
777 }
778 }
779 }
780 }
781
782 mySlface.Clear();
783 mySlface = SlidMap;
784 }
785
786 // ---Arguments of LocOpe_LinearForm : arguments of the prism
787 // sliding
788 if(Sliding) {
789 TopoDS_Face F;
790 BB.MakeFace(F, myPln, myTol);
791 w.Closed (BRep_Tool::IsClosed (w));
792 BB.Add(F, w);
793 mySkface = F;
794 myPbase = mySkface;
795 mySUntil.Nullify();
796 }
797
798
799 // ---Case without sliding : construction of the face profile
800 if(!Sliding) {
801 #ifdef OCCT_DEBUG
802 if (trc) {
803 if (Modify) std::cout << " Sliding failure" << std::endl;
804 std::cout << " no Sliding" << std::endl;
805 }
806 #endif
807 TopExp_Explorer explo1(BndFace, TopAbs_WIRE);
808 TopoDS_Wire WWW = TopoDS::Wire(explo1.Current());
809 BRepTools_WireExplorer explo(WWW);
810 BRep_Builder Bu;
811 TopoDS_Wire Wiwiwi;
812 Bu.MakeWire(Wiwiwi);
813 TopoDS_Vertex NewV1, NewV2, LastV, v;
814 NewV1.Nullify(); NewV2.Nullify(); LastV.Nullify();
815
816 for(; explo.More(); explo.Next()) {
817 const TopoDS_Edge& e = TopoDS::Edge(explo.Current());
818 TopoDS_Vertex v1 = TopExp::FirstVertex(e,Standard_True);
819 TopoDS_Vertex v2 = TopExp::LastVertex(e,Standard_True);
820
821 Standard_Real f, l;//, t;
822 Handle(Geom_Curve) ln = BRep_Tool::Curve(e, f, l);
823 // Handle(Geom_Curve) lln = BRep_Tool::Curve(e, f, l);
824 // Handle(Geom_Curve) ln;
825 // if(e.Orientation() == TopAbs_REVERSED) {
826 // ln = Handle(Geom_Curve)::DownCast(lln->Reversed());
827 // v = v1; v1 = v2; v2= v;
828 // f = IntPar(ln, BRep_Tool::Pnt(v1));
829 // l = IntPar(ln, BRep_Tool::Pnt(v2));
830 // }
831 // else ln = lln;
832
833 Handle(Geom2d_Curve) l2d = GeomAPI::To2d(ln, Plane->Pln());
834 Geom2dAPI_InterCurveCurve intcc(l2d, ln2d, Precision::Confusion());
835 TopoDS_Vertex VV; VV.Nullify();
836
837 if(intcc.NbPoints() > 0) {
838 gp_Pnt2d P = intcc.Point(1);
839 gp_Pnt point;
840 myPln->D0(P.X(), P.Y(), point);
841 Standard_Real par = IntPar(ln, point);
842 if(f <= par && l >= par) {
843 Bu.MakeVertex(VV, point, Precision::Confusion());
844 }
845 }
846
847 if(VV.IsNull() && NewV1.IsNull()) continue;
848
849 if(!VV.IsNull() && NewV1.IsNull()) {
850 NewV1 = VV;
851 LastV = v2;
852 BRepLib_MakeEdge ee1(NewV1, LastV);
853 Bu.Add(Wiwiwi, ee1);
854 continue;
855 }
856
857 if(VV.IsNull() && !NewV1.IsNull()) {
858 BRepLib_MakeEdge ee1(LastV, v2);
859 LastV = v2;
860 Bu.Add(Wiwiwi, e);
861 continue;
862 }
863
864 if(!VV.IsNull() && !NewV1.IsNull()) {
865 NewV2 = VV;
866 BRepLib_MakeEdge ee1(LastV, NewV2);
867 LastV = NewV2;
868 Bu.Add(Wiwiwi, ee1);
869 BRepLib_MakeEdge ee2(LastV, NewV1);
870 Bu.Add(Wiwiwi, ee2);
871 break;
872 }
873 }
874 Wiwiwi.Closed (BRep_Tool::IsClosed (Wiwiwi));
875
876 BRepLib_MakeFace newbndface(myPln->Pln(), Wiwiwi, Standard_True);
877 TopoDS_Face NewBndFace = TopoDS::Face(newbndface.Shape());
878
879 BRepTopAdaptor_FClass2d Cl(NewBndFace, Precision::Confusion());
880 Standard_Real paru, parv;
881 ElSLib::Parameters(myPln->Pln(), CheckPnt, paru, parv);
882 gp_Pnt2d checkpnt2d(paru, parv);
883 if(Cl.Perform(checkpnt2d, Standard_True) == TopAbs_OUT) {
884 BRepAlgoAPI_Cut c(BndFace, NewBndFace);
885 TopExp_Explorer exp(c.Shape(), TopAbs_WIRE);
886 const TopoDS_Wire& aCurWire = TopoDS::Wire(exp.Current());
887 BRepLib_MakeFace ff(myPln->Pln(), aCurWire, Standard_True);
888 NewBndFace = TopoDS::Face(ff.Shape());
889 }
890
891
892 if(!BRepAlgo::IsValid(NewBndFace)) {
893 #ifdef OCCT_DEBUG
894 std::cout << "Invalid new bounding face" << std::endl;
895 #endif
896 myStatusError = BRepFeat_InvShape;
897 NotDone();
898 return;
899 }
900
901 BndFace = NewBndFace;
902
903
904 TopoDS_Face Prof;
905 Standard_Boolean ProfileOK;
906 ProfileOK = NoSlidingProfile(Prof,RevolRib,myTol,Concavite,myPln,
907 bnd,BndFace,CheckPnt,
908 FirstFace,LastFace,FirstVertex,LastVertex,
909 FirstEdge,LastEdge,OnFirstFace,OnLastFace);
910
911 if (!ProfileOK) {
912 #ifdef OCCT_DEBUG
913 if (trc)
914 {
915 std::cout << "Not computable" << std::endl;
916 std::cout << " Face profile not computable" << std::endl;
917 }
918 #endif
919 myStatusError = BRepFeat_NoFaceProf;
920 NotDone();
921 return;
922 }
923
924
925 // ---Propagation on the faces of the initial shape
926 // to find the faces concerned by the rib
927 Standard_Boolean falseside = Standard_True;
928 Propagate(SliList, Prof, myFirstPnt, myLastPnt, falseside);
929 // Control if there is everything required to have the material at the proper side
930 if(falseside == Standard_False) {
931 #ifdef OCCT_DEBUG
932 std::cout << " Verify plane and wire orientation" << std::endl;
933 #endif
934 myStatusError = BRepFeat_FalseSide;
935 NotDone();
936 return;
937 }
938
939 mySlface.Clear();
940
941 TopTools_ListIteratorOfListOfShape it;
942 it.Initialize(SliList);
943
944 TopoDS_Shape comp;
945
946 BB.MakeShell(TopoDS::Shell(comp));
947
948 for(; it.More(); it.Next()) {
949 BB.Add(comp, it.Value());
950 }
951 comp.Closed (BRep_Tool::IsClosed (comp));
952
953 mySUntil = comp;
954
955 mySkface = Prof;
956 myPbase = Prof;
957 }
958
959 mySliding = Sliding;
960
961 TopExp_Explorer exp;
962 for ( exp.Init(mySbase,TopAbs_FACE);exp.More();exp.Next()) {
963 TopTools_ListOfShape thelist3;
964 myMap.Bind(exp.Current(), thelist3);
965 myMap(exp.Current()).Append(exp.Current());
966 }
967 }
968
969
970
971 //=======================================================================
972 //function : Add
973 //purpose : add elements of gluing
974 //=======================================================================
975
Add(const TopoDS_Edge & E,const TopoDS_Face & F)976 void BRepFeat_MakeRevolutionForm::Add(const TopoDS_Edge& E,
977 const TopoDS_Face& F)
978 {
979 #ifdef OCCT_DEBUG
980 Standard_Boolean trc = BRepFeat_GettraceFEAT();
981 if (trc) std::cout << "BRepFeat_MakeRevolutionForm::Add" << std::endl;
982 #endif
983 if(mySlface.IsEmpty()) {
984 TopExp_Explorer exp;
985 for (exp.Init(mySbase,TopAbs_FACE);exp.More();exp.Next()) {
986 if (exp.Current().IsSame(F)) {
987 break;
988 }
989 }
990 if (!exp.More()) {
991 throw Standard_ConstructionError();
992 }
993
994 if (!mySlface.IsBound(F)) {
995 TopTools_ListOfShape thelist;
996 mySlface.Bind(F, thelist);
997 }
998 TopTools_ListIteratorOfListOfShape itl(mySlface(F));
999 for (; itl.More();itl.Next()) {
1000 if (itl.Value().IsSame(E)) {
1001 break;
1002 }
1003 }
1004 if (!itl.More()) {
1005 mySlface(F).Append(E);
1006 }
1007 }
1008 }
1009
1010
1011
1012 //=======================================================================
1013 //function : Perform
1014 //purpose : construction
1015 //=======================================================================
1016
Perform()1017 void BRepFeat_MakeRevolutionForm::Perform()
1018 {
1019 #ifdef OCCT_DEBUG
1020 Standard_Boolean trc = BRepFeat_GettraceFEAT();
1021 if (trc) std::cout << "BRepFeat_MakeRevolutionForm::Perform()" << std::endl;
1022 #endif
1023 if(mySbase.IsNull() || mySkface.IsNull() || myPbase.IsNull()) {
1024 #ifdef OCCT_DEBUG
1025 if (trc) std::cout << " Fields not initialized" << std::endl;
1026 #endif
1027 myStatusError = BRepFeat_NotInitialized;
1028 NotDone();
1029 return;
1030 }
1031
1032 gp_Pnt Pt;
1033
1034 TopExp_Explorer exx(myPbase, TopAbs_VERTEX);
1035 for(; exx.More(); exx.Next()) {
1036 const TopoDS_Vertex& vv = TopoDS::Vertex(exx.Current());
1037 if(!vv.IsNull()) {
1038 Pt = BRep_Tool::Pnt(vv);
1039 break;
1040 }
1041 }
1042
1043 if(myAngle2 != 0) {
1044 gp_Trsf T;
1045 T.SetRotation(myAxe, -myAngle2);
1046 BRepBuilderAPI_Transform trsf(T);
1047 trsf.Perform(myPbase, Standard_False);
1048 TopoDS_Face Pbase = TopoDS::Face(trsf.Shape());
1049 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter(myLFMap);
1050 for(; iter.More(); iter.Next()) {
1051 const TopoDS_Shape& e1 = iter.Value().First();
1052 TopExp_Explorer ex1(myPbase, TopAbs_EDGE);
1053 TopExp_Explorer ex2(Pbase, TopAbs_EDGE);
1054 for(; ex1.More(); ex1.Next()) {
1055 if(ex1.Current().IsSame(e1)) {
1056 myLFMap(iter.Key()).Clear();
1057 myLFMap(iter.Key()).Append(ex2.Current());
1058 break; // break the cycle (e1 became a dead reference)
1059 }
1060 ex2.Next();
1061 }
1062 }
1063
1064 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(mySlface);
1065 for(; iter1.More(); iter1.Next()) {
1066 const TopoDS_Shape& e1 = iter1.Value().First();
1067 TopExp_Explorer ex1(myPbase, TopAbs_EDGE);
1068 TopExp_Explorer ex2(Pbase, TopAbs_EDGE);
1069 for(; ex1.More(); ex1.Next()) {
1070 if(ex1.Current().IsSame(e1)) {
1071 mySlface(iter1.Key()).Clear();
1072 mySlface(iter1.Key()).Append(ex2.Current());
1073 break; // break the cycle (e1 became a dead reference)
1074 }
1075 ex2.Next();
1076 }
1077 }
1078 myPbase = Pbase;
1079 trsf.Perform(mySkface, Standard_False);
1080 // flo : check if it is required to reattributr the field mySkface
1081 // TopoDS_Face mySkface = TopoDS::Face(trsf.Shape());
1082 mySkface = TopoDS::Face(trsf.Shape());
1083 }
1084
1085 LocOpe_RevolutionForm theForm;
1086 theForm.Perform(myPbase, myAxe, (myAngle1+myAngle2));
1087 TopoDS_Shape VraiForm = theForm.Shape(); // uncut primitive
1088
1089 // management of descendants
1090 MajMap(myPbase,theForm,myMap,myFShape,myLShape);
1091
1092 myGluedF.Clear();
1093
1094
1095
1096 gp_Pln Pln0 = myPln->Pln();
1097 BRepLib_MakeFace f(Pln0);
1098
1099
1100 gp_Vec vec1 = myHeight1*Normal(f, Pt);
1101 gp_Vec vec2 = -myHeight2*Normal(f, Pt);
1102
1103 gp_Pln Pln1 = Pln0.Translated(vec1);
1104 gp_Pln Pln2 = Pln0.Translated(vec2);
1105
1106 BRepLib_MakeFace ff1(Pln1);
1107 BRepLib_MakeFace ff2(Pln2);
1108 TopoDS_Face f1 = TopoDS::Face(ff1.Shape());
1109 TopoDS_Face f2 = TopoDS::Face(ff2.Shape());
1110 BRepFeat::FaceUntil(mySbase, f1);
1111 BRepFeat::FaceUntil(mySbase, f2);
1112
1113 LocOpe_CSIntersector ASI1(f1);
1114 LocOpe_CSIntersector ASI2(f2);
1115
1116 Handle(Geom_Line) normale = new Geom_Line(Pt, vec1);
1117 TColGeom_SequenceOfCurve scur;
1118 scur.Append(normale);
1119
1120 ASI1.Perform(scur);
1121 ASI2.Perform(scur);
1122
1123 if(!ASI1.IsDone() || !ASI2.IsDone() ||
1124 ASI1.NbPoints(1) != 1 || ASI2.NbPoints(1) != 1) {
1125 #ifdef OCCT_DEBUG
1126 if (trc) std::cout << " Intersection failure" << std::endl;
1127 #endif
1128 myStatusError = BRepFeat_BadIntersect;
1129 NotDone();
1130 return;
1131 }
1132
1133 TopAbs_Orientation Ori1 = ASI1.Point(1,1).Orientation();
1134 TopAbs_Orientation Ori2 = TopAbs::Reverse(ASI2.Point(1,1).Orientation());
1135 TopoDS_Face FF1 = ASI1.Point(1,1).Face();
1136 TopoDS_Face FF2 = ASI2.Point(1,1).Face();
1137
1138 TopoDS_Shape Comp;
1139 BRep_Builder B;
1140 B.MakeCompound(TopoDS::Compound(Comp));
1141 TopoDS_Solid S1 = BRepFeat::Tool(f1,FF1,Ori1);
1142 TopoDS_Solid S2 = BRepFeat::Tool(f2,FF2,Ori2);
1143 if (!S1.IsNull()) B.Add(Comp,S1);
1144 if (!S2.IsNull()) B.Add(Comp,S2);
1145
1146 BRepAlgoAPI_Cut trP(VraiForm,Comp);
1147 // coupe de la nervure par deux plans parallels
1148 TopTools_DataMapOfShapeListOfShape SlidingMap;
1149
1150 // management of descendants
1151
1152 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape it1;
1153 it1.Initialize(myMap);
1154 for(; it1.More(); it1.Next()) {
1155 const TopoDS_Shape& orig = it1.Key();
1156 if(it1.Value().IsEmpty()) continue;
1157 const TopoDS_Shape& sh = it1.Value().First();
1158 exx.Init(VraiForm, TopAbs_FACE);
1159 for(; exx.More(); exx.Next()) {
1160 TopoDS_Face fac = TopoDS::Face(exx.Current());
1161 TopExp_Explorer exx1(fac, TopAbs_WIRE);
1162 TopoDS_Wire thew = TopoDS::Wire(exx1.Current());
1163 if(thew.IsSame(myFShape)) {
1164 const TopTools_ListOfShape& desfaces = trP.Modified(f2);
1165 myMap(myFShape) = desfaces;
1166 continue;
1167 }
1168 else if(thew.IsSame(myLShape)) {
1169 const TopTools_ListOfShape& desfaces = trP.Modified(f1);
1170 myMap(myLShape) = desfaces;
1171 continue;
1172 }
1173 if(fac.IsSame(sh)) {
1174 if (! trP.IsDeleted(fac))
1175 {
1176 const TopTools_ListOfShape& desfaces = trP.Modified(fac);
1177 if(!desfaces.IsEmpty()) {
1178 myMap(orig).Clear();
1179 myMap(orig) = trP.Modified(fac);
1180 break; // break the cycle (sh became a dead reference)
1181 }
1182 }
1183 }
1184 }
1185 }
1186
1187 exx.Init(VraiForm, TopAbs_FACE);
1188 for(; exx.More(); exx.Next()) {
1189 const TopoDS_Face& fac = TopoDS::Face(exx.Current());
1190 TopTools_ListOfShape thelist;
1191 SlidingMap.Bind(fac, thelist);
1192 if (trP.IsDeleted(fac)) {
1193 }
1194 else {
1195 const TopTools_ListOfShape& desfaces = trP.Modified(fac);
1196 if(!desfaces.IsEmpty())
1197 SlidingMap(fac) = desfaces;
1198 else
1199 SlidingMap(fac).Append(fac);
1200 }
1201 }
1202
1203
1204 // gestion of faces of sliding
1205 SetGluedFaces(mySlface, theForm, SlidingMap, myGluedF);
1206
1207 VraiForm = trP.Shape(); // primitive cut
1208
1209 if(!myGluedF.IsEmpty())
1210 myPerfSelection = BRepFeat_NoSelection;
1211 else
1212 myPerfSelection = BRepFeat_SelectionSh;
1213
1214 exx.Init(myPbase, TopAbs_EDGE);
1215 for(; exx.More(); exx.Next()) {
1216 const TopoDS_Edge& e = TopoDS::Edge(exx.Current());
1217 if(!myMap.IsBound(e)) {
1218 #ifdef OCCT_DEBUG
1219 if (trc) std::cout << " Sliding face not in Base shape" << std::endl;
1220 #endif
1221 myStatusError = BRepFeat_IncSlidFace;
1222 NotDone();
1223 return;
1224 }
1225 }
1226
1227 myGShape = VraiForm;
1228
1229 if(!myGluedF.IsEmpty() && !mySUntil.IsNull()) {
1230 #ifdef OCCT_DEBUG
1231 if (trc)
1232 {
1233 std::cout << "The case is not computable" << std::endl;
1234 std::cout << " Glued faces not empty and Until shape not null" << std::endl;
1235 }
1236 #endif
1237 myStatusError = BRepFeat_InvShape;
1238 NotDone();
1239 return;
1240 }
1241
1242 LFPerform(); // topological reconstruction
1243 }
1244
1245
1246 //=======================================================================
1247 //function : Propagate
1248 //purpose : propagation on the faces of the initial shape, find faces
1249 // concerned by the rib
1250 //=======================================================================
1251
Propagate(TopTools_ListOfShape & SliList,const TopoDS_Face & fac,const gp_Pnt & Firstpnt,const gp_Pnt & Lastpnt,Standard_Boolean & falseside)1252 Standard_Boolean BRepFeat_MakeRevolutionForm::Propagate(TopTools_ListOfShape& SliList,
1253 const TopoDS_Face& fac,
1254 const gp_Pnt& Firstpnt,
1255 const gp_Pnt& Lastpnt,
1256 Standard_Boolean& falseside)
1257 {
1258 #ifdef OCCT_DEBUG
1259 Standard_Boolean trc = BRepFeat_GettraceFEATRIB();
1260 if (trc) std::cout << "BRepFeat_MakeRevolutionForm::Propagate" << std::endl;
1261 #endif
1262 gp_Pnt Firstpoint = Firstpnt;
1263 gp_Pnt Lastpoint = Lastpnt;
1264
1265 Standard_Boolean result = Standard_True;
1266 TopoDS_Face CurrentFace, saveFace;
1267 CurrentFace = TopoDS::Face(SliList.First());
1268 saveFace = CurrentFace;
1269 // BRepBuilderAPI_MakeFace fac(myPln);
1270 Standard_Boolean LastOK = Standard_False, FirstOK= Standard_False;
1271 TopoDS_Vertex v1, v2, v3, v4, Vert;
1272 BRepAlgoAPI_Section sect (fac, CurrentFace, Standard_False);
1273 sect.Approximation(Standard_True);
1274 sect.Build();
1275 TopExp_Explorer Ex;
1276 TopoDS_Edge e, e1;
1277 gp_Pnt FP, LP;
1278 Standard_Integer ii = 0;
1279 for (Ex.Init(sect.Shape(), TopAbs_EDGE); Ex.More(); Ex.Next()) {
1280 ii++;
1281 if(ii==1){
1282 e = TopoDS::Edge(Ex.Current());
1283 }
1284 else if (ii > 1) {
1285 e1 = TopoDS::Edge(Ex.Current());
1286 break;
1287 }
1288 }
1289 if(e.IsNull()) {
1290 falseside = Standard_False;
1291 return Standard_False;
1292 }
1293 //
1294 if(!e1.IsNull()) {
1295 Standard_Real aTolV1, aTolV2;
1296 myListOfEdges.Clear();
1297 TopTools_ListOfShape thelist;
1298 mySlface.Bind(CurrentFace, thelist);
1299 mySlface(CurrentFace).Append(e1);
1300
1301 myListOfEdges.Append(e1);
1302
1303 v1 = TopExp::FirstVertex(e1,Standard_True);
1304 v2 = TopExp::LastVertex (e1,Standard_True);
1305
1306 FP = BRep_Tool::Pnt(v1);
1307 LP = BRep_Tool::Pnt(v2);
1308
1309 aTolV1=BRep_Tool::Tolerance(v1);
1310 aTolV2=BRep_Tool::Tolerance(v2);
1311
1312 if(FP.Distance(Firstpoint) <= aTolV1 ||
1313 FP.Distance(Lastpoint) <= aTolV1) {
1314 FirstOK = Standard_True;
1315 }
1316 if(LP.Distance(Firstpoint)<= aTolV2 ||
1317 LP.Distance(Lastpoint) <= aTolV2) {
1318 LastOK = Standard_True;
1319 }
1320
1321 if(LastOK && FirstOK) {
1322 return result;
1323 }
1324
1325 else {
1326 myListOfEdges.Clear();
1327 }
1328 }
1329 //
1330 if(!e1.IsNull()) {
1331 myListOfEdges.Clear();
1332 TopTools_ListOfShape thelist1;
1333 mySlface.Bind(CurrentFace, thelist1);
1334 mySlface(CurrentFace).Append(e);
1335
1336 myListOfEdges.Append(e);
1337
1338 // mySlface.Bind(CurrentFace,TopTools_ListOfShape());
1339 mySlface(CurrentFace).Append(e1);
1340 // myListOfEdges.Append(e1);
1341
1342 v1 = TopExp::FirstVertex(e,Standard_True);
1343 v2 = TopExp::LastVertex(e,Standard_True);
1344 v3 = TopExp::FirstVertex(e1,Standard_True);
1345 v4 = TopExp::LastVertex(e1,Standard_True);
1346 gp_Pnt p1, p2, p3, p4;
1347 p1 = BRep_Tool::Pnt(v1); FP = p1;
1348 p2 = BRep_Tool::Pnt(v2); LP = p2;
1349 p3 = BRep_Tool::Pnt(v3);
1350 p4 = BRep_Tool::Pnt(v4);
1351 if(p1.Distance(Firstpoint) <= BRep_Tool::Tolerance(v1)) {
1352 if(p3.Distance(Lastpoint) <= BRep_Tool::Tolerance(v3)) {
1353 FirstOK = Standard_True;
1354 Lastpoint = p4;
1355 }
1356 else if(p4.Distance(Lastpoint) <= BRep_Tool::Tolerance(v4)) {
1357 FirstOK = Standard_True;
1358 Lastpoint = p3;
1359 }
1360 else {
1361 e1.Nullify();
1362 }
1363 }
1364 else if(p1.Distance(Lastpoint) <= BRep_Tool::Tolerance(v1)) {
1365 if(p3.Distance(Firstpoint) <= BRep_Tool::Tolerance(v3)) {
1366 FirstOK = Standard_True;
1367 Firstpoint = p4;
1368 }
1369 else if(p4.Distance(Firstpoint) <= BRep_Tool::Tolerance(v4)) {
1370 FirstOK = Standard_True;
1371 Firstpoint = p3;
1372 }
1373 else {
1374 e1.Nullify();
1375 }
1376 }
1377 else if(p2.Distance(Firstpoint) <= BRep_Tool::Tolerance(v2)) {
1378 if(p3.Distance(Lastpoint) <= BRep_Tool::Tolerance(v3)) {
1379 LastOK = Standard_True;
1380 Lastpoint = p4;
1381 }
1382 else if(p4.Distance(Lastpoint) <= BRep_Tool::Tolerance(v4)) {
1383 LastOK = Standard_True;
1384 Lastpoint = p3;
1385 }
1386 else {
1387 e1.Nullify();
1388 }
1389 }
1390 else if(p2.Distance(Lastpoint) <= BRep_Tool::Tolerance(v2)) {
1391 if(p3.Distance(Firstpoint) <= BRep_Tool::Tolerance(v3)) {
1392 LastOK = Standard_True;
1393 Firstpoint = p4;
1394 }
1395 else if(p4.Distance(Firstpoint) <= BRep_Tool::Tolerance(v4)) {
1396 LastOK = Standard_True;
1397 Firstpoint = p3;
1398 }
1399 else {
1400 e1.Nullify();
1401 }
1402 }
1403 else {
1404 e = e1;
1405 e1.Nullify();
1406 }
1407 }
1408 if(e1.IsNull()) {
1409 myListOfEdges.Clear();
1410 TopTools_ListOfShape thelist2;
1411 mySlface.Bind(CurrentFace, thelist2);
1412 mySlface(CurrentFace).Append(e);
1413
1414 myListOfEdges.Append(e);
1415
1416 v1 = TopExp::FirstVertex(e,Standard_True);
1417 v2 = TopExp::LastVertex(e,Standard_True);
1418
1419 FP = BRep_Tool::Pnt(v1);
1420 LP = BRep_Tool::Pnt(v2);
1421
1422 if(FP.Distance(Firstpoint) <= BRep_Tool::Tolerance(v1)
1423 || FP.Distance(Lastpoint) <= BRep_Tool::Tolerance(v1)) {
1424 FirstOK = Standard_True;
1425 }
1426 if(LP.Distance(Firstpoint) <= BRep_Tool::Tolerance(v2)
1427 || LP.Distance(Lastpoint) <= BRep_Tool::Tolerance(v2)) {
1428 LastOK = Standard_True;
1429 }
1430
1431 if(LastOK && FirstOK) {
1432 return result;
1433 }
1434 }
1435
1436 TopTools_IndexedDataMapOfShapeListOfShape mapedges;
1437 TopExp::MapShapesAndAncestors(mySbase, TopAbs_EDGE, TopAbs_FACE, mapedges);
1438 TopExp_Explorer ex;
1439 TopoDS_Edge FirstEdge;
1440
1441 TopoDS_Vertex Vprevious; Vprevious.Nullify();
1442 TopoDS_Vertex Vpreprevious; Vpreprevious.Nullify();
1443
1444 while(!FirstOK) {
1445 // find edge connected to v1:
1446 gp_Pnt pt;
1447 if(!v1.IsNull()) pt= BRep_Tool::Pnt(v1);
1448 gp_Pnt ptprev;
1449 if(!Vprevious.IsNull()) ptprev = BRep_Tool::Pnt(Vprevious);
1450 gp_Pnt ptpreprev;
1451 if(!Vpreprevious.IsNull()) ptpreprev = BRep_Tool::Pnt(Vpreprevious);
1452
1453 if((!Vprevious.IsNull() && ptprev.Distance(pt) <= myTol) ||
1454 (!Vpreprevious.IsNull() && ptpreprev.Distance(pt) <= myTol)) {
1455 falseside = Standard_False;
1456 return Standard_False;
1457 }
1458
1459 for (ex.Init(CurrentFace, TopAbs_EDGE); ex.More(); ex.Next()) {
1460 const TopoDS_Edge& aCurEdge = TopoDS::Edge(ex.Current());
1461
1462 BRepExtrema_ExtPC projF(v1, aCurEdge);
1463
1464 if(projF.IsDone() && projF.NbExt() >=1) {
1465 Standard_Real dist2min = RealLast();
1466 Standard_Integer index = 0;
1467 for (Standard_Integer sol =1 ; sol <= projF.NbExt(); sol++) {
1468 if (projF.SquareDistance(sol) <= dist2min) {
1469 index = sol;
1470 dist2min = projF.SquareDistance(sol);
1471 }
1472 }
1473 if (index != 0) {
1474 if (dist2min <= BRep_Tool::Tolerance(aCurEdge) * BRep_Tool::Tolerance(aCurEdge)) {
1475 FirstEdge = aCurEdge;
1476 break;
1477 }
1478 }
1479 }
1480 }
1481
1482 const TopTools_ListOfShape& L = mapedges.FindFromKey(FirstEdge);
1483 TopTools_ListIteratorOfListOfShape It(L);
1484
1485 for (; It.More(); It.Next()) {
1486 const TopoDS_Face& FF = TopoDS::Face(It.Value());
1487 if (!FF.IsSame(CurrentFace)) {
1488 CurrentFace = FF;
1489 break;
1490 }
1491 }
1492
1493 BRepAlgoAPI_Section sectf (fac, CurrentFace, Standard_False);
1494 sectf.Approximation(Standard_True);
1495 sectf.Build();
1496
1497 TopoDS_Edge edg1;
1498 for (Ex.Init(sectf.Shape(), TopAbs_EDGE); Ex.More(); Ex.Next()) {
1499 edg1 = TopoDS::Edge(Ex.Current());
1500 gp_Pnt ppp1 = BRep_Tool::Pnt(TopExp::FirstVertex(edg1,Standard_True));
1501 gp_Pnt ppp2 = BRep_Tool::Pnt(TopExp::LastVertex(edg1,Standard_True));
1502 if(ppp1.Distance(BRep_Tool::Pnt(v1)) <= BRep_Tool::Tolerance(v1) ||
1503 ppp2.Distance(BRep_Tool::Pnt(v1)) <= BRep_Tool::Tolerance(v1))
1504 break;
1505 }
1506
1507 TopTools_ListOfShape thelist3;
1508 mySlface.Bind(CurrentFace, thelist3);
1509 mySlface(CurrentFace).Append(edg1);
1510 myListOfEdges.Append(edg1);
1511
1512 if (!edg1.IsNull()) SliList.Prepend(CurrentFace);
1513 else return Standard_False;
1514
1515 Vert = TopExp::FirstVertex(edg1,Standard_True);
1516 gp_Pnt PP = BRep_Tool::Pnt(Vert);
1517 FP = BRep_Tool::Pnt(v1);
1518 Standard_Real tol = BRep_Tool::Tolerance(edg1);
1519 Standard_Real tol1 = BRep_Tool::Tolerance(v1);
1520 if(tol1 > tol) tol = tol1;
1521 Standard_Real dist = PP.Distance(FP);
1522 if (dist <= tol) {
1523 Vpreprevious = Vprevious;
1524 Vprevious = v1;
1525 v1 = TopExp::LastVertex(edg1,Standard_True);
1526 }
1527 else {
1528 Vpreprevious = Vprevious;
1529 Vprevious = v1;
1530 v1 = Vert;
1531 }
1532
1533 FP = BRep_Tool::Pnt(v1);
1534
1535 if(FP.Distance(Firstpoint) <= BRep_Tool::Tolerance(v1)
1536 || FP.Distance(Lastpoint) <= BRep_Tool::Tolerance(v1)) {
1537 FirstOK = Standard_True;
1538 }
1539 }
1540
1541 CurrentFace = saveFace;
1542 Vprevious.Nullify();
1543 Vpreprevious.Nullify();
1544
1545 while(!LastOK) {
1546 // find edge connected to v2:
1547 gp_Pnt pt;
1548 if(!v2.IsNull()) pt= BRep_Tool::Pnt(v2);
1549 gp_Pnt ptprev;
1550 if(!Vprevious.IsNull()) ptprev = BRep_Tool::Pnt(Vprevious);
1551 gp_Pnt ptpreprev;
1552 if(!Vpreprevious.IsNull()) ptpreprev = BRep_Tool::Pnt(Vpreprevious);
1553
1554 if((!Vprevious.IsNull() && ptprev.Distance(pt) <= myTol) ||
1555 (!Vpreprevious.IsNull() && ptpreprev.Distance(pt) <= myTol)) {
1556 falseside = Standard_False;
1557 return Standard_False;
1558 }
1559
1560 for (ex.Init(CurrentFace, TopAbs_EDGE); ex.More(); ex.Next()) {
1561 const TopoDS_Edge& aCurEdge = TopoDS::Edge(ex.Current());
1562 BRepExtrema_ExtPC projF(v2, aCurEdge);
1563
1564 if(projF.IsDone() && projF.NbExt() >=1) {
1565 Standard_Real dist2min = RealLast();
1566 Standard_Integer index = 0;
1567 for (Standard_Integer sol =1 ; sol <= projF.NbExt(); sol++) {
1568 if (projF.SquareDistance(sol) <= dist2min) {
1569 index = sol;
1570 dist2min = projF.SquareDistance(sol);
1571 }
1572 }
1573 if (index != 0) {
1574 if (dist2min <= BRep_Tool::Tolerance(aCurEdge) * BRep_Tool::Tolerance(aCurEdge)) {
1575 FirstEdge = aCurEdge;
1576 break;
1577 }
1578 }
1579 }
1580 }
1581
1582 const TopTools_ListOfShape& L = mapedges.FindFromKey(FirstEdge);
1583 TopTools_ListIteratorOfListOfShape It(L);
1584
1585 for (; It.More(); It.Next()) {
1586 const TopoDS_Face& FF = TopoDS::Face(It.Value());
1587 if (!FF.IsSame(CurrentFace)) {
1588 CurrentFace = FF;
1589 break;
1590 }
1591 }
1592
1593 ii = 0;
1594
1595 BRepAlgoAPI_Section sectf (fac, CurrentFace, Standard_False);
1596 sectf.Approximation(Standard_True);
1597 sectf.Build();
1598
1599 TopoDS_Edge edg2;
1600 for (Ex.Init(sectf.Shape(), TopAbs_EDGE); Ex.More(); Ex.Next()) {
1601 edg2 = TopoDS::Edge(Ex.Current());
1602 gp_Pnt ppp1 = BRep_Tool::Pnt(TopExp::FirstVertex(edg2,Standard_True));
1603 gp_Pnt ppp2 = BRep_Tool::Pnt(TopExp::LastVertex(edg2,Standard_True));
1604 if(ppp1.Distance(BRep_Tool::Pnt(v2)) <= BRep_Tool::Tolerance(v2) ||
1605 ppp2.Distance(BRep_Tool::Pnt(v2)) <= BRep_Tool::Tolerance(v2))
1606 break;
1607 }
1608 TopTools_ListOfShape thelist4;
1609 mySlface.Bind(CurrentFace, thelist4);
1610 mySlface(CurrentFace).Append(edg2);
1611 myListOfEdges.Append(edg2);
1612
1613 if (!edg2.IsNull()) SliList.Append(CurrentFace);
1614 else return Standard_False;
1615
1616 Vert = TopExp::FirstVertex(edg2,Standard_True);
1617 gp_Pnt PP = BRep_Tool::Pnt(Vert);
1618 FP = BRep_Tool::Pnt(v2);
1619 if (PP.Distance(FP)<= BRep_Tool::Tolerance(v2)) {
1620 Vpreprevious = Vprevious;
1621 Vprevious = v2;
1622 v2 = TopExp::LastVertex(edg2,Standard_True);
1623 }
1624 else {
1625 v2 = Vert;
1626 }
1627 FP = BRep_Tool::Pnt(v2);
1628
1629
1630 if(FP.Distance(Firstpoint) <= BRep_Tool::Tolerance(v2)
1631 || FP.Distance(Lastpoint) <= BRep_Tool::Tolerance(v2)) {
1632 LastOK = Standard_True;
1633 }
1634 }
1635 if(!e1.IsNull()) myListOfEdges.Append(e1);
1636 return result;
1637
1638 }
1639
1640
1641 //=======================================================================
1642 //function : MajMap
1643 //purpose : management of descendants
1644 //=======================================================================
1645
MajMap(const TopoDS_Shape & theB,const LocOpe_RevolutionForm & theP,TopTools_DataMapOfShapeListOfShape & theMap,TopoDS_Shape & theFShape,TopoDS_Shape & theLShape)1646 static void MajMap(const TopoDS_Shape& theB,
1647 const LocOpe_RevolutionForm& theP,
1648 TopTools_DataMapOfShapeListOfShape& theMap, // myMap
1649 TopoDS_Shape& theFShape, // myFShape
1650 TopoDS_Shape& theLShape) // myLShape
1651 {
1652 TopExp_Explorer exp(theP.FirstShape(),TopAbs_WIRE);
1653 if (exp.More()) {
1654 theFShape = exp.Current();
1655 TopTools_ListOfShape thelist;
1656 theMap.Bind(theFShape, thelist);
1657 for (exp.Init(theP.FirstShape(),TopAbs_FACE);exp.More();exp.Next()) {
1658 const TopoDS_Shape& sh = exp.Current();
1659 theMap(theFShape).Append(sh);
1660 }
1661 }
1662
1663 exp.Init(theP.LastShape(),TopAbs_WIRE);
1664 if (exp.More()) {
1665 theLShape = exp.Current();
1666 TopTools_ListOfShape thelist1;
1667 theMap.Bind(theLShape, thelist1);
1668 for (exp.Init(theP.LastShape(),TopAbs_FACE);exp.More();exp.Next()) {
1669 const TopoDS_Shape& sh = exp.Current();
1670 theMap(theLShape).Append(sh);
1671 }
1672 }
1673
1674 for (exp.Init(theB,TopAbs_EDGE); exp.More(); exp.Next()) {
1675 if (!theMap.IsBound(exp.Current())) {
1676 TopTools_ListOfShape thelist2;
1677 theMap.Bind(exp.Current(), thelist2);
1678 theMap(exp.Current()) = theP.Shapes(exp.Current());
1679 }
1680 }
1681 }
1682
1683
1684 //=======================================================================
1685 //function : SetGluedFaces
1686 //purpose : managemnet of sliding faces
1687 //=======================================================================
1688
SetGluedFaces(const TopTools_DataMapOfShapeListOfShape & theSlmap,LocOpe_RevolutionForm & thePrism,const TopTools_DataMapOfShapeListOfShape & SlidingMap,TopTools_DataMapOfShapeShape & theMap)1689 static void SetGluedFaces(const TopTools_DataMapOfShapeListOfShape& theSlmap,
1690 LocOpe_RevolutionForm& thePrism,
1691 const TopTools_DataMapOfShapeListOfShape& SlidingMap,
1692 TopTools_DataMapOfShapeShape& theMap)
1693 {
1694 // Slidings
1695 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(theSlmap);
1696 if(!theSlmap.IsEmpty()) {
1697 for (; itm.More(); itm.Next()) {
1698 const TopoDS_Face& fac = TopoDS::Face(itm.Key());
1699 const TopTools_ListOfShape& ledg = itm.Value();
1700 TopTools_ListIteratorOfListOfShape it;
1701 for (it.Initialize(ledg); it.More(); it.Next()) {
1702 const TopTools_ListOfShape& gfac = thePrism.Shapes(it.Value());
1703 if (gfac.Extent() != 1) {
1704 #ifdef OCCT_DEBUG
1705 std::cout << "Pb SetGluedFace" << std::endl;
1706 #endif
1707 }
1708 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iterm(SlidingMap);
1709 for(; iterm.More(); iterm.Next()) {
1710 const TopoDS_Face& ff = TopoDS::Face(iterm.Key());
1711 const TopTools_ListOfShape& lfaces = iterm.Value();
1712 if(lfaces.IsEmpty()) continue;
1713 const TopoDS_Face& fff = TopoDS::Face(lfaces.First());
1714 if(gfac.First().IsSame(ff)) theMap.Bind(fff,fac);
1715 }
1716 }
1717 }
1718 }
1719 }
1720
1721