0023311: Duplicated check in if-clause in ChFi2d_Builder_0.cxx
[occt.git] / src / ChFi2d / ChFi2d_Builder_0.cxx
1 // Created on: 1995-07-07
2 // Created by: Joelle CHAUVET
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21 // Modified : 08/07/97 : JPI : traitement des edges degeneres comme pour les fillets 2D
22 // Modified:    Fri Sep 25 09:38:04 1998
23 //              status = ChFi2d_NotAuthorized si les aretes ne sont pas
24 //              des droites ou des cercles; fonction IsLineOrCircle
25 //              (BUC60288)
26
27 #include <ChFi2d.hxx>
28 #include <ChFi2d_Builder.ixx>
29
30 #include <BRepAdaptor_Curve.hxx>
31 #include <BRepAdaptor_Surface.hxx>
32 #include <BRepLib_MakeEdge.hxx>
33 #include <BRepLib_MakeFace.hxx>
34
35 #include <BRep_Builder.hxx>
36 #include <BRep_Tool.hxx>
37
38 #include <ElCLib.hxx>
39 #include <Geom_Curve.hxx>
40 #include <Geom_Line.hxx>
41 #include <Geom_Plane.hxx>
42 #include <Geom_Surface.hxx>
43
44 #include <GeomAdaptor_Curve.hxx>
45 #include <GeomAPI.hxx>
46 #include <GCPnts_AbscissaPoint.hxx>
47
48 #include <Geom2dAdaptor_Curve.hxx>
49 #include <Geom2d_TrimmedCurve.hxx>
50 #include <Geom2d_Circle.hxx>
51 #include <Geom2d_Curve.hxx>
52 #include <Geom2d_Line.hxx>
53 #include <Geom2dInt_GInter.hxx>
54
55 #include <IntRes2d_IntersectionPoint.hxx>
56
57 #include <gp_Pln.hxx>
58 #include <gp_Pnt.hxx>
59 #include <gp_Pnt2d.hxx>
60
61 #include <Precision.hxx>
62
63 #include <TopAbs_Orientation.hxx>
64 #include <TopExp.hxx>
65 #include <TopExp_Explorer.hxx>
66 #include <TopLoc_Location.hxx>
67
68 #include <TopoDS.hxx>
69 #include <TopoDS_Edge.hxx>
70 #include <TopoDS_Wire.hxx>
71 #include <TopoDS_Shape.hxx>
72
73
74 gp_Pnt ComputePoint(const TopoDS_Vertex& V,const TopoDS_Edge& E, 
75                     const Standard_Real D1, Standard_Real& Param1);
76 gp_Pnt ComputePoint(const TopoDS_Face& F, const Handle(Geom_Line)& L,
77                     const TopoDS_Edge& E, Standard_Real& Param);
78 void OrientChamfer(TopoDS_Edge& chamfer,
79                    const TopoDS_Edge& E,
80                    const TopoDS_Vertex& V);
81
82 static Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E,
83                                        const TopoDS_Face& F);
84
85
86 //=======================================================================
87 //function : AddChamfer
88 //purpose  : 
89 //=======================================================================
90
91 TopoDS_Edge ChFi2d_Builder::AddChamfer(const TopoDS_Edge& E1,
92                                      const TopoDS_Edge& E2,
93                                      const Standard_Real D1,
94                                      const Standard_Real D2)
95 {
96   TopoDS_Vertex commonVertex;
97   TopoDS_Edge basisEdge1, basisEdge2;
98   TopoDS_Edge E1Mod, E2Mod, chamfer;
99   
100   Standard_Boolean hasConnection = ChFi2d::CommonVertex(E1, E2, commonVertex);
101   if (!hasConnection) return chamfer;
102
103   if (IsAFillet(E1) || IsAChamfer(E1) ||
104       IsAFillet(E2) || IsAChamfer(E2)) {
105     status = ChFi2d_NotAuthorized;
106     return chamfer;
107   } //  if (IsAChamfer ...
108
109   if (!IsLineOrCircle(E1,newFace) 
110       || !IsLineOrCircle(E2,newFace) ) {
111     status = ChFi2d_NotAuthorized;
112     return chamfer;
113   } //  if (!IsLineOrCircle ...
114
115   // EE1 and EE2 are copies of E1 and E2 with the good orientation
116   // on <newFace>
117   TopoDS_Edge EE1, EE2;
118   status = ChFi2d::FindConnectedEdges(newFace, commonVertex, EE1, EE2);
119   if (EE1.IsSame(E2)) {
120     TopAbs_Orientation orient = EE1.Orientation();
121     EE1 = EE2;
122     EE2 = E2;
123     EE2.Orientation(orient);
124   }
125
126   ComputeChamfer(commonVertex, EE1, EE2, D1, D2,
127                  E1Mod, E2Mod, chamfer);
128   if (status == ChFi2d_IsDone
129       || status == ChFi2d_FirstEdgeDegenerated
130       || status == ChFi2d_LastEdgeDegenerated
131       || status == ChFi2d_BothEdgesDegenerated) {
132 //  if (status == ChFi2d_IsDone) {
133     BuildNewWire(EE1, EE2, E1Mod, chamfer, E2Mod);
134     basisEdge1 = BasisEdge(EE1);
135     basisEdge2 = BasisEdge(EE2);
136     UpDateHistory(basisEdge1, basisEdge2,
137                   E1Mod, E2Mod, chamfer, 2);
138     status = ChFi2d_IsDone;
139     return TopoDS::Edge(chamfers.Value(chamfers.Length()));
140   }
141   return chamfer;
142 } // AddChamfer
143
144
145 //=======================================================================
146 //function : AddChamfer
147 //purpose  : 
148 //=======================================================================
149
150 TopoDS_Edge ChFi2d_Builder::AddChamfer(const TopoDS_Edge& E,
151                                      const TopoDS_Vertex& V,
152                                      const Standard_Real D,
153                                      const Standard_Real Ang)
154 {
155   TopoDS_Edge aChamfer, adjEdge1, adjEdge2;
156   status = ChFi2d::FindConnectedEdges(newFace, V, adjEdge1, adjEdge2);
157   if (status == ChFi2d_ConnexionError) return aChamfer;
158
159   // adjEdge1 is a copy of E  with the good orientation
160   // on <newFace>
161   if (adjEdge2.IsSame(E)) {
162     TopAbs_Orientation orient = adjEdge2.Orientation();
163     adjEdge2 = adjEdge1;
164     adjEdge1 = E;
165     adjEdge1.Orientation(orient);
166   }
167
168   if (IsAFillet(adjEdge1) || IsAChamfer(adjEdge1) ||
169       IsAFillet(adjEdge2) || IsAChamfer(adjEdge2)) {
170     status = ChFi2d_NotAuthorized;
171     return aChamfer;
172   } //  if (IsAChamfer ...
173
174   if (!IsLineOrCircle(adjEdge1,newFace) 
175       || !IsLineOrCircle(adjEdge2,newFace) ) {
176     status = ChFi2d_NotAuthorized;
177     return aChamfer;
178   } //  if (!IsLineOrCircle ...
179
180   TopoDS_Edge E1, E2;
181   ComputeChamfer(V, adjEdge1, D, Ang,
182                  adjEdge2, E1, E2, aChamfer);
183   TopoDS_Edge basisEdge1, basisEdge2;
184   if (status == ChFi2d_IsDone
185       || status == ChFi2d_FirstEdgeDegenerated
186       || status == ChFi2d_LastEdgeDegenerated
187       || status == ChFi2d_BothEdgesDegenerated) {
188 //  if (status == ChFi2d_IsDone) {
189     BuildNewWire(adjEdge1, adjEdge2, E1, aChamfer, E2);
190     basisEdge1 = BasisEdge(adjEdge1);
191     basisEdge2 = BasisEdge(adjEdge2);
192     UpDateHistory(basisEdge1, basisEdge2,
193                   E1, E2, aChamfer, 2);
194     status = ChFi2d_IsDone;
195     return TopoDS::Edge(chamfers.Value(chamfers.Length()));
196   }
197   return aChamfer;
198
199 }
200
201
202 //=======================================================================
203 //function : ComputeChamfer
204 //purpose  : 
205 //=======================================================================
206
207 void ChFi2d_Builder::ComputeChamfer(const TopoDS_Vertex& V, 
208                                   const TopoDS_Edge& E1, 
209                                   const TopoDS_Edge& E2, 
210                                   const Standard_Real D1,
211                                   const Standard_Real D2,
212                                   TopoDS_Edge& TrimE1, 
213                                   TopoDS_Edge& TrimE2, 
214                                   TopoDS_Edge& Chamfer) 
215 {
216    TopoDS_Vertex newExtr1, newExtr2;
217    Standard_Boolean Degen1, Degen2;
218    Chamfer = BuildChamferEdge(V, E1, E2, D1, D2, newExtr1, newExtr2);
219    if ( status != ChFi2d_IsDone) return;
220   TrimE1 = BuildNewEdge(E1, V, newExtr1, Degen1);
221   TrimE2 = BuildNewEdge(E2, V, newExtr2, Degen2);
222   if (Degen1 && Degen2 ) status = ChFi2d_BothEdgesDegenerated;
223   if (Degen1 && !Degen2 ) status = ChFi2d_FirstEdgeDegenerated;
224   if (!Degen1 && Degen2 ) status = ChFi2d_LastEdgeDegenerated;
225 //   TrimE1 = BuildNewEdge(E1, V, newExtr1);
226 //  TrimE2 = BuildNewEdge(E2, V, newExtr2);
227 } // ComputeChamfer
228
229
230 //=======================================================================
231 //function : ComputeChamfer
232 //purpose  : 
233 //=======================================================================
234
235 void ChFi2d_Builder::ComputeChamfer(const TopoDS_Vertex& V, 
236                                   const TopoDS_Edge& E1, 
237                                   const Standard_Real D,
238                                   const Standard_Real Ang,
239                                   const TopoDS_Edge& E2, 
240                                   TopoDS_Edge& TrimE1, 
241                                   TopoDS_Edge& TrimE2, 
242                                   TopoDS_Edge& Chamfer) 
243 {
244    TopoDS_Vertex newExtr1, newExtr2;
245    Standard_Boolean Degen1, Degen2;
246    Chamfer = BuildChamferEdge(V, E1, D, Ang, E2, newExtr1, newExtr2);
247    if ( status != ChFi2d_IsDone) return;
248   TrimE1 = BuildNewEdge(E1, V, newExtr1, Degen1);
249   TrimE2 = BuildNewEdge(E2, V, newExtr2, Degen2);
250   if (Degen1 && Degen2 ) status = ChFi2d_BothEdgesDegenerated;
251   if (Degen1 && !Degen2 ) status = ChFi2d_FirstEdgeDegenerated;
252   if (!Degen1 && Degen2 ) status = ChFi2d_LastEdgeDegenerated;
253 //   TrimE1 = BuildNewEdge(E1, V, newExtr1);
254 //   TrimE2 = BuildNewEdge(E2, V, newExtr2);
255 } // ComputeChamfer
256
257
258 //=======================================================================
259 //function : ModifyFillet
260 //purpose  : 
261 //=======================================================================
262
263 TopoDS_Edge ChFi2d_Builder::ModifyChamfer(const TopoDS_Edge& Chamfer, 
264                                         const TopoDS_Edge& E1, 
265                                         const TopoDS_Edge& E2,  
266                                         const Standard_Real D1,
267                                         const Standard_Real D2)
268 {
269   TopoDS_Vertex aVertex = RemoveChamfer(Chamfer);
270   TopoDS_Edge adjEdge1, adjEdge2;
271   status = ChFi2d::FindConnectedEdges(newFace, aVertex, adjEdge1, adjEdge2);
272   TopoDS_Edge aChamfer;
273   if (status == ChFi2d_ConnexionError) return aChamfer;
274
275   // adjEdge1 and adjEdge2 are copies of E1 and E2 with the good orientation
276   // on <newFace>
277   if (adjEdge1.IsSame(E2)) {
278     TopAbs_Orientation orient = adjEdge1.Orientation();
279     adjEdge1 = adjEdge2;
280     adjEdge2 = E2;
281     adjEdge2.Orientation(orient);
282   }
283
284   aChamfer = AddChamfer(adjEdge1, adjEdge2, D1, D2);
285   return aChamfer;
286 } // ModifyChamfer
287
288
289 //=======================================================================
290 //function : ModifyFillet
291 //purpose  : 
292 //=======================================================================
293
294 TopoDS_Edge ChFi2d_Builder::ModifyChamfer(const TopoDS_Edge& Chamfer, 
295                                         const TopoDS_Edge& E, 
296                                         const Standard_Real D,
297                                         const Standard_Real Ang)
298 {
299   TopoDS_Vertex aVertex = RemoveChamfer(Chamfer);
300   TopoDS_Edge adjEdge1, adjEdge2;
301   status = ChFi2d::FindConnectedEdges(newFace, aVertex, adjEdge1, adjEdge2);
302   TopoDS_Edge aChamfer;
303   if (status == ChFi2d_ConnexionError) return aChamfer;
304
305   if (adjEdge1.IsSame(E)) 
306     aChamfer = AddChamfer(adjEdge1, aVertex, D, Ang);
307   else aChamfer = AddChamfer(adjEdge2, aVertex, D, Ang);
308   return aChamfer;
309 } // ModifyChamfer
310
311
312 //=======================================================================
313 //function : RemoveChamfer
314 //purpose  : 
315 //=======================================================================
316
317 TopoDS_Vertex ChFi2d_Builder::RemoveChamfer(const TopoDS_Edge& Chamfer)
318 {
319   TopoDS_Vertex commonVertex;
320
321   Standard_Integer i = 1;
322   Standard_Integer IsFind = Standard_False;
323   while (i <= chamfers.Length()) {
324     const TopoDS_Edge& aChamfer = TopoDS::Edge(chamfers.Value(i));
325     if (aChamfer.IsSame(Chamfer)) {
326       chamfers.Remove(i);
327       IsFind = Standard_True;
328       break;
329     }
330     i++;
331   }
332   if (!IsFind) return commonVertex;
333
334   TopoDS_Vertex firstVertex, lastVertex;
335   TopExp::Vertices(Chamfer, firstVertex, lastVertex);
336
337
338   TopoDS_Edge adjEdge1, adjEdge2;
339   status = ChFi2d::FindConnectedEdges(newFace, firstVertex,
340                                      adjEdge1, adjEdge2);
341   if (status == ChFi2d_ConnexionError) return commonVertex;
342
343   TopoDS_Edge basisEdge1, basisEdge2, E1, E2;
344   // E1 and E2 are the adjacentes edges to Chamfer
345
346   if (adjEdge1.IsSame(Chamfer)) E1 = adjEdge2;
347   else E1 = adjEdge1;
348   basisEdge1 = BasisEdge(E1);
349   status = ChFi2d::FindConnectedEdges(newFace, lastVertex,adjEdge1, adjEdge2);
350   if (status == ChFi2d_ConnexionError) return commonVertex;
351   if (adjEdge1.IsSame(Chamfer)) E2 = adjEdge2;
352   else E2 = adjEdge1;
353   basisEdge2 = BasisEdge(E2);
354   TopoDS_Vertex connectionE1Chamfer, connectionE2Chamfer;
355   Standard_Boolean hasConnection = 
356     ChFi2d::CommonVertex(basisEdge1, basisEdge2, commonVertex);
357   if (!hasConnection) {
358     status = ChFi2d_ConnexionError;
359     return commonVertex;
360   }
361   hasConnection = ChFi2d::CommonVertex(E1, Chamfer, connectionE1Chamfer);
362   if (!hasConnection) {
363     status = ChFi2d_ConnexionError;
364     return commonVertex;
365   }
366   hasConnection = ChFi2d::CommonVertex(E2, Chamfer, connectionE2Chamfer);
367   if (!hasConnection) {
368     status = ChFi2d_ConnexionError;
369     return commonVertex;
370   }
371
372   // rebuild edges on wire
373   TopoDS_Edge newEdge1, newEdge2;
374   TopoDS_Vertex v, v1, v2;
375   BRepLib_MakeEdge makeEdge;
376   TopLoc_Location loc;
377   Standard_Real first, last;
378
379   TopExp::Vertices(E1, firstVertex, lastVertex);
380   TopExp::Vertices(basisEdge1, v1, v2);
381   if (v1.IsSame(commonVertex)) v = v2;
382   else v = v1;
383
384   if ( firstVertex.IsSame(v) || lastVertex.IsSame(v)) 
385     // It means the edge support only one fillet. In this case
386     // the new edge must be the basis edge.
387     newEdge1 = basisEdge1;
388   else {
389     // It means the edge support one fillet on each end.
390     if (firstVertex.IsSame(connectionE1Chamfer)) {
391 //  syntaxe invalide sur NT
392 //      const Handle(Geom_Curve)& curve = 
393 //      BRep_Tool::Curve(E1, loc, first, last);   
394       Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, loc, first, last);
395       makeEdge.Init(curve, commonVertex, lastVertex);  
396       newEdge1 = makeEdge.Edge();
397       newEdge1.Orientation(basisEdge1.Orientation());
398       newEdge1.Location(basisEdge1.Location());
399     } // if (firstVertex ...
400     else if (lastVertex.IsSame(connectionE1Chamfer)) { 
401 //  syntaxe invalide sur NT
402 //      const Handle(Geom_Curve)& curve = 
403 //      BRep_Tool::Curve(E1, loc, first, last);   
404       Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, loc, first, last);
405       makeEdge.Init(curve, firstVertex, commonVertex);
406       newEdge1 = makeEdge.Edge();
407       newEdge1.Orientation(basisEdge1.Orientation());
408       newEdge1.Location(basisEdge1.Location());
409     } // else if (lastVertex ...
410   } // else ...
411
412   TopExp::Vertices(basisEdge2, v1, v2);
413   if (v1.IsSame(commonVertex)) v = v2;
414   else v = v1;
415
416   TopExp::Vertices(E2, firstVertex, lastVertex);   
417   if ( firstVertex.IsSame(v) || lastVertex.IsSame(v)) 
418     // It means the edge support only one fillet. In this case
419     // the new edge must be the basis edge.
420     newEdge2 = basisEdge2;
421   else {
422     // It means the edge support one fillet on each end.
423     if (firstVertex.IsSame(connectionE2Chamfer)) {
424 //  syntaxe invalide sur NT
425 //      const Handle(Geom_Curve)& curve = 
426 //      BRep_Tool::Curve(E2, loc, first, last);   
427       Handle(Geom_Curve) curve = BRep_Tool::Curve(E2, loc, first, last);
428       makeEdge.Init(curve, commonVertex, lastVertex);
429       newEdge2 = makeEdge.Edge();
430       newEdge2.Orientation(basisEdge2.Orientation());
431       newEdge2.Location(basisEdge2.Location());
432     } // if (firstVertex ...
433     else if (lastVertex.IsSame(connectionE2Chamfer)) {
434 //  syntaxe invalide sur NT
435 //      const Handle(Geom_Curve)& curve = 
436 //      BRep_Tool::Curve(E2, loc, first, last);   
437       Handle(Geom_Curve) curve = BRep_Tool::Curve(E2, loc, first, last);
438       makeEdge.Init(curve, firstVertex, commonVertex);
439       newEdge2 = makeEdge.Edge();
440       newEdge2.Orientation(basisEdge2.Orientation());
441       newEdge2.Location(basisEdge2.Location());
442     } // else if (lastVertex ... 
443   } // else ...
444
445   // rebuild the newFace
446   TopExp_Explorer Ex(newFace, TopAbs_EDGE);
447   TopoDS_Wire newWire;
448
449   BRep_Builder B;
450   B.MakeWire(newWire);
451
452   while (Ex.More()) {
453     const TopoDS_Edge& theEdge = TopoDS::Edge(Ex.Current());
454     if (!theEdge.IsSame(E1) && 
455         !theEdge.IsSame(E2) && 
456         !theEdge.IsSame(Chamfer) )
457       B.Add(newWire, theEdge);
458     else {
459       if (theEdge == E1) 
460         B.Add(newWire, newEdge1);
461       else if (theEdge == E2)
462         B.Add(newWire, newEdge2);
463     } // else
464     Ex.Next();
465   } // while ...
466
467   BRepAdaptor_Surface Adaptor3dSurface(refFace);
468   BRepLib_MakeFace mFace(Adaptor3dSurface.Plane(), newWire);
469   newFace.Nullify();
470   newFace = mFace;
471
472   UpDateHistory(basisEdge1, basisEdge2, newEdge1, newEdge2);  
473
474   return commonVertex;
475 } // RemoveChamfer
476
477
478 //=======================================================================
479 //function : BuildChamferEdge
480 //purpose  : 
481 //=======================================================================
482 TopoDS_Edge ChFi2d_Builder::BuildChamferEdge(const TopoDS_Vertex& V, 
483                                            const TopoDS_Edge& AdjEdge1, 
484                                            const TopoDS_Edge& AdjEdge2, 
485                                            const Standard_Real D1,
486                                            const Standard_Real D2,
487                                            TopoDS_Vertex& NewExtr1,
488                                            TopoDS_Vertex& NewExtr2)
489 {
490   TopoDS_Edge chamfer;
491   if ( D1 <= 0 || D2 <= 0) {
492     status = ChFi2d_ParametersError;
493     return chamfer;
494   } // if ( D1 <=0 ...
495   
496   Standard_Real param1, param2;
497   gp_Pnt p1 = ComputePoint(V, AdjEdge1, D1, param1);
498   gp_Pnt p2 = ComputePoint(V, AdjEdge2, D2, param2);
499   
500   Standard_Real tol = Precision::Confusion();
501   BRep_Builder B;
502   B.MakeVertex(NewExtr1, p1, tol);
503   B.MakeVertex(NewExtr2, p2, tol);
504   NewExtr1.Orientation(TopAbs_FORWARD);
505   NewExtr2.Orientation(TopAbs_REVERSED);
506
507   // chamfer edge construction
508   TopLoc_Location loc;
509   const Handle(Geom_Surface) refSurf = BRep_Tool::Surface(refFace, loc);
510   gp_Vec myVec( p1, p2);
511   gp_Dir myDir(myVec);
512   Handle(Geom_Line) newLine = new Geom_Line( p1, myDir);
513   Standard_Real param = ElCLib::Parameter(newLine->Lin(), p2);
514   B.MakeEdge(chamfer, newLine, tol);
515   B.Range(chamfer,0., param);
516   B.Add(chamfer, NewExtr1);
517   B.UpdateVertex(NewExtr1,0., chamfer, tol);
518   B.Add(chamfer, NewExtr2);
519   B.UpdateVertex(NewExtr2,param, chamfer, tol);
520   OrientChamfer(chamfer, AdjEdge1, V);
521
522   // set the orientation of NewExtr1 and NewExtr2 for the adjacent edges
523   TopoDS_Vertex V1 = TopExp::FirstVertex(AdjEdge1);
524   TopoDS_Vertex V2 = TopExp::LastVertex(AdjEdge1);
525   if (V1.IsSame(V)) NewExtr1.Orientation(V1.Orientation());
526   else NewExtr1.Orientation(V2.Orientation());
527
528   V1 = TopExp::FirstVertex(AdjEdge2);
529   V2 = TopExp::LastVertex(AdjEdge2);
530   if (V1.IsSame(V)) NewExtr2.Orientation(V1.Orientation());
531   else NewExtr2.Orientation(V2.Orientation());
532   B.UpdateVertex(NewExtr1, param1, AdjEdge1, tol);
533   B.UpdateVertex(NewExtr2, param2, AdjEdge2, tol);
534
535   status = ChFi2d_IsDone;
536   return chamfer;
537 } // BuildChamferEdge
538
539
540 //=======================================================================
541 //function : BuildFilletEdge
542 //purpose  : 
543 //=======================================================================
544 TopoDS_Edge ChFi2d_Builder::BuildChamferEdge(const TopoDS_Vertex& V, 
545                                            const TopoDS_Edge& AdjEdge1, 
546                                            const Standard_Real D,
547                                            const Standard_Real Ang,
548                                            const TopoDS_Edge& AdjEdge2, 
549                                            TopoDS_Vertex& NewExtr1,
550                                            TopoDS_Vertex& NewExtr2)
551 {
552   TopoDS_Edge chamfer;
553   if ( D <= 0 || Ang <= 0) {
554     status = ChFi2d_ParametersError;
555     return chamfer;
556   } // if ( D <= 0 ...
557
558   Standard_Real param1, param2;
559   gp_Pnt p1 = ComputePoint(V, AdjEdge1, D, param1);
560   gp_Pnt p = BRep_Tool::Pnt(V);
561   gp_Vec myVec( p1, p);
562
563   // compute the tangent vector on AdjEdge2 at the vertex V.
564   BRepAdaptor_Curve c(AdjEdge2, refFace);
565   Standard_Real first, last;
566   first = c.FirstParameter();
567   last = c.LastParameter();
568
569   gp_Pnt aPoint;
570   gp_Vec tan;
571   c.D1(first, aPoint, tan);
572   if (aPoint.Distance(p) > Precision::Confusion()) {
573     c.D1(last, aPoint, tan);
574   }
575   // tangent orientation
576   TopoDS_Vertex v1, v2;
577   TopExp::Vertices(AdjEdge2, v1, v2);
578   TopAbs_Orientation orient;
579   if (v1.IsSame(V)) orient = v1.Orientation();
580   else orient = v2.Orientation();
581   if (orient == TopAbs_REVERSED) tan *= -1;
582
583   // compute the chamfer geometric support 
584   gp_Ax1 RotAxe(p1, tan^myVec);
585   gp_Vec vecLin = myVec.Rotated(RotAxe, -Ang);
586   gp_Dir myDir(vecLin);
587   Handle(Geom_Line) newLine = new Geom_Line( p1, myDir);
588   BRep_Builder B1;
589   B1.MakeEdge(chamfer, newLine, Precision::Confusion());
590   gp_Pnt p2 = ComputePoint(refFace, newLine, AdjEdge2, param2);
591
592
593   Standard_Real tol = Precision::Confusion();
594   BRep_Builder B;
595   B.MakeVertex(NewExtr1, p1, tol);
596   B.MakeVertex(NewExtr2, p2, tol);
597   NewExtr1.Orientation(TopAbs_FORWARD);
598   NewExtr2.Orientation(TopAbs_REVERSED);
599
600   // chamfer edge construction
601   Standard_Real param = ElCLib::Parameter(newLine->Lin(), p2);
602   B.MakeEdge(chamfer, newLine, tol);
603   B.Range(chamfer,0., param);
604   B.Add(chamfer, NewExtr1);
605   B.UpdateVertex(NewExtr1,0., chamfer, tol);
606   B.Add(chamfer, NewExtr2);
607   B.UpdateVertex(NewExtr2,param, chamfer, tol);
608   OrientChamfer(chamfer, AdjEdge1, V);
609
610   // set the orientation of NewExtr1 and NewExtr2 for the adjacent edges
611   TopoDS_Vertex V1 = TopExp::FirstVertex(AdjEdge1);
612   TopoDS_Vertex V2 = TopExp::LastVertex(AdjEdge1);
613   if (V1.IsSame(V)) NewExtr1.Orientation(V1.Orientation());
614   else NewExtr1.Orientation(V2.Orientation());
615
616   V1 = TopExp::FirstVertex(AdjEdge2);
617   V2 = TopExp::LastVertex(AdjEdge2);
618   if (V1.IsSame(V)) NewExtr2.Orientation(V1.Orientation());
619   else NewExtr2.Orientation(V2.Orientation());
620   B.UpdateVertex(NewExtr1, param1, AdjEdge1, tol);
621   B.UpdateVertex(NewExtr2, param2, AdjEdge2, tol);
622
623   status = ChFi2d_IsDone;
624   return chamfer;
625 }
626
627
628 //=======================================================================
629 //function : ComputePoint
630 //purpose  : 
631 //=======================================================================
632
633 gp_Pnt ComputePoint(const TopoDS_Vertex& V,const TopoDS_Edge& E, 
634                     const Standard_Real D, Standard_Real& Param)
635 {
636   // geometric support
637   BRepAdaptor_Curve c(E);
638   Standard_Real first, last;
639   first = c.FirstParameter();
640   last = c.LastParameter();
641
642   gp_Pnt thePoint;
643   if (c.GetType() == GeomAbs_Line) {
644     gp_Pnt p1, p2;
645     TopoDS_Vertex v1, v2;
646     TopExp::Vertices(E, v1, v2);
647     p1 = BRep_Tool::Pnt(v1);
648     p2 = BRep_Tool::Pnt(v2);
649     gp_Vec myVec( p1, p2);
650     myVec.Normalize();
651     myVec *= D;
652     if (v2.IsSame(V)) {
653       myVec *= -1; // change the sense of myVec
654       thePoint = p2.Translated(myVec);
655     } // if (v2 ...
656     else thePoint = p1.Translated(myVec);
657
658     Param = ElCLib::Parameter(c.Line(), thePoint);
659         //szv:OCC20823-begin
660     c.D0(Param, thePoint);
661         //szv:OCC20823-end
662     return thePoint;
663   } // if (C->IsKind(TYPE ...
664
665   if (c.GetType() == GeomAbs_Circle) {
666     gp_Circ cir = c.Circle();
667     Standard_Real radius = cir.Radius();
668     TopoDS_Vertex v1, v2;
669     TopExp::Vertices(E, v1, v2);
670     Standard_Real param1,param2;
671     if (V.IsSame(v1)) {
672       param1 = BRep_Tool::Parameter(v1,E);
673       param2 = BRep_Tool::Parameter(v2,E);
674     }
675     else {
676       param1 = BRep_Tool::Parameter(v2,E);
677       param2 = BRep_Tool::Parameter(v1,E);
678     }     
679     Standard_Real deltaAlpha = D/radius;
680     if (param1 > param2) Param = param1 - deltaAlpha;
681     else Param = param1 + deltaAlpha;
682     c.D0(Param, thePoint);
683     return thePoint;
684   } // if (C->IsKind(TYPE ...  
685
686   else {
687     // in all other case than lines and circles.
688     gp_Pnt p;
689     TopoDS_Vertex v1, v2;
690     TopExp::Vertices(E, v1, v2);
691     if (V.IsSame(v1)) {
692       p = BRep_Tool::Pnt(v1);
693     }
694     else {
695       p = BRep_Tool::Pnt(v2);
696     }     
697
698     GeomAdaptor_Curve cc = c.Curve();
699     if (p.Distance(c.Value(first)) <= Precision::Confusion()) {
700       GCPnts_AbscissaPoint computePoint(cc, D, first);
701       Param = computePoint.Parameter();
702     }
703     else {
704       GCPnts_AbscissaPoint computePoint(cc, D, last);
705       Param = computePoint.Parameter();
706     }
707     thePoint = cc.Value(Param);
708     return thePoint;
709   } // else ...
710   return thePoint;
711 } // ComputePoint
712
713
714
715 //=======================================================================
716 //function : ComputePoint
717 //purpose  : 
718 //=======================================================================
719
720 gp_Pnt ComputePoint(const TopoDS_Face& F, 
721                     const Handle(Geom_Line)& L,
722                     const TopoDS_Edge& E, 
723                     Standard_Real& Param)
724 {
725   BRepAdaptor_Surface Adaptor3dSurface(F);
726   Handle(Geom_Plane) refSurf = new Geom_Plane(Adaptor3dSurface.Plane());
727   Handle(Geom2d_Curve) lin2d = GeomAPI::To2d(L, refSurf->Pln());
728   Handle(Geom2d_Curve) c2d;
729   Standard_Real first, last;
730   c2d = BRep_Tool::CurveOnSurface(E, F, first, last);
731   Geom2dAdaptor_Curve adaptorL(lin2d);
732   Geom2dAdaptor_Curve adaptorC(c2d);
733   Geom2dInt_GInter Intersection(adaptorL, adaptorC,
734                                 Precision::PIntersection(),
735                                 Precision::PIntersection());
736   Standard_Real paramOnLine = 1E300;
737   gp_Pnt2d p2d;
738   if (Intersection.IsDone()) {
739     Standard_Integer i = 1;
740     while ( i <= Intersection.NbPoints()) {
741       IntRes2d_IntersectionPoint iP = Intersection.Point(i);
742       if (iP.ParamOnFirst() < paramOnLine) {
743         p2d = iP.Value();
744         paramOnLine = iP.ParamOnFirst();
745         Param = iP.ParamOnSecond();
746       } // if (iP.ParamOnFirst ...
747       i++;
748     } // while ( i <= ... 
749   } // if (Intersection.IsDone ...
750
751   gp_Pnt thePoint = Adaptor3dSurface.Value(p2d.X(), p2d.Y());  
752   return thePoint;
753 } // ComputePoint
754
755 //=======================================================================
756 //function : OrientChamfer
757 //purpose  : 
758 //=======================================================================
759
760 void OrientChamfer(TopoDS_Edge& chamfer,
761                    const TopoDS_Edge& E,
762                    const TopoDS_Vertex& V)
763
764   TopAbs_Orientation vOrient, orient = E.Orientation();
765   TopoDS_Vertex v1, v2;
766   TopExp::Vertices(E, v1, v2);
767   if (v1.IsSame(V)) vOrient = v2.Orientation();
768   else vOrient = v1.Orientation();
769
770   if ((orient == TopAbs_FORWARD && vOrient == TopAbs_FORWARD) ||
771       (orient == TopAbs_REVERSED && vOrient == TopAbs_REVERSED))
772     chamfer.Orientation(TopAbs_FORWARD);
773   else chamfer.Orientation(TopAbs_REVERSED);
774 } // OrientChamfer
775
776
777 //=======================================================================
778 //function : IsLineOrCircle
779 //purpose  : 
780 //=======================================================================
781
782 Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E,
783                                 const TopoDS_Face& F) 
784 {
785   Standard_Real first, last;
786   TopLoc_Location loc;
787 //  syntaxe invalide sur NT
788 //      const Handle(Geom2d_Curve)& C = 
789 //      BRep_Tool::CurveOnSurface(E,F,first,last);   
790   Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,first,last);
791   Handle(Geom2d_Curve) basisC; 
792   Handle(Geom2d_TrimmedCurve) TC = Handle(Geom2d_TrimmedCurve)::DownCast(C);
793   if (!TC.IsNull())
794     basisC = Handle(Geom2d_Curve)::DownCast(TC->BasisCurve());
795   else
796     basisC = Handle(Geom2d_Curve)::DownCast(C);
797
798   if ( basisC->DynamicType() == STANDARD_TYPE(Geom2d_Circle)
799       || basisC->DynamicType() == STANDARD_TYPE(Geom2d_Line) ) {
800     return Standard_True;
801   }
802   else {
803     return Standard_False;
804   } // else ...
805 } // IsLineOrCircle