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