0029936: Documentation - improve description of AIS_Animation class
[occt.git] / src / AIS / AIS_LengthDimension.cxx
1 // Created on: 1996-12-05
2 // Created by: Arnaud BOUZY/Odile Olivier
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2013 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <AIS_LengthDimension.hxx>
18
19 #include <AIS.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepExtrema_DistShapeShape.hxx>
23 #include <BRepLib_MakeVertex.hxx>
24 #include <BRepTopAdaptor_FClass2d.hxx>
25 #include <BRepTools.hxx>
26 #include <ElCLib.hxx>
27 #include <ElSLib.hxx>
28 #include <gce_MakeDir.hxx>
29 #include <gce_MakePln.hxx>
30 #include <Geom_TrimmedCurve.hxx>
31 #include <GeomAPI_ExtremaCurveCurve.hxx>
32 #include <GeomAPI_ExtremaSurfaceSurface.hxx>
33 #include <Geom_Curve.hxx>
34 #include <Geom_Line.hxx>
35 #include <TopExp.hxx>
36 #include <TopExp_Explorer.hxx>
37
38
39 IMPLEMENT_STANDARD_RTTIEXT(AIS_LengthDimension,AIS_Dimension)
40
41 //=======================================================================
42 //function : Constructor
43 //purpose  : Dimension between two faces
44 //=======================================================================
45 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFirstFace,
46                                           const TopoDS_Face& theSecondFace)
47 : AIS_Dimension (AIS_KOD_LENGTH),
48   myHasCustomDirection (Standard_False)
49 {
50   SetMeasuredGeometry (theFirstFace, theSecondFace);
51   SetFlyout (15.0);
52 }
53
54 //=======================================================================
55 //function : Constructor
56 //purpose  : Dimension between two shape
57 //=======================================================================
58 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFace,
59                                           const TopoDS_Edge& theEdge)
60 : AIS_Dimension (AIS_KOD_LENGTH),
61   myHasCustomDirection (Standard_False)
62 {
63   SetMeasuredGeometry (theFace, theEdge);
64   SetFlyout (15.0);
65 }
66
67 //=======================================================================
68 //function : Constructor
69 //purpose  : Dimension between two points
70 //=======================================================================
71 AIS_LengthDimension::AIS_LengthDimension (const gp_Pnt& theFirstPoint,
72                                           const gp_Pnt& theSecondPoint,
73                                           const gp_Pln& thePlane)
74 : AIS_Dimension (AIS_KOD_LENGTH),
75   myHasCustomDirection (Standard_False)
76 {
77   SetMeasuredGeometry (theFirstPoint, theSecondPoint, thePlane);
78   SetFlyout (15.0);
79 }
80
81 //=======================================================================
82 //function : Constructor
83 //purpose  : Dimension between two shape
84 //=======================================================================
85 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Shape& theFirstShape,
86                                           const TopoDS_Shape& theSecondShape,
87                                           const gp_Pln& thePlane)
88 : AIS_Dimension (AIS_KOD_LENGTH),
89   myHasCustomDirection (Standard_False)
90 {
91   SetCustomPlane (thePlane);
92   SetMeasuredShapes (theFirstShape, theSecondShape);
93   SetFlyout (15.0);
94 }
95
96 //=======================================================================
97 //function : Constructor
98 //purpose  : Dimension of one edge
99 //=======================================================================
100 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Edge& theEdge,
101                                           const gp_Pln& thePlane)
102 : AIS_Dimension (AIS_KOD_LENGTH),
103   myHasCustomDirection (Standard_False)
104 {
105   SetMeasuredGeometry (theEdge, thePlane);
106   SetFlyout (15.0);
107 }
108
109 //=======================================================================
110 //function : SetMeasuredGeometry
111 //purpose  : 
112 //=======================================================================
113 void AIS_LengthDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
114                                                const gp_Pnt& theSecondPoint,
115                                                const gp_Pln& thePlane)
116 {
117   myFirstPoint      = theFirstPoint;
118   mySecondPoint     = theSecondPoint;
119   myFirstShape      = BRepLib_MakeVertex (myFirstPoint);
120   mySecondShape     = BRepLib_MakeVertex (mySecondPoint);
121   myGeometryType    = GeometryType_Points;
122   SetCustomPlane (thePlane);
123   myIsGeometryValid = IsValidPoints (theFirstPoint, theSecondPoint);
124
125   SetToUpdate();
126 }
127
128 //=======================================================================
129 //function : SetMeasuredGeometry
130 //purpose  : 
131 //=======================================================================
132 void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Edge& theEdge,
133                                                const gp_Pln& thePlane)
134 {
135   myFirstShape      = theEdge;
136   mySecondShape     = TopoDS_Shape();
137   myGeometryType    = GeometryType_Edge;
138   SetCustomPlane (thePlane);
139   myIsGeometryValid = InitOneShapePoints (myFirstShape);
140
141   SetToUpdate();
142 }
143
144 //=======================================================================
145 //function : SetMeasuredGeometry
146 //purpose  : 
147 //=======================================================================
148 void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
149                                                const TopoDS_Face& theSecondFace)
150 {
151   SetMeasuredShapes (theFirstFace, theSecondFace);
152 }
153
154 //=======================================================================
155 //function : SetMeasuredGeometry
156 //purpose  : 
157 //=======================================================================
158 void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Face& theFace,
159                                                const TopoDS_Edge& theEdge)
160 {
161   SetMeasuredShapes (theFace, theEdge);
162 }
163
164 //=======================================================================
165 //function : SetMeasuredShapes
166 //purpose  : 
167 //=======================================================================
168 void AIS_LengthDimension::SetMeasuredShapes (const TopoDS_Shape& theFirstShape,
169                                              const TopoDS_Shape& theSecondShape)
170 {
171   gp_Pln aComputedPlane;
172   Standard_Boolean isPlaneReturned = Standard_False;
173
174   myFirstShape      = theFirstShape;
175   mySecondShape     = theSecondShape;
176   myIsGeometryValid = InitTwoShapesPoints (myFirstShape, mySecondShape, aComputedPlane, isPlaneReturned);
177
178   if (myIsGeometryValid && !myIsPlaneCustom)
179   {
180     if (isPlaneReturned)
181     {
182       myPlane = aComputedPlane;
183     }
184     else
185     {
186       myIsGeometryValid = Standard_False;
187     }
188   }
189
190   SetToUpdate();
191 }
192
193 //=======================================================================
194 //function : CheckPlane
195 //purpose  : 
196 //=======================================================================
197 Standard_Boolean AIS_LengthDimension::CheckPlane (const gp_Pln& thePlane) const
198 {
199   Standard_Boolean anIsFaultyNormal =
200     thePlane.Axis().Direction().IsParallel(gce_MakeDir (myFirstPoint, mySecondPoint), Precision::Angular());
201
202   if ((!thePlane.Contains (myFirstPoint, Precision::Confusion()) && !thePlane.Contains (mySecondPoint, Precision::Confusion()))
203    || anIsFaultyNormal)
204   {
205     return Standard_False;
206   }
207
208   return Standard_True;
209 }
210
211 //=======================================================================
212 //function : ComputePlane
213 //purpose  : 
214 //=======================================================================
215 gp_Pln AIS_LengthDimension::ComputePlane (const gp_Dir& theAttachDir) const
216 {
217   if (!IsValidPoints (myFirstPoint, mySecondPoint))
218   {
219     return gp_Pln();
220   }
221
222   gp_Pnt aThirdPoint (myFirstPoint.Translated (gp_Vec(theAttachDir)));
223   gce_MakePln aPlaneConstrustor (myFirstPoint, mySecondPoint, aThirdPoint);
224   return aPlaneConstrustor.Value();
225 }
226
227 //=======================================================================
228 //function : GetModelUnits
229 //purpose  :
230 //=======================================================================
231 const TCollection_AsciiString& AIS_LengthDimension::GetModelUnits() const
232 {
233   return myDrawer->DimLengthModelUnits();
234 }
235
236 //=======================================================================
237 //function : GetDisplayUnits
238 //purpose  :
239 //=======================================================================
240 const TCollection_AsciiString& AIS_LengthDimension::GetDisplayUnits() const
241 {
242   return myDrawer->DimLengthDisplayUnits();
243 }
244
245 //=======================================================================
246 //function : SetModelUnits
247 //purpose  :
248 //=======================================================================
249 void AIS_LengthDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
250 {
251   myDrawer->SetDimLengthModelUnits (theUnits);
252 }
253
254 //=======================================================================
255 //function : SetDisplayUnits
256 //purpose  :
257 //=======================================================================
258 void AIS_LengthDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
259 {
260   myDrawer->SetDimLengthDisplayUnits (theUnits);
261 }
262
263 //=======================================================================
264 //function : ComputeValue
265 //purpose  : 
266 //=======================================================================
267 Standard_Real AIS_LengthDimension::ComputeValue() const
268 {
269   if (!IsValid())
270     return 0.0;
271
272   if (!myHasCustomDirection)
273     return myFirstPoint.Distance (mySecondPoint);
274
275   return fabs (gp_Vec(myFirstPoint, mySecondPoint).Dot (myDirection));
276 }
277
278 //=======================================================================
279 //function : Compute
280 //purpose  : 
281 //=======================================================================
282 void AIS_LengthDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
283                                    const Handle(Prs3d_Presentation)& thePresentation,
284                                    const Standard_Integer theMode)
285 {
286   mySelectionGeom.Clear (theMode);
287
288   if (!IsValid())
289   {
290     return;
291   }
292
293   DrawLinearDimension (thePresentation, theMode, myFirstPoint, mySecondPoint);
294 }
295
296  //=======================================================================
297 //function : ComputeFlyoutLinePoints
298 //purpose  : 
299 //=======================================================================
300 void AIS_LengthDimension::ComputeFlyoutLinePoints (const gp_Pnt& theFirstPoint, const gp_Pnt& theSecondPoint,
301                                                    gp_Pnt& theLineBegPoint, gp_Pnt& theLineEndPoint)
302 {
303   if (!myHasCustomDirection)
304   {
305     AIS_Dimension::ComputeFlyoutLinePoints (theFirstPoint, theSecondPoint, theLineBegPoint, theLineEndPoint);
306     return;
307   }
308
309   // find scalar of projection target vector (from start to second point) to flyout vector
310   gp_Ax1 aPlaneNormal = GetPlane().Axis();
311   gp_Vec aFlyoutNormalizedDir(aPlaneNormal.Direction() ^ myDirection);
312   aFlyoutNormalizedDir.Normalize();
313   Standard_Real aTargetProjectedToFlyout = gp_Vec(theFirstPoint, theSecondPoint).Dot (aFlyoutNormalizedDir);
314
315   gp_Dir aFlyoutVector = aFlyoutNormalizedDir;
316   // create lines for layouts
317   gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
318   gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
319
320   // Get flyout end points
321   theLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint)  + GetFlyout() + aTargetProjectedToFlyout, aLine1);
322   theLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
323 }
324
325 //=======================================================================
326 //function : ComputeFlyoutSelection
327 //purpose  : 
328 //=======================================================================
329 void AIS_LengthDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
330                                                   const Handle(SelectMgr_EntityOwner)& theEntityOwner)
331 {
332   if (!IsValid())
333   {
334     return;
335   }
336
337   ComputeLinearFlyouts (theSelection, theEntityOwner, myFirstPoint, mySecondPoint);
338 }
339
340 //=======================================================================
341 //function : IsValidPoints
342 //purpose  :
343 //=======================================================================
344 Standard_Boolean AIS_LengthDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
345                                                      const gp_Pnt& theSecondPoint) const
346 {
347   return theFirstPoint.Distance (theSecondPoint) > Precision::Confusion();
348 }
349
350 //=======================================================================
351 //function : InitTwoEdgesLength
352 //purpose  : Initialization of dimension between two linear edges
353 //=======================================================================
354 Standard_Boolean AIS_LengthDimension::InitTwoEdgesLength (const TopoDS_Edge& theFirstEdge,
355                                                           const TopoDS_Edge& theSecondEdge,
356                                                           gp_Dir& theDirAttach)
357 {
358   BRepAdaptor_Curve aFirstCurveAdapt (theFirstEdge);
359   if (aFirstCurveAdapt.GetType() != GeomAbs_Line)
360   {
361     return Standard_False;
362   }
363
364   BRepAdaptor_Curve aSecondCurveAdapt (theSecondEdge);
365   if (aSecondCurveAdapt.GetType() != GeomAbs_Line)
366   {
367     return Standard_False;
368   }
369
370   Handle(Geom_Curve) aFirstCurve;
371   Handle(Geom_Curve) aSecondCurve;
372
373   gp_Pnt aPoint11 (gp::Origin());
374   gp_Pnt aPoint12 (gp::Origin());
375   gp_Pnt aPoint21 (gp::Origin());
376   gp_Pnt aPoint22 (gp::Origin());
377   Standard_Boolean isFirstInfinite  = Standard_False;
378   Standard_Boolean isSecondInfinite = Standard_False;
379
380   if (!AIS::ComputeGeometry (theFirstEdge, theSecondEdge,
381                              aFirstCurve, aSecondCurve,
382                              aPoint11, aPoint12,
383                              aPoint21, aPoint22,
384                              isFirstInfinite,
385                              isSecondInfinite))
386   {
387     return Standard_False;
388   }
389
390   const Handle(Geom_Line) aFirstLine = Handle(Geom_Line)::DownCast (aFirstCurve);
391   const Handle(Geom_Line) aSecondLine = Handle(Geom_Line)::DownCast (aSecondCurve);
392
393   if (!aFirstLine->Lin().Direction().IsParallel (aSecondLine->Lin().Direction(),Precision::Angular()))
394   {
395     return Standard_False;
396   }
397
398   theDirAttach = aFirstLine->Lin().Direction();
399
400   gp_Pnt aPoint;
401
402   if (!isFirstInfinite)
403   {
404     if (AIS::Nearest (aSecondCurve, aPoint11, aPoint21, aPoint22, aPoint))
405     {
406       myFirstPoint = aPoint11;
407       mySecondPoint = aPoint;
408       return IsValidPoints (myFirstPoint, mySecondPoint);
409     }
410     else if (AIS::Nearest (aSecondCurve, aPoint12, aPoint21, aPoint22, aPoint))
411     {
412       myFirstPoint = aPoint12;
413       mySecondPoint = aPoint;
414       return IsValidPoints (myFirstPoint, mySecondPoint);
415     }
416   }
417
418   if (!isSecondInfinite)
419   {
420     if (AIS::Nearest (aFirstCurve, aPoint21, aPoint11, aPoint12, aPoint))
421     {
422       myFirstPoint = aPoint;
423       mySecondPoint = aPoint21;
424       return IsValidPoints (myFirstPoint, mySecondPoint);
425     }
426     if (AIS::Nearest (aFirstCurve, aPoint22, aPoint11, aPoint12, aPoint))
427     {
428       myFirstPoint = aPoint;
429       mySecondPoint = aPoint22;
430       return IsValidPoints (myFirstPoint, mySecondPoint);
431     }
432   }
433
434   GeomAPI_ExtremaCurveCurve anExtrema (aFirstCurve, aSecondCurve);
435   anExtrema.NearestPoints (myFirstPoint, mySecondPoint);
436   return IsValidPoints (myFirstPoint, mySecondPoint);
437 }
438
439 //=======================================================================
440 //function : InitEdgeVertexLength
441 //purpose  : for first edge and second vertex shapes
442 //=======================================================================
443 Standard_Boolean AIS_LengthDimension::InitEdgeVertexLength (const TopoDS_Edge& theEdge,
444                                                             const TopoDS_Vertex& theVertex,
445                                                             gp_Dir& theEdgeDir,
446                                                             Standard_Boolean isInfinite)
447 {
448   gp_Pnt anEdgePoint1 (gp::Origin());
449   gp_Pnt anEdgePoint2 (gp::Origin());
450   Handle(Geom_Curve) aCurve;
451
452   if (!AIS::ComputeGeometry (theEdge, aCurve, anEdgePoint1, anEdgePoint2, isInfinite))
453   {
454     return Standard_False;
455   }
456
457   myFirstPoint = BRep_Tool::Pnt (theVertex);
458
459   Handle(Geom_Line) aGeomLine (Handle(Geom_Line)::DownCast (aCurve));
460   const gp_Lin& aLin = aGeomLine->Lin();
461
462   // Get direction of edge to build plane automatically.
463   theEdgeDir = aLin.Direction();
464
465   mySecondPoint = AIS::Nearest (aLin, myFirstPoint);
466
467   return IsValidPoints (myFirstPoint, mySecondPoint);
468 }
469
470 //=======================================================================
471 //function : InitEdgeFaceLength
472 //purpose  : 
473 //=======================================================================
474 Standard_Boolean AIS_LengthDimension::InitEdgeFaceLength (const TopoDS_Edge& theEdge,
475                                                           const TopoDS_Face& theFace,
476                                                           gp_Dir& theEdgeDir)
477 {
478   theEdgeDir = gp::DX();
479
480   // Find attachment points (closest distance between the edge and the face)
481   BRepExtrema_DistShapeShape aDistAdaptor (theEdge, theFace, Extrema_ExtFlag_MIN);
482   if (!aDistAdaptor.IsDone() || aDistAdaptor.NbSolution() <1)
483   {
484     return Standard_False;
485   }
486   myFirstPoint = aDistAdaptor.PointOnShape1 (1);
487   mySecondPoint = aDistAdaptor.PointOnShape2 (1);
488
489   // Take direction for dimension line (will be orthogonalized later) parallel to edge
490   BRepAdaptor_Curve aCurveAdaptor (theEdge);
491   Standard_Real aParam;
492   if (aDistAdaptor.SupportOnShape1 (1).ShapeType() == TopAbs_EDGE)
493   {
494     aDistAdaptor.ParOnEdgeS1 (1, aParam);
495   }
496   else
497   {
498     Standard_Real aD1 = aCurveAdaptor.Value(aCurveAdaptor.FirstParameter()).SquareDistance (myFirstPoint);
499     Standard_Real aD2 = aCurveAdaptor.Value(aCurveAdaptor.LastParameter()).SquareDistance (myFirstPoint);
500     aParam = (aD1 < aD2 ? aCurveAdaptor.FirstParameter() : aCurveAdaptor.LastParameter());
501   }
502   gp_Pnt aP;
503   gp_Vec aV;
504   aCurveAdaptor.D1 (aParam, aP, aV);
505   if (aV.SquareMagnitude() > gp::Resolution())
506   {
507     theEdgeDir = aV;
508   }
509
510   // reverse direction if parameter is close to the end of the curve,
511   // to reduce chances to have overlapping between dimension line and edge
512   if (Abs (aParam - aCurveAdaptor.FirstParameter()) < Abs (aParam - aCurveAdaptor.LastParameter()))
513   {
514     theEdgeDir.Reverse();
515   }
516
517   return IsValidPoints (myFirstPoint, mySecondPoint);
518 }
519
520 //=======================================================================
521 //function : InitTwoShapesPoints
522 //purpose  : Initialization of two points where dimension layouts
523 //           will be attached
524 //=======================================================================
525 Standard_Boolean AIS_LengthDimension::InitTwoShapesPoints (const TopoDS_Shape& theFirstShape,
526                                                            const TopoDS_Shape& theSecondShape,
527                                                            gp_Pln& theComputedPlane,
528                                                            Standard_Boolean& theIsPlaneComputed)
529 {
530   theIsPlaneComputed = Standard_False;
531   gp_Dir aDirAttach;
532   Standard_Boolean isInfinite = Standard_False;
533   Standard_Boolean isSuccess  = Standard_False;
534   switch (theFirstShape.ShapeType())
535   {
536     case TopAbs_FACE:
537     {
538       // Initialization for face
539       gp_Pln aFirstPlane;
540       Handle(Geom_Surface) aFirstSurface;
541       AIS_KindOfSurface aFirstSurfKind;
542       Standard_Real aFirstOffset;
543
544       TopoDS_Face aFirstFace = TopoDS::Face (theFirstShape);
545
546       AIS::InitFaceLength (TopoDS::Face (theFirstShape),
547                            aFirstPlane,
548                            aFirstSurface,
549                            aFirstSurfKind,
550                            aFirstOffset);
551
552       if (theSecondShape.ShapeType() == TopAbs_FACE)
553       {
554         // Initialization for face
555         myGeometryType = GeometryType_Faces;
556         gp_Pln aSecondPlane;
557         Handle(Geom_Surface) aSecondSurface;
558         AIS_KindOfSurface aSecondSurfKind;
559         Standard_Real aSecondOffset;
560
561         TopoDS_Face aSecondFace = TopoDS::Face (theSecondShape);
562
563         AIS::InitFaceLength (aSecondFace,
564                              aSecondPlane,
565                              aSecondSurface,
566                              aSecondSurfKind,
567                              aSecondOffset);
568
569         if (aFirstSurfKind == AIS_KOS_Plane)
570         {
571           if (!aFirstPlane.Axis().Direction().IsParallel (aSecondPlane.Axis().Direction(), Precision::Angular()))
572           {
573             return Standard_False;
574           }
575
576           TopExp_Explorer anExplorer (theFirstShape, TopAbs_VERTEX);
577
578           // In case of infinite planes
579           if (!anExplorer.More())
580           {
581             myFirstPoint = aFirstPlane.Location();
582           }
583           else
584           {
585             myFirstPoint = BRep_Tool::Pnt (TopoDS::Vertex (anExplorer.Current()));
586           }
587
588           mySecondPoint = AIS::ProjectPointOnPlane (myFirstPoint, aSecondPlane);
589
590           Standard_Real anU, aV;
591           ElSLib::Parameters (aSecondPlane, mySecondPoint, anU, aV);
592
593           BRepTopAdaptor_FClass2d aClassifier (aSecondFace, Precision::Confusion());
594           TopAbs_State aState = aClassifier.Perform (gp_Pnt2d (anU, aV), Standard_False);
595
596           if (aState == TopAbs_OUT || aState == TopAbs_UNKNOWN)
597           {
598             mySecondPoint = AIS::Nearest (aSecondFace, myFirstPoint);
599           }
600
601           isSuccess = IsValidPoints (myFirstPoint, mySecondPoint);
602           if (isSuccess)
603           {
604             theComputedPlane = ComputePlane (aFirstPlane.Position().XDirection());
605             theIsPlaneComputed = Standard_True;
606           }
607         }
608         else // curvilinear faces
609         {
610           Standard_Real aU1Min, aV1Min, aU1Max, aV1Max;
611           Standard_Real aU2Min, aV2Min, aU2Max, aV2Max;
612           BRepTools::UVBounds (aFirstFace, aU1Min, aU1Max, aV1Min,  aV1Max);
613           BRepTools::UVBounds (aSecondFace, aU2Min, aU2Max, aV2Min, aV2Max);
614
615           GeomAPI_ExtremaSurfaceSurface anExtrema (aFirstSurface, aSecondSurface,
616                                                    aU1Min, aU1Max, aV1Min, aV1Max,
617                                                    aU2Min, aU2Max, aV2Min, aV2Max);
618
619           Standard_Real aU1, aV1, aU2, aV2;
620           anExtrema.LowerDistanceParameters (aU1, aV1, aU2, aV2);
621           myFirstPoint = BRep_Tool::Surface (aFirstFace)->Value (aU1, aV1);
622           mySecondPoint = BRep_Tool::Surface (aSecondFace)->Value (aU2, aV2);
623
624           // Adjust automatic plane
625           gp_Ax2 aLocalAxes (myFirstPoint, gce_MakeDir (myFirstPoint, mySecondPoint));
626           aDirAttach = gce_MakeDir (aLocalAxes.XDirection ());
627
628           // Check points
629           isSuccess = IsValidPoints (myFirstPoint, mySecondPoint);
630           if (isSuccess)
631           {
632             theComputedPlane = ComputePlane (aDirAttach);
633             theIsPlaneComputed = Standard_True;
634           }
635         }
636
637         return isSuccess && IsValidPoints (myFirstPoint, mySecondPoint);
638       }
639       else if (theSecondShape.ShapeType() == TopAbs_EDGE)
640       {
641         myGeometryType = GeometryType_EdgeFace;
642         isSuccess = InitEdgeFaceLength (TopoDS::Edge (theSecondShape),
643                                         TopoDS::Face (theFirstShape),
644                                         aDirAttach);
645
646         if (isSuccess)
647         {
648           theComputedPlane = ComputePlane (aDirAttach);
649           theIsPlaneComputed = Standard_True;
650         }
651
652         return isSuccess;
653       }
654     }
655     break;
656
657     case TopAbs_EDGE:
658     {
659       if (theSecondShape.ShapeType() == TopAbs_VERTEX)
660       {
661         myGeometryType = GeometryType_EdgeVertex;
662         isSuccess = InitEdgeVertexLength (TopoDS::Edge (theFirstShape),
663                                           TopoDS::Vertex (theSecondShape),
664                                           aDirAttach,
665                                           isInfinite);
666
667         if (isSuccess)
668         {
669           theComputedPlane = ComputePlane (aDirAttach);
670           theIsPlaneComputed = Standard_True;
671         }
672
673         return isSuccess;
674       }
675       else if (theSecondShape.ShapeType() == TopAbs_EDGE)
676       {
677         myGeometryType = GeometryType_Edges;
678         isSuccess = InitTwoEdgesLength (TopoDS::Edge (theFirstShape),
679                                         TopoDS::Edge (theSecondShape),
680                                         aDirAttach);
681
682         if (isSuccess)
683         {
684           theComputedPlane = ComputePlane (aDirAttach);
685           theIsPlaneComputed = Standard_True;
686         }
687
688         return isSuccess;
689       }
690       else if (theSecondShape.ShapeType() == TopAbs_FACE)
691       {
692         myGeometryType = GeometryType_EdgeFace;
693         isSuccess = InitEdgeFaceLength (TopoDS::Edge (theFirstShape),
694                                         TopoDS::Face (theSecondShape),
695                                         aDirAttach);
696
697         if (isSuccess)
698         {
699           theComputedPlane = ComputePlane (aDirAttach);
700           theIsPlaneComputed = Standard_True;
701         }
702
703         return isSuccess;
704       }
705     }
706     break;
707
708     case TopAbs_VERTEX:
709     {
710       if (theSecondShape.ShapeType() == TopAbs_VERTEX)
711       {
712         myGeometryType = GeometryType_Points;
713         myFirstPoint  = BRep_Tool::Pnt (TopoDS::Vertex (theFirstShape));
714         mySecondPoint = BRep_Tool::Pnt (TopoDS::Vertex (theSecondShape));
715
716         return IsValidPoints (myFirstPoint, mySecondPoint);
717       }
718       else if (theSecondShape.ShapeType() == TopAbs_EDGE)
719       {
720         myGeometryType = GeometryType_EdgeVertex;
721         isSuccess =  InitEdgeVertexLength (TopoDS::Edge(theSecondShape),
722                                            TopoDS::Vertex(theFirstShape),
723                                            aDirAttach,
724                                            isInfinite);
725         if (isSuccess)
726         {
727           theComputedPlane = ComputePlane (aDirAttach);
728           theIsPlaneComputed = Standard_True;
729         }
730
731         return isSuccess;
732       }
733     }
734     break;
735
736     case TopAbs_COMPOUND:
737     case TopAbs_COMPSOLID:
738     case TopAbs_SOLID:
739     case TopAbs_SHELL:
740     case TopAbs_WIRE:
741     case TopAbs_SHAPE:
742       break;
743   }
744
745   return Standard_False;
746 }
747
748 //=======================================================================
749 //function : InitOneShapePoints
750 //purpose  : Initialization of two points where dimension layouts
751 //           will be attached
752 // Attention: 1) <theShape> can be only the edge in currect implementation
753 //            2) No length for infinite edge
754 //=======================================================================
755 Standard_Boolean AIS_LengthDimension::InitOneShapePoints (const TopoDS_Shape& theShape)
756 {
757   if (theShape.ShapeType() != TopAbs_EDGE)
758   {
759     return Standard_False;
760   }
761
762   TopoDS_Edge anEdge = TopoDS::Edge (theShape);
763
764   BRepAdaptor_Curve aBrepCurve(anEdge);
765   Standard_Real aFirst = aBrepCurve.FirstParameter();
766   Standard_Real aLast  = aBrepCurve.LastParameter();
767
768   if (aBrepCurve.GetType() != GeomAbs_Line)
769   {
770     return Standard_False;
771   }
772
773   Standard_Boolean isInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
774   if (isInfinite)
775   {
776     return Standard_False;
777   }
778
779   myFirstPoint  = aBrepCurve.Value (aBrepCurve.FirstParameter());
780   mySecondPoint = aBrepCurve.Value (aBrepCurve.LastParameter());
781
782   return IsValidPoints (myFirstPoint, mySecondPoint);
783 }
784
785 //=======================================================================
786 //function : GetTextPosition
787 //purpose  : 
788 //=======================================================================
789 const gp_Pnt AIS_LengthDimension::GetTextPosition() const
790 {
791   if (IsTextPositionCustom())
792   {
793     return myFixedTextPosition;
794   }
795
796   // Counts text position according to the dimension parameters
797   return GetTextPositionForLinear (myFirstPoint, mySecondPoint);
798 }
799
800 //=======================================================================
801 //function : SetTextPosition
802 //purpose  : 
803 //=======================================================================
804 void AIS_LengthDimension::SetTextPosition (const gp_Pnt& theTextPos)
805 {
806   if (!IsValid())
807   {
808     return;
809   }
810
811   myIsTextPositionFixed = Standard_True;
812   myFixedTextPosition = theTextPos;
813
814   SetToUpdate();
815 }
816
817 //=======================================================================
818 //function : SetDirection
819 //purpose  : 
820 //=======================================================================
821 void AIS_LengthDimension::SetDirection (const gp_Dir& theDirection, const Standard_Boolean theUseDirection)
822 {
823   myHasCustomDirection = theUseDirection;
824   if (myHasCustomDirection)
825     myDirection = theDirection;
826 }