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