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