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