0022368: AIS_Trihedron's highlight presentation isn't updated on trihedron relocation
[occt.git] / src / AIS / AIS.cxx
1 // File:        AIS.cxx
2 // Created:     Wed Dec 11 11:16:37 1996
3 // Author:      Robert COUBLANC
4 //              <rob@robox.paris1.matra-dtv.fr>
5
6
7 #include <AIS.ixx>
8
9 #include <Adaptor3d_HCurve.hxx>
10 #include <Adaptor3d_HSurface.hxx>
11
12 #include <BRepBuilderAPI_MakeEdge.hxx>
13 #include <BRepBuilderAPI_MakeVertex.hxx>
14 #include <BRepAdaptor_Curve.hxx>
15 #include <BRepAdaptor_HSurface.hxx>
16 #include <BRepAdaptor_Surface.hxx>
17 #include <BRepTopAdaptor_FClass2d.hxx>
18 #include <BRep_Tool.hxx>
19 #include <Bnd_Box.hxx>
20
21 #include <ElCLib.hxx>
22 #include <ElSLib.hxx>
23
24 #include <GccEnt_QualifiedLin.hxx>
25 #include <Geom2d_Circle.hxx>
26 #include <GeomAPI_ExtremaCurveCurve.hxx>
27 #include <GeomAPI_ProjectPointOnSurf.hxx>
28 #include <GeomLib.hxx>
29 #include <GeomProjLib.hxx>
30 #include <GeomProjLib.hxx>
31 #include <Geom_CartesianPoint.hxx>
32 #include <Geom_Circle.hxx>
33 #include <Geom_ConicalSurface.hxx>
34 #include <Geom_Curve.hxx>
35 #include <Geom_CylindricalSurface.hxx>
36 #include <Geom_Ellipse.hxx>
37 #include <Geom_Line.hxx>
38 #include <Geom_OffsetSurface.hxx>
39 #include <Geom_Plane.hxx>
40 #include <Geom_SphericalSurface.hxx>
41 #include <Geom_SurfaceOfLinearExtrusion.hxx>
42 #include <Geom_SurfaceOfRevolution.hxx>
43 #include <Geom_ToroidalSurface.hxx>
44 #include <Geom_TrimmedCurve.hxx>
45 #include <Precision.hxx>
46 #include <Prs3d_LineAspect.hxx>
47 #include <Prs3d_PointAspect.hxx>
48 #include <StdPrs_Point.hxx>
49 #include <StdPrs_WFDeflectionShape.hxx>
50 #include <TColStd_Array1OfReal.hxx>
51 #include <TColStd_Array2OfReal.hxx>
52 #include <TopExp.hxx>
53 #include <TopExp_Explorer.hxx>
54 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
55 #include <TopoDS.hxx>
56 #include <gce_MakeLin.hxx>
57 #include <gp_Ax1.hxx>
58 #include <gp_Ax3.hxx>
59 #include <gp_Dir.hxx>
60 #include <gp_Elips.hxx>
61 #include <gp_Lin.hxx>
62 #include <gp_Pln.hxx>
63 #include <gp_Pnt.hxx>
64 #include <gp_Vec.hxx>
65 #include <gp_XYZ.hxx>
66
67 const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
68
69 //=======================================================================
70 //function : Nearest
71 //purpose  :
72 //=======================================================================
73
74 gp_Pnt AIS::Nearest(const TopoDS_Shape& ashape, const gp_Pnt& apoint)
75 {
76   Standard_Real dist2 = RealLast();
77   Standard_Real curdist2;
78   gp_Pnt result(0.0,0.0,0.0);
79   gp_Pnt curpnt(0.0,0.0,0.0);
80   TopExp_Explorer explo(ashape,TopAbs_VERTEX);
81   while (explo.More())
82     {
83       curpnt = BRep_Tool::Pnt(TopoDS::Vertex(explo.Current()));
84       curdist2 = apoint.SquareDistance(curpnt);
85       if (curdist2 < dist2)
86         {
87           result = curpnt;
88           dist2 = curdist2;
89         }
90       explo.Next();
91     }
92   return result;
93 }
94
95 //=======================================================================
96 //function : Farest
97 //purpose  :
98 //=======================================================================
99
100 gp_Pnt AIS::Farest( const TopoDS_Shape& aShape, const gp_Pnt& aPoint )
101 {
102   Standard_Real MaxDist2 = 0.0e0, curdist2;
103   gp_Pnt Result(0.0,0.0,0.0);
104   gp_Pnt curpnt(0.0,0.0,0.0);
105   TopExp_Explorer Explo( aShape, TopAbs_VERTEX );
106   for (; Explo.More(); Explo.Next())
107     {
108       curpnt = BRep_Tool::Pnt( TopoDS::Vertex( Explo.Current() ) );
109       curdist2 = aPoint.SquareDistance( curpnt );
110       if (curdist2 > MaxDist2)
111         {
112           MaxDist2 = curdist2;
113           Result = curpnt;
114         }
115     }
116   return Result;
117 }
118
119
120 //=======================================================================
121 //function : ComputeGeometry
122 //purpose  : for line, circle, ellipse 
123 //=======================================================================
124
125 Standard_Boolean AIS::ComputeGeometry(const TopoDS_Edge& anEdge,
126                                       Handle(Geom_Curve)& aCurve,
127                                       gp_Pnt& FirstPnt,
128                                       gp_Pnt& LastPnt)
129 {
130   TopLoc_Location loc_edge;
131   Standard_Real first,last;
132   aCurve = BRep_Tool::Curve(anEdge,loc_edge,first,last);
133   if (aCurve.IsNull()) return Standard_False;
134   if (!loc_edge.IsIdentity()) {
135 //#ifndef DEB
136     Handle(Geom_Geometry) aGeomGeometry = aCurve->Transformed(loc_edge.Transformation());
137     aCurve = (Handle(Geom_Curve)&) aGeomGeometry ;
138 //#else
139 //    aCurve = (Handle(Geom_Curve)&) aCurve->Transformed(loc_edge.Transformation());
140 //#endif
141   }
142   if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
143     aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
144   }
145
146   if (aCurve->IsInstance(STANDARD_TYPE(Geom_Line))) {
147     // CLE
148     // const Handle(Geom_Line)& line = (Handle(Geom_Line)&) aCurve;
149     Handle(Geom_Line) line = (Handle(Geom_Line)&) aCurve;
150     // ENDCLE
151
152     FirstPnt = ElCLib::Value(first,line->Lin());
153     LastPnt = ElCLib::Value(last,line->Lin());
154   }
155   else if (aCurve->IsInstance(STANDARD_TYPE(Geom_Circle))) {
156     // CLE
157     // const Handle(Geom_Circle)& circ = (Handle(Geom_Circle)&) aCurve;
158     Handle(Geom_Circle) circ = (Handle(Geom_Circle)&) aCurve;
159     // ENDCLE
160     FirstPnt = ElCLib::Value(first,circ->Circ());
161     LastPnt = ElCLib::Value(last,circ->Circ());
162   }
163   else if (aCurve->IsInstance(STANDARD_TYPE(Geom_Ellipse))) {
164     // CLE
165     // const Handle(Geom_Ellipse)& elips = (Handle(Geom_Ellipse)&) aCurve;
166     Handle(Geom_Ellipse) elips = (Handle(Geom_Ellipse)&) aCurve;
167     // ENDCLE
168     FirstPnt = ElCLib::Value(first, elips->Elips());
169     LastPnt = ElCLib::Value(last, elips->Elips());
170   }
171   else return Standard_False;
172   return Standard_True;
173 }
174
175 //=======================================================================
176 //function : ComputeGeometry
177 //purpose  :
178 //=======================================================================
179
180 Standard_Boolean AIS::ComputeGeometry(const TopoDS_Edge& anEdge,
181                                       Handle(Geom_Curve)& aCurve,
182                                       gp_Pnt& FirstPnt,
183                                       gp_Pnt& LastPnt,
184                                       Handle(Geom_Curve)& extCurve,
185                                       Standard_Boolean& isInfinite,
186                                       Standard_Boolean& isOnPlane,
187                                       const Handle(Geom_Plane)& aPlane)
188 {
189   if (aPlane.IsNull()) return Standard_False;
190
191   Standard_Real first,last;
192   BRepAdaptor_Curve brepCurv(anEdge);
193   aCurve = Handle(Geom_Curve)::DownCast(brepCurv.Curve().Curve()->Transformed(brepCurv.Trsf()));
194   first = brepCurv.FirstParameter();
195   last = brepCurv.LastParameter();
196
197   if (aCurve.IsNull()) return Standard_False;
198   
199   extCurve = aCurve;
200   isInfinite = (Precision::IsInfinite(first) || Precision::IsInfinite(last));
201
202   // Checks that the projcurve is not in the plane
203   isOnPlane = Standard_True;
204   if (extCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
205     extCurve = ((Handle(Geom_TrimmedCurve)&) extCurve)->BasisCurve();
206   }
207
208   if ( extCurve->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
209     // CLE
210     // const Handle(Geom_Line) & gl = (Handle(Geom_Line)&) extCurve;
211     Handle(Geom_Line) gl = (Handle(Geom_Line)&) extCurve;
212     // ENDCLE
213     isOnPlane = aPlane->Pln().Contains( gl->Lin(), Precision::Confusion(), Precision::Angular() );
214   }
215   else if (extCurve->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
216     // CLE
217     // const Handle(Geom_Circle) & gc = (Handle(Geom_Circle)&) extCurve;
218     Handle(Geom_Circle) gc = (Handle(Geom_Circle)&) extCurve;
219     // ENDCLE
220     gp_Ax3 ax(gc->Position());
221     isOnPlane = ax.IsCoplanar(aPlane->Pln().Position(),
222                               Precision::Confusion(),
223                               Precision::Angular());
224   }
225   if ( isOnPlane ) {
226     extCurve.Nullify();
227   }
228   
229 //#ifndef DEB
230   Handle(Geom_Curve) aGeomCurve = GeomProjLib::ProjectOnPlane(aCurve,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
231   aCurve = aGeomCurve ;
232 //#else
233 //  aCurve = (Handle(Geom_Curve)&) GeomProjLib::ProjectOnPlane(aCurve,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
234 //#endif
235   
236   if (aCurve->IsInstance(STANDARD_TYPE(Geom_Line))) {
237     // CLE
238     // const Handle(Geom_Line)& line = (Handle(Geom_Line)&) aCurve;
239     Handle(Geom_Line) line = (Handle(Geom_Line)&) aCurve;
240     // EDNCLE
241     if (!isInfinite) {
242       FirstPnt = ElCLib::Value(first,line->Lin());
243       LastPnt = ElCLib::Value(last,line->Lin());
244     }
245   }
246   else if (aCurve->IsInstance(STANDARD_TYPE(Geom_Circle))) {
247     // CLE
248     // const Handle(Geom_Circle)& circ = (Handle(Geom_Circle)&) aCurve;
249     Handle(Geom_Circle) circ = (Handle(Geom_Circle)&) aCurve;
250     // ENDCLE
251     FirstPnt = ElCLib::Value(first,circ->Circ());
252     LastPnt = ElCLib::Value(last,circ->Circ());
253   }
254   // jfa 10/10/2000
255   else if (aCurve->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
256     {
257       Handle(Geom_Ellipse) ell = (Handle(Geom_Ellipse)&) aCurve;
258       FirstPnt = ElCLib::Value(first,ell->Elips());
259       LastPnt = ElCLib::Value(last,ell->Elips());
260     }
261   // jfa 10/10/2000 end
262   else return Standard_False;
263   return Standard_True;
264 }
265
266 //=======================================================================
267 //function : ComputeGeometry
268 //purpose  :
269 //=======================================================================
270
271 Standard_Boolean AIS::ComputeGeometry(const TopoDS_Edge& anEdge1,
272                                       const TopoDS_Edge& anEdge2,
273                                       Handle(Geom_Curve)& aCurve1,
274                                       Handle(Geom_Curve)& aCurve2,
275                                       gp_Pnt& FirstPnt1,
276                                       gp_Pnt& LastPnt1,
277                                       gp_Pnt& FirstPnt2,
278                                       gp_Pnt& LastPnt2,
279                                       const Handle(Geom_Plane)& aPlane)
280 {
281   if (aPlane.IsNull()) return Standard_False;
282
283   TopLoc_Location loc_edge1,loc_edge2;
284   Standard_Real first1,last1,first2,last2;
285   
286   aCurve1 = BRep_Tool::Curve(anEdge1,loc_edge1,first1,last1);
287   aCurve2 = BRep_Tool::Curve(anEdge2,loc_edge2,first2,last2);
288
289   if (aCurve1.IsNull()) return Standard_False;
290   if (aCurve2.IsNull()) return Standard_False;
291   
292   if (!loc_edge1.IsIdentity()) {
293 //#ifndef DEB
294     Handle(Geom_Geometry) aGeomGeometry = aCurve1->Transformed(loc_edge1.Transformation());
295     aCurve1 = (Handle(Geom_Curve)&) aGeomGeometry ;
296 //#else
297 //    aCurve1 = (Handle(Geom_Curve)&) aCurve1->Transformed(loc_edge1.Transformation());
298 //#endif
299   }
300   if (!loc_edge2.IsIdentity()) {
301 //#ifndef DEB
302     Handle(Geom_Geometry) aGeomGeometry = aCurve2->Transformed(loc_edge2.Transformation());
303     aCurve2 = (Handle(Geom_Curve)&) aGeomGeometry ;
304 //#else
305 //    aCurve2 = (Handle(Geom_Curve)&) aCurve2->Transformed(loc_edge2.Transformation());
306 //#endif
307   }
308
309 //#ifndef DEB
310   Handle(Geom_Curve) aGeomCurve = GeomProjLib::ProjectOnPlane(aCurve1,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
311   aCurve1 = aGeomCurve ;
312 //#else
313 //  aCurve1 =  (Handle(Geom_Curve)&) GeomProjLib::ProjectOnPlane(aCurve1,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
314 //#endif
315 //#ifndef DEB
316   aGeomCurve = GeomProjLib::ProjectOnPlane(aCurve2,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
317   aCurve2 = aGeomCurve;
318 //#else
319 //  aCurve2 =  (Handle(Geom_Curve)&) GeomProjLib::ProjectOnPlane(aCurve2,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
320 //#endif
321
322   if (aCurve1->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
323     aCurve1 = ((Handle(Geom_TrimmedCurve)&) aCurve1)->BasisCurve();
324   }
325   if (aCurve2->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
326     aCurve2 = ((Handle(Geom_TrimmedCurve)&) aCurve2)->BasisCurve();
327   }
328
329   if (aCurve1->IsInstance(STANDARD_TYPE(Geom_Line))) {
330     // CLE
331     // const Handle(Geom_Line)& line = (Handle(Geom_Line)&) aCurve1;
332     Handle(Geom_Line) line = (Handle(Geom_Line)&) aCurve1;
333     // ENDCLE
334     FirstPnt1 = ElCLib::Value(first1,line->Lin());
335     LastPnt1 = ElCLib::Value(last1,line->Lin());
336   }
337   else if (aCurve1->IsInstance(STANDARD_TYPE(Geom_Circle))) {
338     // CLE
339     // const Handle(Geom_Circle)& circ = (Handle(Geom_Circle)&) aCurve1;
340     Handle(Geom_Circle) circ = (Handle(Geom_Circle)&) aCurve1;
341     // ENDCLE
342     FirstPnt1 = ElCLib::Value(first1,circ->Circ());
343     LastPnt1 = ElCLib::Value(last1,circ->Circ());
344   }
345   else return Standard_False;
346
347   if (aCurve2->IsInstance(STANDARD_TYPE(Geom_Line))) {
348     // CLE
349     // const Handle(Geom_Line)& line = (Handle(Geom_Line)&) aCurve2;
350     Handle(Geom_Line) line = (Handle(Geom_Line)&) aCurve2;
351     // ENDCLE
352     FirstPnt2 = ElCLib::Value(first2,line->Lin());
353     LastPnt2 = ElCLib::Value(last2,line->Lin());
354   }
355   else if (aCurve2->IsInstance(STANDARD_TYPE(Geom_Circle))) {
356     // CLE
357     // const Handle(Geom_Circle)& circ = (Handle(Geom_Circle)&) aCurve2;
358     Handle(Geom_Circle) circ = (Handle(Geom_Circle)&) aCurve2;
359     // ENDCLE
360     FirstPnt2 = ElCLib::Value(first2,circ->Circ());
361     LastPnt2 = ElCLib::Value(last2,circ->Circ());
362   }
363   else return Standard_False;
364
365   return Standard_True;
366 }
367
368 //=======================================================================
369 //function : ComputeGeometry
370 //purpose  : Computes the geometry of the 2 edges in the current wp
371 //           and the 'rigth' geometry of the edges if one doesn't
372 //           belong to the currentworkingplane.
373 //           There may be only one curve that can't belong to the
374 //           current workingplane ( attachement constraint)
375 //           if the 2 edges belong to the current WP, <WhatProj> = 0
376 //
377 //           indexExt = 0 2 edges are in the current wp
378 //           indexExt = 1 first edge is not in the current wp
379 //           indexExt = 2 second edge is not in the current wp
380 //           if none of the two edges is in the current wp ,
381 //           it returns Standard_False
382 //=======================================================================
383
384 Standard_Boolean AIS::ComputeGeometry(const TopoDS_Edge& anEdge1, 
385                                       const TopoDS_Edge& anEdge2, 
386                                       Standard_Integer& indexExt, 
387                                       Handle(Geom_Curve)& aCurve1, 
388                                       Handle(Geom_Curve)& aCurve2, 
389                                       gp_Pnt& FirstPnt1, 
390                                       gp_Pnt& LastPnt1, 
391                                       gp_Pnt& FirstPnt2, 
392                                       gp_Pnt& LastPnt2, 
393                                       Handle(Geom_Curve)& extCurve,
394                                       Standard_Boolean& isInfinite1,
395                                       Standard_Boolean& isInfinite2,                                  
396                                       const Handle(Geom_Plane)& aPlane)
397 {
398   if (aPlane.IsNull()) return Standard_False;
399   extCurve.Nullify();
400   indexExt = 0;
401
402   Standard_Real first1,last1,first2,last2;
403   isInfinite1 = isInfinite2 = Standard_False;
404
405   BRepAdaptor_Curve brepCurv1(anEdge1);
406   BRepAdaptor_Curve brepCurv2(anEdge2);
407   aCurve1 = Handle(Geom_Curve)::DownCast(brepCurv1.Curve().Curve()->Transformed(brepCurv1.Trsf()));
408   aCurve2 = Handle(Geom_Curve)::DownCast(brepCurv2.Curve().Curve()->Transformed(brepCurv2.Trsf()));
409   if (aCurve1->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
410     aCurve1 = ((Handle(Geom_TrimmedCurve)&) aCurve1)->BasisCurve();
411   }
412   if (aCurve2->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
413     aCurve2 = ((Handle(Geom_TrimmedCurve)&) aCurve2)->BasisCurve();
414   }
415
416   first1 = brepCurv1.FirstParameter();
417   last1 = brepCurv1.LastParameter();
418   first2 = brepCurv2.FirstParameter();
419   last2 = brepCurv2.LastParameter();
420
421   if (aCurve1.IsNull()) return Standard_False;
422   if (aCurve2.IsNull()) return Standard_False;
423   
424   Handle(Geom_Curve) aSov1 = aCurve1;
425   Handle(Geom_Curve) aSov2 = aCurve2;
426  
427   // Checks that the projcurve is not in the plane
428   Standard_Boolean isOnPlanC1,isOnPlanC2;
429   if ((!ComputeGeomCurve(aCurve1,first1,last1,FirstPnt1,LastPnt1,aPlane,isOnPlanC1))
430       || (!ComputeGeomCurve(aCurve2,first2,last2,FirstPnt2,LastPnt2,aPlane,isOnPlanC2)))
431     return Standard_False;
432   
433   if (Precision::IsInfinite(first1) || Precision::IsInfinite(last1)) {
434     isInfinite1 = Standard_True;
435     indexExt = 1;
436   }
437   if (Precision::IsInfinite(first2) || Precision::IsInfinite(last2)) {
438     isInfinite2 = Standard_True;    
439     indexExt = 2;
440   }
441   if (isInfinite1 && isInfinite2) indexExt = 0;  //New
442
443   if (isInfinite1 || isInfinite2) {
444     if (aCurve1->DynamicType() == aCurve2->DynamicType()) {
445       // CLE
446       // const gp_Lin& lin1 = ((Handle(Geom_Line)&) aCurve1)->Lin();
447       // const gp_Lin& lin2 = ((Handle(Geom_Line)&) aCurve2)->Lin();
448       gp_Lin lin1 = ((Handle(Geom_Line)&) aCurve1)->Lin();
449       gp_Lin lin2 = ((Handle(Geom_Line)&) aCurve2)->Lin();
450       // ENDCLE
451       if (indexExt == 1) {
452         FirstPnt1 = ElCLib::Value(ElCLib::Parameter(lin2,FirstPnt2),lin1);
453         LastPnt1 = ElCLib::Value(ElCLib::Parameter(lin2,LastPnt2),lin1);
454       }
455       else if (indexExt == 2) {
456         FirstPnt2 = ElCLib::Value(ElCLib::Parameter(lin1,FirstPnt1),lin2);
457         LastPnt2 = ElCLib::Value(ElCLib::Parameter(lin1,LastPnt1),lin2);
458       }
459     }
460   }
461
462   if (isOnPlanC1 && isOnPlanC2) return Standard_True;
463
464   if (!isOnPlanC1 && isOnPlanC2) {// courbe 2 seulement dans le plan
465     indexExt = 1;
466     extCurve = aSov1;
467   }
468   else if (isOnPlanC1 && !isOnPlanC2) {// courbe 1 seulement dans le plan
469     indexExt = 2;
470     extCurve = aSov2;
471   }
472   else
473     return Standard_False;
474   
475   return Standard_True;
476 }
477
478
479 // it is patch!
480
481 //=======================================================================
482 //function : ComputeGeomCurve
483 //purpose  : Checks if aCurve belongs to aPlane; if not, projects aCurve in aPlane
484 //           and returns aCurveproj;
485 //           Return TRUE if ok
486 //=======================================================================
487
488 Standard_Boolean AIS::ComputeGeomCurve(Handle(Geom_Curve)& aCurve,
489                                           const Standard_Real first1,
490                                           const Standard_Real last1,
491                                           gp_Pnt& FirstPnt1,
492                                           gp_Pnt& LastPnt1,
493                                           const Handle(Geom_Plane)& aPlane,
494                                           Standard_Boolean& isOnPlane)
495 {
496   isOnPlane = Standard_True;
497
498   const Standard_Integer NodeNumber = 20;
499   Standard_Real Delta = (last1 - first1) / (NodeNumber - 1);
500   if (Delta <= Precision::PConfusion())
501     Delta = last1 - first1;
502   gp_Pnt CurPnt(0.0,0.0,0.0);
503   Standard_Real CurPar = first1;
504   for (Standard_Integer i = 1; i <= NodeNumber; i++)
505     {
506       CurPnt = aCurve->Value( CurPar );
507       if (aPlane->Pln().SquareDistance( CurPnt ) > SquareTolerance)
508         {
509           isOnPlane = Standard_False;
510           break;
511         }
512       CurPar += Delta;
513     }
514   
515   if (! Precision::IsInfinite(first1) && ! Precision::IsInfinite(last1))
516     {
517       FirstPnt1 = aCurve->Value( first1 );
518       LastPnt1  = aCurve->Value( last1 );
519     }
520   if (!isOnPlane) {
521 //#ifndef DEB
522     Handle( Geom_Curve ) aGeomCurve = GeomProjLib::ProjectOnPlane( aCurve,
523                                                                    aPlane,
524                                                                    aPlane->Pln().Axis().Direction(),
525                                                                    Standard_False);
526     aCurve = aGeomCurve ;
527 //#else
528 //    aCurve =  (Handle( Geom_Curve )&) GeomProjLib::ProjectOnPlane( aCurve,
529 //                                                                 aPlane,
530 //                                                                 aPlane->Pln().Axis().Direction(),
531 //                                                                 Standard_False);
532 //#endif
533     if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
534       aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
535     }
536     if (! Precision::IsInfinite(first1) && ! Precision::IsInfinite(last1)) {
537       FirstPnt1 = AIS::ProjectPointOnPlane( FirstPnt1, aPlane->Pln() );
538       LastPnt1 = AIS::ProjectPointOnPlane( LastPnt1, aPlane->Pln() );
539     }
540   }
541   return Standard_True;
542 }
543
544
545 //=======================================================================
546 //function : ComputeGeometry
547 //purpose  : computes the point corresponding to the vertex <aVertex>
548 //           in the plane <aPlane>. If the vertex is already in the plane
549 //           <isOnPlane>, <isOnPlane> = true.
550 //           <point> is the projected vertex in the plane.
551 //=======================================================================
552
553 Standard_Boolean  AIS::ComputeGeometry(const TopoDS_Vertex& aVertex,
554                                        gp_Pnt& point,
555                                        const Handle(Geom_Plane)& aPlane,
556                                        Standard_Boolean& isOnPlane)
557 {
558   point = BRep_Tool::Pnt(aVertex);
559   isOnPlane = aPlane->Pln().Contains(point,  Precision::Confusion());
560   if ( !isOnPlane) {
561     point = AIS::ProjectPointOnPlane( point, aPlane->Pln() );
562   }
563   return Standard_True;
564 }
565
566 //=======================================================================
567 //function : GetPlaneFromFace
568 //purpose  :
569 //           Returns type of surface which can be Plane or OtherSurface
570 //=======================================================================
571
572 Standard_Boolean AIS::GetPlaneFromFace( const TopoDS_Face&            aFace,
573                                         gp_Pln &                     aPlane,
574                                         Handle( Geom_Surface )&      aSurf,
575                                         AIS_KindOfSurface &          aSurfType,
576                                         Standard_Real &              Offset )
577
578 {
579   Standard_Boolean Result = Standard_False;
580   BRepAdaptor_Surface surf1( aFace );
581   Handle( Adaptor3d_HSurface ) surf2;
582   //gp_Vec OffsetVec( 1.0e0, 0.0e0, 0.0e0 );
583   Standard_Boolean isOffset = Standard_False;
584
585   if (surf1.GetType() == GeomAbs_OffsetSurface)
586     {
587       // Extracting Basis Surface
588       surf2 = surf1.BasisSurface();
589       isOffset = Standard_True;
590     }
591   else
592     surf2 = new BRepAdaptor_HSurface( surf1 );
593
594   aSurf = surf1.Surface().Surface();
595   //  aSurf->Transform(surf1.Trsf()) ;
596   aSurf = Handle( Geom_Surface )::DownCast( aSurf->Transformed( surf1.Trsf() ) );
597
598   if (surf2->GetType() == GeomAbs_Plane)
599     {
600       aPlane = surf2->Plane();
601       aSurfType = AIS_KOS_Plane;
602       Offset = 0.;
603       Result = Standard_True;
604     }
605
606   else if (surf2->GetType() == GeomAbs_SurfaceOfExtrusion)
607     {
608       Handle( Adaptor3d_HCurve ) BasisCurve = surf2->BasisCurve();
609       gp_Dir ExtrusionDir = surf2->Direction();
610       if (BasisCurve->GetType() == GeomAbs_Line)
611         {
612           gp_Lin BasisLine = BasisCurve->Line();
613           gp_Dir LineDir = BasisLine.Direction();
614           gp_Pnt LinePos = BasisLine.Location();
615           gp_Pln thePlane( LinePos, LineDir ^ ExtrusionDir);
616           aPlane = thePlane;
617           aSurfType = AIS_KOS_Plane;
618           Offset = 0.;
619           Result = Standard_True;
620         }
621     }
622
623   if (Result == Standard_True && isOffset)
624     {
625       aSurf = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Surface();
626       aPlane = (Handle( Geom_Plane )::DownCast( aSurf ))->Pln();
627       /*
628       Handle( Geom_OffsetSurface ) OffsetSurf = Handle( Geom_OffsetSurface )::DownCast( aSurf );
629       gp_Pnt PointOnPlane;
630       gp_Vec D1u, D1v;
631       OffsetSurf->D1( 0, 0, PointOnPlane, D1u, D1v );
632       D1u.Normalize();
633       D1v.Normalize();
634       OffsetVec = D1u ^ D1v;
635       aPlane.Translate( OffsetValue * OffsetVec );
636       */
637       Offset = 0.0e0;
638     }
639   if (Result == Standard_False)
640     {
641       if (isOffset)
642         {
643           Handle( Standard_Type ) TheType = aSurf->DynamicType();
644           if (TheType == STANDARD_TYPE(Geom_CylindricalSurface) ||
645               TheType == STANDARD_TYPE(Geom_ConicalSurface)     ||
646               TheType == STANDARD_TYPE(Geom_SphericalSurface)   ||
647               TheType == STANDARD_TYPE(Geom_ToroidalSurface))
648             {
649               aSurf = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Surface();
650               Offset = 0.0e0;
651             }
652           else
653             {
654               Offset = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Offset();
655               aSurf =  (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->BasisSurface();
656             }
657         }
658       Handle( Standard_Type ) TheType = aSurf->DynamicType();
659       if (TheType == STANDARD_TYPE(Geom_CylindricalSurface))
660         aSurfType = AIS_KOS_Cylinder;
661       else if (TheType == STANDARD_TYPE(Geom_ConicalSurface))
662         aSurfType = AIS_KOS_Cone;
663       else if (TheType == STANDARD_TYPE(Geom_SphericalSurface))
664         aSurfType = AIS_KOS_Sphere;
665       else if (TheType == STANDARD_TYPE(Geom_ToroidalSurface))
666         aSurfType = AIS_KOS_Torus;
667       else if (TheType == STANDARD_TYPE(Geom_SurfaceOfRevolution))
668         aSurfType = AIS_KOS_Revolution;
669       else if (TheType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
670         aSurfType = AIS_KOS_Extrusion;
671       else
672         aSurfType = AIS_KOS_OtherSurface;
673     }
674   return Result;
675 }
676
677
678 //=======================================================================
679 //function : ProjectPointOnPlane
680 //purpose  :
681 //=======================================================================
682
683 gp_Pnt AIS::ProjectPointOnPlane( const gp_Pnt & aPoint, const gp_Pln & aPlane )
684 {
685   gp_Vec aVec( aPlane.Location(), aPoint );
686   gp_Vec Normal = aPlane.Axis().Direction();
687   Normal = (aVec * Normal) * Normal;
688
689   return ( aPoint.Translated( -Normal ) );
690 }
691
692 //=======================================================================
693 //function : ProjectPointOnLine
694 //purpose  :
695 //=======================================================================
696
697 gp_Pnt AIS::ProjectPointOnLine( const gp_Pnt & aPoint, const gp_Lin & aLine )
698 {
699   gp_XYZ LinLoc = aLine.Location().XYZ();
700   gp_XYZ LinDir = aLine.Direction().XYZ();
701   Standard_Real Parameter = (aPoint.XYZ() - LinLoc) * LinDir;
702   gp_Pnt Result( LinLoc + Parameter * LinDir );
703   return Result;
704 }
705
706
707 //=======================================================================
708 //function : InitFaceLength
709 //purpose  : 
710 //=======================================================================
711
712 void AIS::InitFaceLength( const TopoDS_Face& aFace, 
713                          gp_Pln               & aPlane,
714                          Handle(Geom_Surface) & aSurface,
715                          AIS_KindOfSurface    & aSurfaceType,
716                          Standard_Real        & anOffset) 
717 {
718   AIS::GetPlaneFromFace( aFace, aPlane, aSurface, aSurfaceType, anOffset );
719   
720   if (Abs( anOffset ) > Precision::Confusion())
721     {
722       aSurface = new Geom_OffsetSurface( aSurface, anOffset );
723       anOffset = 0.0e0;
724     }
725   
726 }
727
728 //=======================================================================
729 //function : ComputeLengthBetweenPlanarFaces
730 //purpose  :
731 //=======================================================================
732
733 void AIS::ComputeLengthBetweenPlanarFaces( const TopoDS_Face &      FirstFace,
734                                            const TopoDS_Face &      SecondFace,
735                                            const gp_Pln &           Plane1,
736                                            const gp_Pln &           Plane2,
737                                            Standard_Real &          Value,
738                                            gp_Pnt &                 FirstAttach,
739                                            gp_Pnt &                 SecondAttach,
740                                            gp_Dir       &           DirAttach,
741                                            const Standard_Boolean   AutomaticPos,
742                                            gp_Pnt &                 Position )
743 {
744   TopExp_Explorer aExp( FirstFace, TopAbs_VERTEX );
745   // cas des plans infinis . SMO.
746   if (!aExp.More())
747     FirstAttach = Plane1.Location();
748   else  
749     FirstAttach = BRep_Tool::Pnt( TopoDS::Vertex( aExp.Current() ) );
750   SecondAttach = AIS::ProjectPointOnPlane( FirstAttach, Plane2 );
751
752   Value = FirstAttach.Distance( SecondAttach );
753
754   gp_Dir LengthDir = Plane1.Axis().Direction();
755   /*
756   if (Value > Precision::Confusion())
757     LengthDir = gp_Dir( gp_Vec( FirstAttach, SecondAttach ) );
758     */
759   DirAttach = Plane1.Position().XDirection();
760
761   if (AutomaticPos)
762     Position.SetXYZ((FirstAttach.XYZ() + SecondAttach.XYZ())/2.0e0) ;
763  
764   else // position is given
765     {
766       FirstAttach = AIS::Nearest( FirstFace, Position );
767       SecondAttach = AIS::ProjectPointOnPlane( FirstAttach, Plane2 );
768     }
769
770   Quantity_Parameter U, V ;
771   ElSLib::Parameters( Plane2, SecondAttach, U, V );
772   BRepTopAdaptor_FClass2d aClassifier( SecondFace, Precision::Confusion() );
773   TopAbs_State State = aClassifier.Perform( gp_Pnt2d( U, V ), Standard_False );
774   if (State == TopAbs_OUT || State == TopAbs_UNKNOWN)
775     {
776       SecondAttach = AIS::Nearest( SecondFace, Position );
777       if (Value > Precision::Confusion())
778         {
779           gp_Vec aVector = gp_Vec( FirstAttach, SecondAttach ) ^ LengthDir;
780           if (aVector.SquareMagnitude() > SquareTolerance)
781             DirAttach = aVector ^ LengthDir;
782         }
783       else
784         {
785           gp_Vec DirVec( FirstAttach, SecondAttach );
786           if (DirVec.SquareMagnitude() > SquareTolerance)
787             DirAttach = gp_Dir( DirVec );
788         }
789     }
790   if (!AutomaticPos)
791     {
792       gp_Pln PlaneOfDim( FirstAttach, DirAttach ^ LengthDir );
793       Position = AIS::ProjectPointOnPlane( Position, PlaneOfDim );
794     }
795 }
796
797
798 // Purpose: Return the point from <aFace> wich is the more distant
799 //          from <anAxis>
800 static gp_Pnt FindFarPoint (const gp_Ax1 &           anAxis,
801                             const TopoDS_Face &      aFace )
802 {
803   gp_Pnt ResPnt(0.0,0.0,0.0);
804   Standard_Real MaxDist = 0.e0, curdist2;
805
806   gp_Lin Line (anAxis);
807
808   TopExp_Explorer Explo (aFace, TopAbs_VERTEX);
809
810   if (!Explo.More()) {
811     // Cas des plans infinis (pas de Vertex, pas d'arete)
812     gp_Pln plane;
813     Handle( Geom_Surface ) aSurf;
814     AIS_KindOfSurface KOS;
815     Standard_Real offset;
816     AIS::GetPlaneFromFace (aFace,plane,aSurf,KOS,offset );
817     gp_Pnt aPoint = plane.Location();
818     MaxDist = Line.SquareDistance (aPoint);
819     if (MaxDist <= SquareTolerance)  {
820       MaxDist = 100;
821       gp_Dir DMove = plane.Axis().Direction()^anAxis.Direction();
822       gp_Vec VMove (DMove.XYZ()*100);
823       ResPnt = aPoint.Translated (VMove);
824     }
825   }
826
827   for (; Explo.More(); Explo.Next())
828     {
829       // CLE
830       // const TopoDS_Vertex & aVertex = TopoDS::Vertex( Explo.Current() );
831       TopoDS_Vertex aVertex = TopoDS::Vertex( Explo.Current() );
832       // ENDCLE
833       gp_Pnt aPoint = BRep_Tool::Pnt( aVertex );
834       curdist2 = Line.SquareDistance( aPoint );
835       if (curdist2 > MaxDist)
836         {
837           MaxDist = curdist2;
838           ResPnt = aPoint;
839         }
840     }
841
842   if (MaxDist <= SquareTolerance)
843     {
844       const Standard_Integer NodeNumber = 20;
845       Explo.Init( aFace, TopAbs_EDGE );
846       for (; Explo.More(); Explo.Next())
847         {
848           // CLE
849           // const TopoDS_Edge & anEdge = TopoDS::Edge( Explo.Current() );
850           TopoDS_Edge anEdge = TopoDS::Edge( Explo.Current() );
851           // ENDCLE
852           BRepAdaptor_Curve aCurve( anEdge );
853           Standard_Real FirstPar = aCurve.FirstParameter();
854           Standard_Real LastPar = aCurve.LastParameter();
855           Standard_Real Delta = (LastPar - FirstPar) / (NodeNumber - 1);
856           for (Standard_Integer i = 0; i < NodeNumber; i++)
857             {
858               gp_Pnt aPoint(0.0,0.0,0.0);
859               aCurve.D0( FirstPar, aPoint );
860               curdist2 = Line.SquareDistance( aPoint );
861               if (curdist2 > MaxDist)
862                 {
863                   MaxDist = curdist2;
864                   ResPnt = aPoint;
865                 }
866               FirstPar += Delta;
867             }
868           if (MaxDist > SquareTolerance) break;
869         }
870     }
871   if (MaxDist <= SquareTolerance)
872     Standard_ConstructionError::Raise("AIS:: problem attach point") ;
873   return ResPnt;
874 }
875
876 void AIS::ComputeAngleBetweenPlanarFaces( const TopoDS_Face &      FirstFace,
877                                           const TopoDS_Face &      SecondFace,
878                                           const Handle( Geom_Surface )& Surf2,
879                                           const gp_Ax1 &           Axis,
880                                           const Standard_Real      Value,
881                                           const Standard_Boolean   AutomaticPos,
882                                           gp_Pnt &                 Position,
883                                           gp_Pnt &                 Center,
884                                           gp_Pnt &                 FirstAttach,
885                                           gp_Pnt &                 SecondAttach,
886                                           gp_Dir &                 FirstDir,
887                                           gp_Dir &                 SecondDir )
888 {
889   FirstAttach = FindFarPoint( Axis, FirstFace );
890   Center = AIS::ProjectPointOnLine( FirstAttach, gp_Lin( Axis ) );
891   gp_Dir aDir1( gp_Vec( Center, FirstAttach ) );
892   FirstDir = aDir1;
893   SecondAttach = FirstAttach.Rotated( Axis, Value );
894   gp_Dir aDir2( gp_Vec( Center, SecondAttach ) );
895   SecondDir = aDir2;
896
897   GeomAPI_ProjectPointOnSurf   aProjPnt( SecondAttach,
898                                          Surf2 ) ;
899   //SecondAttach = aProjPnt.Point(1) ;
900   Quantity_Parameter U,V ;
901   aProjPnt.Parameters(1,U,V) ;
902   BRepTopAdaptor_FClass2d aClassifier(SecondFace,
903                                       Precision::Confusion());
904   if (aClassifier.Perform(gp_Pnt2d(U,V),Standard_False) == TopAbs_OUT ||
905       aClassifier.Perform(gp_Pnt2d(U,V),Standard_False) == TopAbs_UNKNOWN)
906     SecondAttach = FindFarPoint( Axis, SecondFace );
907
908   if (AutomaticPos)
909     Position = FirstAttach.Rotated( Axis, Value*0.5 );
910   else
911     {
912       gp_Pln PlaneOfDim( Center, Axis.Direction() );
913       Position = AIS::ProjectPointOnPlane( Position, PlaneOfDim );
914     }
915 }
916                                      
917                                      
918 void AIS::ComputeAngleBetweenCurvilinearFaces( const TopoDS_Face &      FirstFace,
919                                                const TopoDS_Face &      SecondFace,
920                                                const Handle( Geom_Surface )& FirstSurf,
921                                                const Handle( Geom_Surface )& SecondSurf,
922                                                const AIS_KindOfSurface  FirstSurfType,
923                                                const AIS_KindOfSurface  SecondSurfType,
924                                                const gp_Ax1 &           Axis,
925                                                const Standard_Real      Value,
926                                                const Standard_Boolean   AutomaticPos,
927                                                gp_Pnt &                 Position,
928                                                gp_Pnt &                 Center,
929                                                gp_Pnt &                 FirstAttach,
930                                                gp_Pnt &                 SecondAttach,
931                                                gp_Dir &                 FirstDir,
932                                                gp_Dir &                 SecondDir,
933                                                Handle( Geom_Plane ) &   Plane )
934 {
935   //
936   // even if it is not AutomaticPosition do not assume the Automatic
937   // case has saved the values in the AIS_AngleDimension class : this
938   // is not always the case
939   //
940   gp_Pnt SavedPosition = Position ;
941   FirstAttach = FindFarPoint( Axis, FirstFace );
942   Plane = new Geom_Plane( Axis.Location(),
943                           gp_Dir( gp_Vec( Axis.Location(), FirstAttach ) ^
944                                   gp_Vec( Axis.Direction() ) ) );
945   
946   Handle( Geom_Line ) FirstLine, SecondLine;
947   Standard_Real FirstU, FirstV;
948   if (FirstSurfType == AIS_KOS_Cylinder)
949     ElSLib::Parameters( Handle( Geom_CylindricalSurface )::DownCast( FirstSurf )->Cylinder(),
950                         FirstAttach,
951                         FirstU, FirstV );
952   else // it is Cone
953     ElSLib::Parameters( Handle( Geom_ConicalSurface )::DownCast( FirstSurf )->Cone(),
954                         FirstAttach,
955                         FirstU, FirstV );
956   FirstLine = Handle( Geom_Line )::DownCast( FirstSurf->UIso( FirstU ) );
957   
958   if (SecondSurfType == AIS_KOS_Cylinder)
959     {
960       Handle( Geom_CylindricalSurface ) Cylinder2 =
961         Handle( Geom_CylindricalSurface )::DownCast( SecondSurf );
962       Standard_Real SecondU = Cylinder2->Cylinder().XAxis().Direction().Angle(
963                                                                               gp_Dir( gp_Vec( ProjectPointOnLine( FirstAttach, gp_Lin( Cylinder2->Cylinder().Axis() ) ),
964                                                                                               FirstAttach ) ) );
965       
966       SecondLine = Handle( Geom_Line )::DownCast( Cylinder2->UIso( SecondU ) );
967     }
968   
969   else // it is Cone
970     {
971       Handle( Geom_ConicalSurface ) Cone2 = Handle( Geom_ConicalSurface )::DownCast( SecondSurf );
972       gp_Dir Xdirection = Cone2->Cone().XAxis().Direction() ;
973       gp_Dir ToFirstAttach = gp_Dir( gp_Vec(
974                                             ProjectPointOnLine( FirstAttach, gp_Lin( Cone2->Cone().Axis() )),
975                                             FirstAttach ) );
976       
977       Standard_Real SecondU = Xdirection.Angle( ToFirstAttach );
978       // check sign
979       if (! Xdirection.IsEqual( ToFirstAttach, Precision::Angular() ) &&
980           ! Xdirection.IsOpposite( ToFirstAttach, Precision::Angular() ) &&
981           (Xdirection ^ ToFirstAttach) * Cone2->Cone().Axis().Direction() < 0.0e0)
982         SecondU = 2*PI - SecondU ;
983       
984       SecondLine = Handle( Geom_Line )::DownCast( Cone2->UIso( SecondU ) );
985       
986     }
987   if (! (FirstLine->Lin().Direction().IsEqual( SecondLine->Lin().Direction(), Precision::Angular() )) &&
988       ! (FirstLine->Lin().Direction().IsOpposite( SecondLine->Lin().Direction(), Precision::Angular() )))
989     {
990       GeomAPI_ExtremaCurveCurve Intersection( FirstLine, SecondLine );
991       Intersection.Points( 1, Center, Center );
992       
993       if (Center.SquareDistance( FirstAttach ) <= SquareTolerance)
994         {
995           FirstAttach = AIS::Farest( FirstFace, Center );
996           Standard_Real U, V;
997           if (FirstSurfType == AIS_KOS_Cylinder)
998             {
999               ElSLib::Parameters ( (Handle( Geom_CylindricalSurface )::DownCast( FirstSurf ))->Cylinder(),
1000                                    FirstAttach,
1001                                    U, V );
1002               FirstAttach = ElSLib::Value( FirstU, V,
1003                                            (Handle( Geom_CylindricalSurface )::DownCast( FirstSurf ))
1004                                            ->Cylinder() );
1005             }
1006           else // it is Cone
1007             {
1008               ElSLib::Parameters ( (Handle( Geom_ConicalSurface )::DownCast( FirstSurf ))->Cone(),
1009                                    FirstAttach,
1010                                    U, V );
1011               FirstAttach = ElSLib::Value( FirstU, V,
1012                                            (Handle( Geom_ConicalSurface )::DownCast( FirstSurf ))
1013                                            ->Cone() );
1014             }
1015         }
1016       gp_Vec FirstVec( Center, FirstAttach );
1017       FirstDir = gp_Dir( FirstVec );
1018       
1019       gp_Ax1 AxisOfRotation( Center, Plane->Pln().Axis().Direction() );
1020       SecondAttach = FirstAttach.Rotated( AxisOfRotation, Value );
1021       if (! SecondLine->Lin().Contains( SecondAttach, Precision::Confusion() ))
1022         {
1023           AxisOfRotation.Reverse();
1024           SecondAttach = FirstAttach.Rotated( AxisOfRotation, Value );
1025         }
1026       
1027       Position = FirstAttach.Rotated( AxisOfRotation, Value/2 );
1028
1029       gp_Vec SecondVec( Center, SecondAttach );
1030       SecondDir = gp_Dir( SecondVec );
1031       
1032     }
1033   else // FirstLine and SecondLine are coincident
1034     {
1035       Position = SecondAttach = FirstAttach;
1036       FirstDir = FirstLine->Lin().Direction();
1037       SecondDir = FirstDir;
1038       Center = Position.Translated( gp_Vec( -FirstDir ) );
1039       //Position.Translate( gp_Vec( FirstDir ) );
1040     }
1041   
1042   GeomAPI_ProjectPointOnSurf   aProjPnt( SecondAttach, SecondSurf ) ;
1043   Quantity_Parameter U, V;
1044   aProjPnt.LowerDistanceParameters( U, V ) ;
1045   BRepTopAdaptor_FClass2d aClassifier2( SecondFace, Precision::Confusion());
1046   TopAbs_State State = aClassifier2.Perform( gp_Pnt2d( U, V ), Standard_True );
1047   if (State == TopAbs_OUT || State == TopAbs_UNKNOWN)
1048     {
1049       Standard_Real MinDist2 = RealLast();
1050       Standard_Real curdist2;
1051       gp_Pnt curpnt(0.0,0.0,0.0);
1052       gp_Pnt Result(0.0,0.0,0.0);
1053       TopExp_Explorer Explo( SecondFace, TopAbs_VERTEX );
1054       for (; Explo.More(); Explo.Next())
1055         {
1056           curpnt = BRep_Tool::Pnt( TopoDS::Vertex( Explo.Current() ) );
1057           curdist2 = SecondAttach.SquareDistance( curpnt ) ;
1058           if (curpnt.SquareDistance( Center ) > SquareTolerance && curdist2 < MinDist2)
1059             {
1060               Result = curpnt;
1061               MinDist2 = curdist2;
1062             }
1063         }
1064       SecondAttach = Result;
1065     }
1066
1067   if (! AutomaticPos)
1068     {  // protection in case this is created using the manual position
1069       
1070       
1071       Position = AIS::ProjectPointOnPlane( SavedPosition, Plane->Pln() );
1072     }
1073 }
1074
1075
1076 void AIS::ComputeLengthBetweenCurvilinearFaces( const TopoDS_Face &      FirstFace,
1077                                                 const TopoDS_Face &      SecondFace,
1078                                                 Handle( Geom_Surface )&  FirstSurf,
1079                                                 Handle( Geom_Surface )&  SecondSurf,
1080                                                 const Standard_Boolean   AutomaticPos,
1081                                                 Standard_Real &          Value,
1082                                                 gp_Pnt &                 Position,
1083                                                 gp_Pnt &                 FirstAttach,
1084                                                 gp_Pnt &                 SecondAttach,
1085                                                 gp_Dir &                 DirAttach )
1086 {
1087   GeomAPI_ProjectPointOnSurf aProjector;
1088   Quantity_Parameter U, V;
1089 #ifndef DEB
1090   TopAbs_State State = TopAbs_UNKNOWN;
1091 #else
1092   TopAbs_State State;
1093 #endif
1094   if (AutomaticPos)
1095     {
1096       TopExp_Explorer Explo( FirstFace, TopAbs_VERTEX );
1097       FirstAttach = BRep_Tool::Pnt( TopoDS::Vertex( Explo.Current() ) );
1098       aProjector.Init(FirstAttach , FirstSurf );
1099       FirstAttach = aProjector.NearestPoint();
1100       aProjector.LowerDistanceParameters( U, V );
1101     }
1102   else // posiiton is given
1103     {
1104       aProjector.Init( Position, FirstSurf );
1105       FirstAttach = aProjector.NearestPoint();
1106
1107       aProjector.LowerDistanceParameters( U, V );
1108       BRepTopAdaptor_FClass2d aClassifier( FirstFace, Precision::Confusion() );
1109       State = aClassifier.Perform( gp_Pnt2d( U, V ), ( (FirstSurf->IsUPeriodic() || FirstSurf->IsVPeriodic())?
1110                                                        Standard_True
1111                                                        : Standard_False ) );
1112       if (State == TopAbs_OUT || State == TopAbs_UNKNOWN)
1113         {
1114           FirstAttach = AIS::Nearest( FirstFace, Position );
1115           aProjector.Init( FirstAttach, FirstSurf );
1116           aProjector.LowerDistanceParameters( U, V );
1117         }
1118     }
1119
1120   gp_Vec D1U, D1V;
1121   FirstSurf->D1( U, V, FirstAttach, D1U, D1V );
1122   if (D1U.SquareMagnitude() <= SquareTolerance || D1V.SquareMagnitude() <= SquareTolerance)
1123     {
1124       FirstAttach = AIS::Farest( FirstFace, FirstAttach );
1125       aProjector.Init( FirstAttach, FirstSurf );
1126       aProjector.LowerDistanceParameters( U, V );
1127       FirstSurf->D1( U, V, FirstAttach, D1U, D1V );
1128     }
1129   D1U.Normalize();
1130   D1V.Normalize();
1131   DirAttach = gp_Dir( D1U ^ D1V );
1132
1133   aProjector.Init( FirstAttach, SecondSurf );
1134 #ifndef DEB
1135   Standard_Integer Index = 0;
1136 #else
1137   Standard_Integer Index;
1138 #endif
1139   Quantity_Length MinDist = RealLast();
1140   gp_Dir LocalDir;
1141   for (Standard_Integer i = 1; i <= aProjector.NbPoints(); i++)
1142     {
1143       aProjector.Parameters( i, U, V );
1144
1145       SecondSurf->D1( U, V, SecondAttach, D1U, D1V );
1146       if (D1U.SquareMagnitude() <= SquareTolerance || D1V.SquareMagnitude() <= SquareTolerance)
1147         LocalDir = gp_Dir( gp_Vec( FirstAttach, aProjector.Point( i ) ) );
1148       else
1149         LocalDir = gp_Dir( D1U ^ D1V );
1150       if (DirAttach.IsParallel( LocalDir, Precision::Angular() ) && aProjector.Distance( i ) < MinDist)
1151         {
1152           Index = i;
1153           MinDist = aProjector.Distance( i );
1154         }
1155     }
1156 if (Index == 0)  { 
1157   SecondAttach = FirstAttach;
1158 } else {
1159   SecondAttach = aProjector.Point( Index );
1160   aProjector.Parameters( Index, U, V );
1161
1162   Value = FirstAttach.Distance( SecondAttach );
1163   if (Value > Precision::Confusion())
1164     DirAttach = gp_Dir( gp_Vec( FirstAttach, SecondAttach ) );
1165
1166   if (AutomaticPos)
1167     Position.SetXYZ( (FirstAttach.XYZ() + SecondAttach.XYZ()) / 2 );
1168   else if (State == TopAbs_OUT || State == TopAbs_UNKNOWN)
1169     Position = AIS::ProjectPointOnLine( Position, gp_Lin( FirstAttach, DirAttach ) );
1170
1171   // Now there is projection of FirstAttach onto SecondSurf in aProjector
1172   BRepTopAdaptor_FClass2d aClassifier( SecondFace, Precision::Confusion() );
1173   State = aClassifier.Perform( gp_Pnt2d( U, V ), ( (SecondSurf->IsUPeriodic() || SecondSurf->IsVPeriodic())?
1174                                                    Standard_True
1175                                                    : Standard_False ) );
1176   if (State == TopAbs_OUT || State == TopAbs_UNKNOWN)
1177     SecondAttach = AIS::Nearest( SecondFace, SecondAttach );
1178 }
1179 }
1180 gp_Pnt AIS::TranslatePointToBound( const gp_Pnt & aPoint, const gp_Dir & aDir, const Bnd_Box & aBndBox )
1181 {
1182   if (aBndBox.IsOut( aPoint ))
1183     return aPoint;
1184   else
1185     {
1186       gp_Pnt Result(0.0,0.0,0.0);
1187       TColStd_Array2OfReal Bound( 1, 3, 1, 2 );
1188       TColStd_Array1OfReal Origin( 1, 3 );
1189       TColStd_Array1OfReal Dir( 1, 3 );
1190       Standard_Real t;
1191       
1192       aBndBox.Get( Bound(1,1), Bound(2,1), Bound(3,1), Bound(1,2),  Bound(2,2), Bound(3,2) );
1193       aPoint.Coord( Origin(1), Origin(2), Origin(3) );
1194       aDir.Coord( Dir(1), Dir(2), Dir(3) );
1195
1196       Bnd_Box EnlargedBox = aBndBox;
1197       EnlargedBox.Enlarge( aBndBox.GetGap() + Precision::Confusion() );
1198
1199       Standard_Boolean IsFound = Standard_False;
1200       for (Standard_Integer i = 1; i <= 3; i++)
1201         {
1202           if (Abs( Dir( i ) ) <= gp::Resolution())
1203             continue;
1204           for (Standard_Integer j = 1; j <= 2; j++)
1205             {
1206               t = (Bound( i, j ) - Origin( i )) / Dir( i );
1207               if (t < 0.0e0)
1208                 continue;
1209               Result = aPoint.Translated( gp_Vec( aDir ) * t );
1210               if (! EnlargedBox.IsOut( Result ))
1211                 {
1212                   IsFound = Standard_True;
1213                   break;
1214                 }
1215             }
1216           if (IsFound) break;
1217         }
1218       return Result;
1219     }
1220 }
1221
1222
1223 //=======================================================================
1224 //function : InDomain
1225 //purpose  : 
1226 //=======================================================================
1227
1228 Standard_Boolean AIS::InDomain(const Standard_Real fpar,
1229                                const Standard_Real lpar,
1230                                const Standard_Real para) 
1231 {
1232   if (fpar >= 0.) {
1233     if(lpar > fpar)
1234       return ((para >= fpar) && (para <= lpar));
1235     else { // fpar > lpar
1236       Standard_Real delta = 2*PI-fpar;
1237       Standard_Real lp, par, fp;
1238       lp = lpar + delta;
1239       par = para + delta;
1240       while(lp > 2*PI) lp-=2*PI;
1241       while(par > 2*PI) par-=2*PI;
1242       fp = 0.;
1243       return ((par >= fp) && (par <= lp));
1244     }
1245       
1246   }
1247   if (para >= (fpar+2*PI)) return Standard_True;
1248   if (para <= lpar) return Standard_True;
1249   return Standard_False;
1250 }
1251
1252 //=======================================================================
1253 //function : DistanceFromApex
1254 //purpose  : calculates parametric length arc of ellipse
1255 //=======================================================================
1256
1257 Standard_Real AIS::DistanceFromApex(const gp_Elips & elips,
1258                                     const gp_Pnt   & Apex,
1259                                     const Standard_Real par)
1260 {
1261   Standard_Real dist;
1262   Standard_Real parApex = ElCLib::Parameter ( elips, Apex );
1263   if(parApex == 0.0 || parApex == PI) 
1264     {//Major case
1265       if(parApex == 0.0) //pos Apex
1266         dist = (par < PI) ? par : (2*PI - par);
1267       else //neg Apex
1268         dist = (par < PI) ? ( PI - par) : ( par - PI );
1269     }
1270   else 
1271     {// Minor case
1272       if(parApex == PI / 2) //pos Apex
1273         {
1274           if(par <= parApex + PI && par > parApex) // 3/2*PI < par < PI/2
1275             dist = par - parApex;
1276           else 
1277             { 
1278               if(par >  parApex + PI) // 3/2*PI < par < 2*PI
1279                 dist = 2*PI - par + parApex;
1280               else
1281                 dist = parApex - par; 
1282             }
1283           }
1284       else //neg Apex == 3/2*PI
1285         {
1286           if(par <= parApex && par >= PI/2) // PI/2 < par < 3/2*PI
1287             dist = parApex - par;
1288           else
1289             {
1290               if(par >  parApex) // 3/2*PI < par < 2*PI
1291                 dist = par - parApex;
1292               else
1293                 dist = par + PI/2; // 0 < par < PI/2
1294             }
1295         }
1296     }
1297   return dist;
1298 }
1299
1300 //=======================================================================
1301 //function : NearestApex
1302 //purpose  : 
1303 //=======================================================================
1304
1305 gp_Pnt AIS::NearestApex(const gp_Elips & elips,
1306                         const gp_Pnt   & pApex,
1307                         const gp_Pnt   & nApex,
1308                         const Standard_Real fpara,
1309                         const Standard_Real lpara,
1310                               Standard_Boolean & IsInDomain)
1311 {
1312   Standard_Real parP, parN;
1313   gp_Pnt EndOfArrow(0.0,0.0,0.0);
1314   IsInDomain = Standard_True;
1315   parP = ElCLib::Parameter ( elips, pApex );
1316   if(InDomain(fpara, lpara, parP)) EndOfArrow = pApex;
1317   else 
1318     {
1319       parN = ElCLib::Parameter ( elips, nApex );
1320       if(InDomain(fpara, lpara, parN)) EndOfArrow = nApex;
1321       else {
1322         IsInDomain = Standard_False;
1323         Standard_Real posd = Min(DistanceFromApex (elips,pApex, fpara), 
1324                                  DistanceFromApex (elips,pApex, lpara));
1325         Standard_Real negd = Min(DistanceFromApex (elips,nApex, fpara), 
1326                                  DistanceFromApex (elips,nApex, lpara));
1327         if( posd < negd ) 
1328           EndOfArrow = pApex;
1329         else
1330           EndOfArrow = nApex;
1331       }
1332     }
1333   return EndOfArrow;
1334 }
1335
1336 //=======================================================================
1337 //function : ComputeProjEdgePresentation
1338 //purpose  : 
1339 //=======================================================================
1340
1341 void AIS::ComputeProjEdgePresentation( const Handle( Prs3d_Presentation )& aPresentation,
1342                                        const Handle( AIS_Drawer )& aDrawer,
1343                                        const TopoDS_Edge& anEdge,
1344                                        const Handle( Geom_Curve )& ProjCurve,
1345                                        const gp_Pnt& FirstP,
1346                                        const gp_Pnt& LastP,
1347                                        const Quantity_NameOfColor aColor,
1348                                        const Standard_Real aWidth,
1349                                        const Aspect_TypeOfLine aProjTOL,
1350                                        const Aspect_TypeOfLine aCallTOL )
1351 {
1352   if (!aDrawer->HasWireAspect()){
1353     aDrawer->SetWireAspect(new Prs3d_LineAspect(aColor,aProjTOL,2.));}
1354   else {
1355     // CLE
1356     // const Handle(Prs3d_LineAspect)& li = aDrawer->WireAspect();
1357     Handle(Prs3d_LineAspect) li = aDrawer->WireAspect();
1358     // ENDCLE
1359     li->SetColor(aColor);
1360     li->SetTypeOfLine(aProjTOL);
1361     li->SetWidth(aWidth);
1362   }
1363
1364   Standard_Real pf, pl;
1365   TopLoc_Location loc;
1366   Handle(Geom_Curve) curve;
1367   Standard_Boolean isInfinite;
1368   curve = BRep_Tool::Curve(anEdge,loc,pf,pl);
1369   isInfinite = (Precision::IsInfinite(pf) || Precision::IsInfinite(pl));
1370
1371   TopoDS_Edge E;
1372
1373   // Calcul de la presentation de l'edge
1374   if (ProjCurve->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1375     // CLE
1376     // const Handle(Geom_Line) & gl = (Handle(Geom_Line)&) ProjCurve;
1377     Handle(Geom_Line) gl = (Handle(Geom_Line)&) ProjCurve;
1378     // ENDCLE
1379     if ( !isInfinite) {
1380       pf = ElCLib::Parameter(gl->Lin(),FirstP);
1381       pl = ElCLib::Parameter(gl->Lin(),LastP);
1382       BRepBuilderAPI_MakeEdge MakEd(gl->Lin(), pf, pl);
1383       E = MakEd.Edge();
1384     }
1385     else {
1386       BRepBuilderAPI_MakeEdge MakEd(gl->Lin());
1387       E = MakEd.Edge();
1388     }
1389   }
1390   else if (ProjCurve->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1391     // CLE
1392     // const Handle(Geom_Circle) & gc = (Handle(Geom_Circle)&) ProjCurve;
1393     Handle(Geom_Circle) gc = (Handle(Geom_Circle)&) ProjCurve;
1394     // ENDCLE
1395     pf = ElCLib::Parameter(gc->Circ(),FirstP);
1396     pl = ElCLib::Parameter(gc->Circ(),LastP);
1397     BRepBuilderAPI_MakeEdge MakEd(gc->Circ(),pf, pl);
1398     E = MakEd.Edge();
1399   }
1400   StdPrs_WFDeflectionShape::Add(aPresentation, E, aDrawer);
1401
1402   //Calcul de la presentation des lignes de raccord
1403   aDrawer->WireAspect()->SetTypeOfLine(aCallTOL);
1404   if (!isInfinite) {
1405     gp_Pnt ppf(0.0,0.0,0.0), ppl(0.0,0.0,0.0);
1406     ppf = BRep_Tool::Pnt( TopExp::FirstVertex(TopoDS::Edge(anEdge)));
1407     ppl = BRep_Tool::Pnt( TopExp::LastVertex(TopoDS::Edge(anEdge)));
1408
1409     // it is patch!
1410     if (FirstP.SquareDistance( ppf ) > SquareTolerance)
1411       {
1412         BRepBuilderAPI_MakeEdge MakEd1(FirstP, ppf);
1413         StdPrs_WFDeflectionShape::Add(aPresentation, MakEd1.Edge(), aDrawer);
1414       }
1415     else
1416       {
1417         BRepBuilderAPI_MakeVertex MakVert1( FirstP );
1418         StdPrs_WFDeflectionShape::Add(aPresentation, MakVert1.Vertex(), aDrawer);
1419       }
1420     if (LastP.SquareDistance( ppl ) > SquareTolerance)
1421       {
1422         BRepBuilderAPI_MakeEdge MakEd2(LastP, ppl);
1423         StdPrs_WFDeflectionShape::Add(aPresentation, MakEd2.Edge(), aDrawer);
1424       }
1425     else
1426       {
1427         BRepBuilderAPI_MakeVertex MakVert2( LastP );
1428         StdPrs_WFDeflectionShape::Add(aPresentation, MakVert2.Vertex(), aDrawer);
1429       }
1430 /*
1431     BRepBuilderAPI_MakeEdge MakEd1(FirstP, ppf);
1432     StdPrs_WFDeflectionShape::Add(aPresentation, MakEd1.Edge(), aDrawer);
1433     BRepBuilderAPI_MakeEdge MakEd2(LastP, ppl);
1434     StdPrs_WFDeflectionShape::Add(aPresentation, MakEd2.Edge(), aDrawer);
1435 */
1436   }
1437 }
1438
1439 //=======================================================================
1440 //function : ComputeProjVertexPresentation
1441 //purpose  : 
1442 //=======================================================================
1443
1444 void AIS::ComputeProjVertexPresentation( const Handle( Prs3d_Presentation )& aPresentation,
1445                                         const Handle( AIS_Drawer )& aDrawer,
1446                                         const TopoDS_Vertex& aVertex,
1447                                         const gp_Pnt& ProjPoint,
1448                                         const Quantity_NameOfColor aColor,
1449                                         const Standard_Real aWidth,
1450                                         const Aspect_TypeOfMarker aProjTOM,
1451                                         const Aspect_TypeOfLine aCallTOL ) 
1452 {
1453   if (!aDrawer->HasPointAspect()){
1454     aDrawer->SetPointAspect(new Prs3d_PointAspect(aProjTOM, aColor,1));}
1455   else {
1456     // CLE
1457     // const Handle(Prs3d_PointAspect)& pa = aDrawer->PointAspect();
1458     Handle(Prs3d_PointAspect) pa = aDrawer->PointAspect();
1459     // ENDCLE
1460     pa->SetColor(aColor);
1461     pa->SetTypeOfMarker(aProjTOM);
1462   }
1463   
1464   // calcul du projete
1465   StdPrs_Point::Add(aPresentation, new Geom_CartesianPoint(ProjPoint), aDrawer);
1466
1467   if (!aDrawer->HasWireAspect()){
1468     aDrawer->SetWireAspect(new Prs3d_LineAspect(aColor,aCallTOL,2.));}
1469   else {
1470     // CLE
1471     // const Handle(Prs3d_LineAspect)& li = aDrawer->WireAspect();
1472     Handle(Prs3d_LineAspect) li = aDrawer->WireAspect();
1473     // ENDCLE
1474     li->SetColor(aColor);
1475     li->SetTypeOfLine(aCallTOL);
1476     li->SetWidth(aWidth);
1477   }
1478   
1479   // Si les points ne sont pas confondus...
1480   if (!ProjPoint.IsEqual (BRep_Tool::Pnt(aVertex),Precision::Confusion())) {
1481     // calcul des lignes de rappel
1482     BRepBuilderAPI_MakeEdge MakEd(ProjPoint,BRep_Tool::Pnt(aVertex));
1483     StdPrs_WFDeflectionShape::Add(aPresentation, MakEd.Edge(), aDrawer);
1484   }
1485 }