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