0025180: Visualization - Homogeneous transformation API in TKV3d
[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   thePresentation->Clear();
276   mySelectionGeom.Clear (theMode);
277
278   if (!IsValid())
279   {
280     return;
281   }
282
283   DrawLinearDimension (thePresentation, theMode, myFirstPoint, mySecondPoint);
284 }
285
286 //=======================================================================
287 //function : ComputeFlyoutSelection
288 //purpose  : 
289 //=======================================================================
290 void AIS_LengthDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
291                                                   const Handle(SelectMgr_EntityOwner)& theEntityOwner)
292 {
293   if (!IsValid())
294   {
295     return;
296   }
297
298   ComputeLinearFlyouts (theSelection, theEntityOwner, myFirstPoint, mySecondPoint);
299 }
300
301 //=======================================================================
302 //function : IsValidPoints
303 //purpose  :
304 //=======================================================================
305 Standard_Boolean AIS_LengthDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
306                                                      const gp_Pnt& theSecondPoint) const
307 {
308   return theFirstPoint.Distance (theSecondPoint) > Precision::Confusion();
309 }
310
311 //=======================================================================
312 //function : InitTwoEdgesLength
313 //purpose  : Initialization of dimension between two linear edges
314 //=======================================================================
315 Standard_Boolean AIS_LengthDimension::InitTwoEdgesLength (const TopoDS_Edge& theFirstEdge,
316                                                           const TopoDS_Edge& theSecondEdge,
317                                                           gp_Dir& theDirAttach)
318 {
319   BRepAdaptor_Curve aFirstCurveAdapt (theFirstEdge);
320   if (aFirstCurveAdapt.GetType() != GeomAbs_Line)
321   {
322     return Standard_False;
323   }
324
325   BRepAdaptor_Curve aSecondCurveAdapt (theSecondEdge);
326   if (aSecondCurveAdapt.GetType() != GeomAbs_Line)
327   {
328     return Standard_False;
329   }
330
331   Handle(Geom_Curve) aFirstCurve;
332   Handle(Geom_Curve) aSecondCurve;
333
334   gp_Pnt aPoint11 (gp::Origin());
335   gp_Pnt aPoint12 (gp::Origin());
336   gp_Pnt aPoint21 (gp::Origin());
337   gp_Pnt aPoint22 (gp::Origin());
338   Standard_Boolean isFirstInfinite  = Standard_False;
339   Standard_Boolean isSecondInfinite = Standard_False;
340
341   if (!AIS::ComputeGeometry (theFirstEdge, theSecondEdge,
342                              aFirstCurve, aSecondCurve,
343                              aPoint11, aPoint12,
344                              aPoint21, aPoint22,
345                              isFirstInfinite,
346                              isSecondInfinite))
347   {
348     return Standard_False;
349   }
350
351   const Handle(Geom_Line) aFirstLine = Handle(Geom_Line)::DownCast (aFirstCurve);
352   const Handle(Geom_Line) aSecondLine = Handle(Geom_Line)::DownCast (aSecondCurve);
353
354   if (!aFirstLine->Lin().Direction().IsParallel (aSecondLine->Lin().Direction(),Precision::Angular()))
355   {
356     return Standard_False;
357   }
358
359   theDirAttach = aFirstLine->Lin().Direction();
360
361   gp_Pnt aPoint;
362
363   if (!isFirstInfinite)
364   {
365     if (AIS::Nearest (aSecondCurve, aPoint11, aPoint21, aPoint22, aPoint))
366     {
367       myFirstPoint = aPoint11;
368       mySecondPoint = aPoint;
369       return IsValidPoints (myFirstPoint, mySecondPoint);
370     }
371     else if (AIS::Nearest (aSecondCurve, aPoint12, aPoint21, aPoint22, aPoint))
372     {
373       myFirstPoint = aPoint12;
374       mySecondPoint = aPoint;
375       return IsValidPoints (myFirstPoint, mySecondPoint);
376     }
377   }
378
379   if (!isSecondInfinite)
380   {
381     if (AIS::Nearest (aFirstCurve, aPoint21, aPoint11, aPoint12, aPoint))
382     {
383       myFirstPoint = aPoint;
384       mySecondPoint = aPoint21;
385       return IsValidPoints (myFirstPoint, mySecondPoint);
386     }
387     if (AIS::Nearest (aFirstCurve, aPoint22, aPoint11, aPoint12, aPoint))
388     {
389       myFirstPoint = aPoint;
390       mySecondPoint = aPoint22;
391       return IsValidPoints (myFirstPoint, mySecondPoint);
392     }
393   }
394
395   GeomAPI_ExtremaCurveCurve anExtrema (aFirstCurve, aSecondCurve);
396   anExtrema.NearestPoints (myFirstPoint, mySecondPoint);
397   return IsValidPoints (myFirstPoint, mySecondPoint);
398 }
399
400 //=======================================================================
401 //function : InitEdgeVertexLength
402 //purpose  : for first edge and second vertex shapes
403 //=======================================================================
404 Standard_Boolean AIS_LengthDimension::InitEdgeVertexLength (const TopoDS_Edge& theEdge,
405                                                             const TopoDS_Vertex& theVertex,
406                                                             gp_Dir& theEdgeDir,
407                                                             Standard_Boolean isInfinite)
408 {
409   gp_Pnt anEdgePoint1 (gp::Origin());
410   gp_Pnt anEdgePoint2 (gp::Origin());
411   Handle(Geom_Curve) aCurve;
412
413   if (!AIS::ComputeGeometry (theEdge, aCurve, anEdgePoint1, anEdgePoint2, isInfinite))
414   {
415     return Standard_False;
416   }
417
418   myFirstPoint = BRep_Tool::Pnt (theVertex);
419
420   Handle(Geom_Line) aGeomLine (Handle(Geom_Line)::DownCast (aCurve));
421   const gp_Lin& aLin = aGeomLine->Lin();
422
423   // Get direction of edge to build plane automatically.
424   theEdgeDir = aLin.Direction();
425
426   mySecondPoint = AIS::Nearest (aLin, myFirstPoint);
427
428   return IsValidPoints (myFirstPoint, mySecondPoint);
429 }
430
431 //=======================================================================
432 //function : InitEdgeFaceLength
433 //purpose  : 
434 //=======================================================================
435 Standard_Boolean AIS_LengthDimension::InitEdgeFaceLength (const TopoDS_Edge& theEdge,
436                                                           const TopoDS_Face& theFace,
437                                                           gp_Dir& theEdgeDir)
438 {
439   // Compute edge direction
440   BRepAdaptor_Curve aCurveAdaptor (theEdge);
441   Handle(Geom_Curve) aCurve = Handle(Geom_Curve)::DownCast (aCurveAdaptor.Curve().Curve()->Transformed (aCurveAdaptor.Trsf()));
442   if (aCurve.IsNull())
443   {
444     return Standard_False;
445   }
446   Standard_Real aFirst = aCurveAdaptor.FirstParameter();
447   Standard_Real aLast = aCurveAdaptor.LastParameter();
448   gp_Pnt aFirstPoint = !Precision::IsInfinite (aFirst) ? aCurve->Value (aFirst) : gp::Origin();
449   gp_Pnt aSecondPoint = !Precision::IsInfinite (aLast) ? aCurve->Value (aLast) : gp::Origin();
450   gce_MakeDir aMakeDir (aFirstPoint, aSecondPoint);
451   if (!aMakeDir.IsDone())
452   {
453     return Standard_False;
454   }
455   theEdgeDir = aMakeDir.Value();
456
457   // Find attachment points
458   BRepExtrema_DistShapeShape aDistAdaptor (theEdge, theFace, Extrema_ExtFlag_MIN);
459   if (!aDistAdaptor.IsDone())
460   {
461     return Standard_False;
462   }
463   myFirstPoint = aDistAdaptor.PointOnShape1 (1);
464   mySecondPoint = aDistAdaptor.PointOnShape2 (1);
465
466   return IsValidPoints (myFirstPoint, mySecondPoint);
467 }
468
469 //=======================================================================
470 //function : InitTwoShapesPoints
471 //purpose  : Initialization of two points where dimension layouts
472 //           will be attached
473 //=======================================================================
474 Standard_Boolean AIS_LengthDimension::InitTwoShapesPoints (const TopoDS_Shape& theFirstShape,
475                                                            const TopoDS_Shape& theSecondShape,
476                                                            gp_Pln& theComputedPlane,
477                                                            Standard_Boolean& theIsPlaneComputed)
478 {
479   theIsPlaneComputed = Standard_False;
480   gp_Dir aDirAttach;
481   Standard_Boolean isInfinite = Standard_False;
482   Standard_Boolean isSuccess  = Standard_False;
483   switch (theFirstShape.ShapeType())
484   {
485     case TopAbs_FACE:
486     {
487       // Initialization for face
488       gp_Pln aFirstPlane;
489       Handle(Geom_Surface) aFirstSurface;
490       AIS_KindOfSurface aFirstSurfKind;
491       Standard_Real aFirstOffset;
492
493       TopoDS_Face aFirstFace = TopoDS::Face (theFirstShape);
494
495       AIS::InitFaceLength (TopoDS::Face (theFirstShape),
496                            aFirstPlane,
497                            aFirstSurface,
498                            aFirstSurfKind,
499                            aFirstOffset);
500
501       if (theSecondShape.ShapeType() == TopAbs_FACE)
502       {
503         // Initialization for face
504         myGeometryType = GeometryType_Faces;
505         gp_Pln aSecondPlane;
506         Handle(Geom_Surface) aSecondSurface;
507         AIS_KindOfSurface aSecondSurfKind;
508         Standard_Real aSecondOffset;
509
510         TopoDS_Face aSecondFace = TopoDS::Face (theSecondShape);
511
512         AIS::InitFaceLength (aSecondFace,
513                              aSecondPlane,
514                              aSecondSurface,
515                              aSecondSurfKind,
516                              aSecondOffset);
517
518         if (aFirstSurfKind == AIS_KOS_Plane)
519         {
520           if (!aFirstPlane.Axis().Direction().IsParallel (aSecondPlane.Axis().Direction(), Precision::Angular()))
521           {
522             return Standard_False;
523           }
524
525           TopExp_Explorer anExplorer (theFirstShape, TopAbs_VERTEX);
526
527           // In case of infinite planes
528           if (!anExplorer.More())
529           {
530             myFirstPoint = aFirstPlane.Location();
531           }
532           else
533           {
534             myFirstPoint = BRep_Tool::Pnt (TopoDS::Vertex (anExplorer.Current()));
535           }
536
537           mySecondPoint = AIS::ProjectPointOnPlane (myFirstPoint, aSecondPlane);
538
539           Quantity_Parameter anU, aV;
540           ElSLib::Parameters (aSecondPlane, mySecondPoint, anU, aV);
541
542           BRepTopAdaptor_FClass2d aClassifier (aSecondFace, Precision::Confusion());
543           TopAbs_State aState = aClassifier.Perform (gp_Pnt2d (anU, aV), Standard_False);
544
545           if (aState == TopAbs_OUT || aState == TopAbs_UNKNOWN)
546           {
547             mySecondPoint = AIS::Nearest (aSecondFace, myFirstPoint);
548           }
549
550           isSuccess = IsValidPoints (myFirstPoint, mySecondPoint);
551           if (isSuccess)
552           {
553             theComputedPlane = ComputePlane (aFirstPlane.Position().XDirection());
554             theIsPlaneComputed = Standard_True;
555           }
556         }
557         else // curvilinear faces
558         {
559           Standard_Real aU1Min, aV1Min, aU1Max, aV1Max;
560           Standard_Real aU2Min, aV2Min, aU2Max, aV2Max;
561           BRepTools::UVBounds (aFirstFace, aU1Min, aU1Max, aV1Min,  aV1Max);
562           BRepTools::UVBounds (aSecondFace, aU2Min, aU2Max, aV2Min, aV2Max);
563
564           GeomAPI_ExtremaSurfaceSurface anExtrema (aFirstSurface, aSecondSurface,
565                                                    aU1Min, aU1Max, aV1Min, aV1Max,
566                                                    aU2Min, aU2Max, aV2Min, aV2Max);
567
568           Standard_Real aU1, aV1, aU2, aV2;
569           anExtrema.LowerDistanceParameters (aU1, aV1, aU2, aV2);
570           myFirstPoint = BRep_Tool::Surface (aFirstFace)->Value (aU1, aV1);
571           mySecondPoint = BRep_Tool::Surface (aSecondFace)->Value (aU2, aV2);
572
573           // Adjust automatic plane
574           gp_Ax2 aLocalAxes (myFirstPoint, gce_MakeDir (myFirstPoint, mySecondPoint));
575           aDirAttach = gce_MakeDir (aLocalAxes.XDirection ());
576
577           // Check points
578           isSuccess = IsValidPoints (myFirstPoint, mySecondPoint);
579           if (isSuccess)
580           {
581             theComputedPlane = ComputePlane (aDirAttach);
582             theIsPlaneComputed = Standard_True;
583           }
584         }
585
586         return isSuccess && IsValidPoints (myFirstPoint, mySecondPoint);
587       }
588       else if (theSecondShape.ShapeType() == TopAbs_EDGE)
589       {
590         myGeometryType = GeometryType_EdgeFace;
591         isSuccess = InitEdgeFaceLength (TopoDS::Edge (theSecondShape),
592                                         TopoDS::Face (theFirstShape),
593                                         aDirAttach);
594
595         if (isSuccess)
596         {
597           theComputedPlane = ComputePlane (aDirAttach);
598           theIsPlaneComputed = Standard_True;
599         }
600
601         return isSuccess;
602       }
603     }
604     break;
605
606     case TopAbs_EDGE:
607     {
608       if (theSecondShape.ShapeType() == TopAbs_VERTEX)
609       {
610         myGeometryType = GeometryType_EdgeVertex;
611         isSuccess = InitEdgeVertexLength (TopoDS::Edge (theFirstShape),
612                                           TopoDS::Vertex (theSecondShape),
613                                           aDirAttach,
614                                           isInfinite);
615
616         if (isSuccess)
617         {
618           theComputedPlane = ComputePlane (aDirAttach);
619           theIsPlaneComputed = Standard_True;
620         }
621
622         return isSuccess;
623       }
624       else if (theSecondShape.ShapeType() == TopAbs_EDGE)
625       {
626         myGeometryType = GeometryType_Edges;
627         isSuccess = InitTwoEdgesLength (TopoDS::Edge (theFirstShape),
628                                         TopoDS::Edge (theSecondShape),
629                                         aDirAttach);
630
631         if (isSuccess)
632         {
633           theComputedPlane = ComputePlane (aDirAttach);
634           theIsPlaneComputed = Standard_True;
635         }
636
637         return isSuccess;
638       }
639       else if (theSecondShape.ShapeType() == TopAbs_FACE)
640       {
641         myGeometryType = GeometryType_EdgeFace;
642         isSuccess = InitEdgeFaceLength (TopoDS::Edge (theFirstShape),
643                                         TopoDS::Face (theSecondShape),
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_VERTEX:
658     {
659       if (theSecondShape.ShapeType() == TopAbs_VERTEX)
660       {
661         myGeometryType = GeometryType_Points;
662         myFirstPoint  = BRep_Tool::Pnt (TopoDS::Vertex (theFirstShape));
663         mySecondPoint = BRep_Tool::Pnt (TopoDS::Vertex (theSecondShape));
664
665         return IsValidPoints (myFirstPoint, mySecondPoint);
666       }
667       else if (theSecondShape.ShapeType() == TopAbs_EDGE)
668       {
669         myGeometryType = GeometryType_EdgeVertex;
670         isSuccess =  InitEdgeVertexLength (TopoDS::Edge(theSecondShape),
671                                            TopoDS::Vertex(theFirstShape),
672                                            aDirAttach,
673                                            isInfinite);
674         if (isSuccess)
675         {
676           theComputedPlane = ComputePlane (aDirAttach);
677           theIsPlaneComputed = Standard_True;
678         }
679
680         return isSuccess;
681       }
682     }
683     break;
684
685     case TopAbs_COMPOUND:
686     case TopAbs_COMPSOLID:
687     case TopAbs_SOLID:
688     case TopAbs_SHELL:
689     case TopAbs_WIRE:
690     case TopAbs_SHAPE:
691       break;
692   }
693
694   return Standard_False;
695 }
696
697 //=======================================================================
698 //function : InitOneShapePoints
699 //purpose  : Initialization of two points where dimension layouts
700 //           will be attached
701 // Attention: 1) <theShape> can be only the edge in currect implementation
702 //            2) No length for infinite edge
703 //=======================================================================
704 Standard_Boolean AIS_LengthDimension::InitOneShapePoints (const TopoDS_Shape& theShape)
705 {
706   if (theShape.ShapeType() != TopAbs_EDGE)
707   {
708     return Standard_False;
709   }
710
711   TopoDS_Edge anEdge = TopoDS::Edge (theShape);
712
713   BRepAdaptor_Curve aBrepCurve(anEdge);
714   Standard_Real aFirst = aBrepCurve.FirstParameter();
715   Standard_Real aLast  = aBrepCurve.LastParameter();
716
717   if (aBrepCurve.GetType() != GeomAbs_Line)
718   {
719     return Standard_False;
720   }
721
722   Standard_Boolean isInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
723   if (isInfinite)
724   {
725     return Standard_False;
726   }
727
728   myFirstPoint  = aBrepCurve.Value (aBrepCurve.FirstParameter());
729   mySecondPoint = aBrepCurve.Value (aBrepCurve.LastParameter());
730
731   return IsValidPoints (myFirstPoint, mySecondPoint);
732 }
733
734 //=======================================================================
735 //function : GetTextPosition
736 //purpose  : 
737 //=======================================================================
738 const gp_Pnt AIS_LengthDimension::GetTextPosition() const
739 {
740   if (IsTextPositionCustom())
741   {
742     return myFixedTextPosition;
743   }
744
745   // Counts text position according to the dimension parameters
746   return GetTextPositionForLinear (myFirstPoint, mySecondPoint);
747 }
748
749 //=======================================================================
750 //function : SetTextPosition
751 //purpose  : 
752 //=======================================================================
753 void AIS_LengthDimension::SetTextPosition (const gp_Pnt& theTextPos)
754 {
755   if (!IsValid())
756   {
757     return;
758   }
759
760   myIsTextPositionFixed = Standard_True;
761   myFixedTextPosition = theTextPos;
762
763   SetToUpdate();
764 }