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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <AIS_LengthDimension.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepLib_MakeVertex.hxx>
23 #include <BRepTopAdaptor_FClass2d.hxx>
24 #include <BRepTools.hxx>
27 #include <gce_MakeDir.hxx>
28 #include <gce_MakePln.hxx>
29 #include <GeomAPI_ExtremaCurveCurve.hxx>
30 #include <GeomAPI_ExtremaCurveSurface.hxx>
31 #include <GeomAPI_ExtremaSurfaceSurface.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom_Line.hxx>
35 #include <TopExp_Explorer.hxx>
37 IMPLEMENT_STANDARD_HANDLE(AIS_LengthDimension, AIS_Dimension)
38 IMPLEMENT_STANDARD_RTTIEXT(AIS_LengthDimension, AIS_Dimension)
40 //=======================================================================
41 //function : Constructor
42 //purpose : Dimension between two faces
43 //=======================================================================
44 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFirstFace,
45 const TopoDS_Face& theSecondFace)
46 : AIS_Dimension (AIS_KOD_LENGTH)
48 SetMeasuredGeometry (theFirstFace, theSecondFace);
52 //=======================================================================
53 //function : Constructor
54 //purpose : Dimension between two shape
55 //=======================================================================
56 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFace,
57 const TopoDS_Edge& theEdge)
58 : AIS_Dimension (AIS_KOD_LENGTH)
60 SetMeasuredGeometry (theFace, theEdge);
64 //=======================================================================
65 //function : Constructor
66 //purpose : Dimension between two points
67 //=======================================================================
68 AIS_LengthDimension::AIS_LengthDimension (const gp_Pnt& theFirstPoint,
69 const gp_Pnt& theSecondPoint,
70 const gp_Pln& thePlane)
71 : AIS_Dimension (AIS_KOD_LENGTH)
73 SetMeasuredGeometry (theFirstPoint, theSecondPoint, thePlane);
77 //=======================================================================
78 //function : Constructor
79 //purpose : Dimension between two shape
80 //=======================================================================
81 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Shape& theFirstShape,
82 const TopoDS_Shape& theSecondShape,
83 const gp_Pln& thePlane)
84 : AIS_Dimension (AIS_KOD_LENGTH)
86 SetCustomPlane (thePlane);
87 SetMeasuredShapes (theFirstShape, theSecondShape);
91 //=======================================================================
92 //function : Constructor
93 //purpose : Dimension of one edge
94 //=======================================================================
95 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Edge& theEdge,
96 const gp_Pln& thePlane)
97 : AIS_Dimension (AIS_KOD_LENGTH)
99 SetMeasuredGeometry (theEdge, thePlane);
103 //=======================================================================
104 //function : SetMeasuredGeometry
106 //=======================================================================
107 void AIS_LengthDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
108 const gp_Pnt& theSecondPoint,
109 const gp_Pln& thePlane)
111 myFirstPoint = theFirstPoint;
112 mySecondPoint = theSecondPoint;
113 myFirstShape = BRepLib_MakeVertex (myFirstPoint);
114 mySecondShape = BRepLib_MakeVertex (mySecondPoint);
115 myGeometryType = GeometryType_Points;
116 SetCustomPlane (thePlane);
117 myIsValid = IsValidPoints (theFirstPoint, theSecondPoint) && CheckPlane (myPlane);
122 //=======================================================================
123 //function : SetMeasuredGeometry
125 //=======================================================================
126 void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Edge& theEdge,
127 const gp_Pln& thePlane)
129 myFirstShape = theEdge;
130 mySecondShape = TopoDS_Shape();
131 myGeometryType = GeometryType_Edge;
132 SetCustomPlane (thePlane);
133 myIsValid = InitOneShapePoints (myFirstShape) && CheckPlane (myPlane);
138 //=======================================================================
139 //function : SetMeasuredGeometry
141 //=======================================================================
142 void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
143 const TopoDS_Face& theSecondFace)
145 SetMeasuredShapes (theFirstFace, theSecondFace);
148 //=======================================================================
149 //function : SetMeasuredGeometry
151 //=======================================================================
152 void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Face& theFace,
153 const TopoDS_Edge& theEdge)
155 SetMeasuredShapes (theFace, theEdge);
158 //=======================================================================
159 //function : SetMeasuredShapes
161 //=======================================================================
162 void AIS_LengthDimension::SetMeasuredShapes (const TopoDS_Shape& theFirstShape,
163 const TopoDS_Shape& theSecondShape)
165 gp_Pln aComputedPlane;
166 Standard_Boolean isPlaneReturned = Standard_False;
167 myFirstShape = theFirstShape;
168 mySecondShape = theSecondShape;
169 myIsValid = InitTwoShapesPoints (myFirstShape, mySecondShape, aComputedPlane, isPlaneReturned);
171 if (myIsValid && !myIsPlaneCustom)
175 myPlane = aComputedPlane;
179 myIsValid = Standard_False;
183 myIsValid &= CheckPlane (myPlane);
188 //=======================================================================
189 //function : CheckPlane
191 //=======================================================================
192 Standard_Boolean AIS_LengthDimension::CheckPlane (const gp_Pln& thePlane) const
194 if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
195 !thePlane.Contains (mySecondPoint, Precision::Confusion()))
197 return Standard_False;
200 return Standard_True;
203 //=======================================================================
204 //function : ComputePlane
206 //=======================================================================
207 gp_Pln AIS_LengthDimension::ComputePlane (const gp_Dir& theAttachDir) const
209 if (!IsValidPoints (myFirstPoint, mySecondPoint))
214 gp_Pnt aThirdPoint (myFirstPoint.Translated (gp_Vec(theAttachDir)));
215 gce_MakePln aPlaneConstrustor (myFirstPoint, mySecondPoint, aThirdPoint);
216 return aPlaneConstrustor.Value();
219 //=======================================================================
220 //function : GetModelUnits
222 //=======================================================================
223 const TCollection_AsciiString& AIS_LengthDimension::GetModelUnits() const
225 return myDrawer->DimLengthModelUnits();
228 //=======================================================================
229 //function : GetDisplayUnits
231 //=======================================================================
232 const TCollection_AsciiString& AIS_LengthDimension::GetDisplayUnits() const
234 return myDrawer->DimLengthDisplayUnits();
237 //=======================================================================
238 //function : SetModelUnits
240 //=======================================================================
241 void AIS_LengthDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
243 myDrawer->SetDimLengthModelUnits (theUnits);
246 //=======================================================================
247 //function : SetDisplayUnits
249 //=======================================================================
250 void AIS_LengthDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
252 myDrawer->SetDimLengthDisplayUnits (theUnits);
255 //=======================================================================
256 //function : ComputeValue
258 //=======================================================================
259 Standard_Real AIS_LengthDimension::ComputeValue() const
261 return IsValid() ? myFirstPoint.Distance (mySecondPoint) : 0.0;
264 //=======================================================================
267 //=======================================================================
268 void AIS_LengthDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
269 const Handle(Prs3d_Presentation)& thePresentation,
270 const Standard_Integer theMode)
272 thePresentation->Clear();
273 mySelectionGeom.Clear (theMode);
280 DrawLinearDimension (thePresentation, theMode, myFirstPoint, mySecondPoint);
283 //=======================================================================
284 //function : ComputeFlyoutSelection
286 //=======================================================================
287 void AIS_LengthDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
288 const Handle(SelectMgr_EntityOwner)& theEntityOwner)
295 ComputeLinearFlyouts (theSelection, theEntityOwner, myFirstPoint, mySecondPoint);
298 //=======================================================================
299 //function : IsValidPoints
301 //=======================================================================
302 Standard_Boolean AIS_LengthDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
303 const gp_Pnt& theSecondPoint) const
305 return theFirstPoint.Distance (theSecondPoint) > Precision::Confusion();
308 //=======================================================================
309 //function : InitTwoEdgesLength
310 //purpose : Initialization of dimension between two linear edges
311 //=======================================================================
312 Standard_Boolean AIS_LengthDimension::InitTwoEdgesLength (const TopoDS_Edge& theFirstEdge,
313 const TopoDS_Edge& theSecondEdge,
314 gp_Dir& theDirAttach)
316 BRepAdaptor_Curve aFirstCurveAdapt (theFirstEdge);
317 if (aFirstCurveAdapt.GetType() != GeomAbs_Line)
319 return Standard_False;
322 BRepAdaptor_Curve aSecondCurveAdapt (theSecondEdge);
323 if (aSecondCurveAdapt.GetType() != GeomAbs_Line)
325 return Standard_False;
328 Handle(Geom_Curve) aFirstCurve;
329 Handle(Geom_Curve) aSecondCurve;
331 gp_Pnt aPoint11 (gp::Origin());
332 gp_Pnt aPoint12 (gp::Origin());
333 gp_Pnt aPoint21 (gp::Origin());
334 gp_Pnt aPoint22 (gp::Origin());
335 Standard_Boolean isFirstInfinite = Standard_False;
336 Standard_Boolean isSecondInfinite = Standard_False;
338 if (!AIS::ComputeGeometry (theFirstEdge, theSecondEdge,
339 aFirstCurve, aSecondCurve,
345 return Standard_False;
348 const Handle(Geom_Line) aFirstLine = Handle(Geom_Line)::DownCast (aFirstCurve);
349 const Handle(Geom_Line) aSecondLine = Handle(Geom_Line)::DownCast (aSecondCurve);
351 if (!aFirstLine->Lin().Direction().IsParallel (aSecondLine->Lin().Direction(),Precision::Angular()))
353 return Standard_False;
356 theDirAttach = aFirstLine->Lin().Direction();
360 if (!isFirstInfinite)
362 if (AIS::Nearest (aSecondCurve, aPoint11, aPoint21, aPoint22, aPoint))
364 myFirstPoint = aPoint11;
365 mySecondPoint = aPoint;
366 return IsValidPoints (myFirstPoint, mySecondPoint);
368 else if (AIS::Nearest (aSecondCurve, aPoint12, aPoint21, aPoint22, aPoint))
370 myFirstPoint = aPoint12;
371 mySecondPoint = aPoint;
372 return IsValidPoints (myFirstPoint, mySecondPoint);
376 if (!isSecondInfinite)
378 if (AIS::Nearest (aFirstCurve, aPoint21, aPoint11, aPoint12, aPoint))
380 myFirstPoint = aPoint;
381 mySecondPoint = aPoint21;
382 return IsValidPoints (myFirstPoint, mySecondPoint);
384 if (AIS::Nearest (aFirstCurve, aPoint22, aPoint11, aPoint12, aPoint))
386 myFirstPoint = aPoint;
387 mySecondPoint = aPoint22;
388 return IsValidPoints (myFirstPoint, mySecondPoint);
392 GeomAPI_ExtremaCurveCurve anExtrema (aFirstCurve, aSecondCurve);
393 anExtrema.NearestPoints (myFirstPoint, mySecondPoint);
394 return IsValidPoints (myFirstPoint, mySecondPoint);
397 //=======================================================================
398 //function : InitEdgeVertexLength
399 //purpose : for first edge and second vertex shapes
400 //=======================================================================
401 Standard_Boolean AIS_LengthDimension::InitEdgeVertexLength (const TopoDS_Edge& theEdge,
402 const TopoDS_Vertex& theVertex,
404 Standard_Boolean isInfinite)
406 gp_Pnt anEdgePoint1 (gp::Origin());
407 gp_Pnt anEdgePoint2 (gp::Origin());
408 Handle(Geom_Curve) aCurve;
410 if (!AIS::ComputeGeometry (theEdge, aCurve, anEdgePoint1, anEdgePoint2, isInfinite))
412 return Standard_False;
415 myFirstPoint = BRep_Tool::Pnt (theVertex);
417 const Handle(Geom_Line)& aGeomLine = (Handle(Geom_Line)&) aCurve;
418 const gp_Lin& aLin = aGeomLine->Lin();
420 // Get direction of edge to build plane automatically.
421 theEdgeDir = aLin.Direction();
423 mySecondPoint = AIS::Nearest (aLin, myFirstPoint);
425 return IsValidPoints (myFirstPoint, mySecondPoint);
428 //=======================================================================
429 //function : InitEdgeFaceLength
431 //=======================================================================
432 Standard_Boolean AIS_LengthDimension::InitEdgeFaceLength (const TopoDS_Edge& theEdge,
433 const TopoDS_Face& theFace,
436 Handle(Geom_Curve) aCurve;
437 gp_Pnt aFirstPoint, aSecondPoint;
438 Standard_Boolean isInfinite = Standard_False;
440 if (!AIS::ComputeGeometry (theEdge, aCurve, aFirstPoint, aSecondPoint, isInfinite))
442 return Standard_False;
444 theEdgeDir = gce_MakeDir (aFirstPoint, aSecondPoint);
446 Handle(Geom_Surface) aSurface;
447 AIS_KindOfSurface aSurfType;
448 Standard_Real anOffset;
450 if (!AIS::GetPlaneFromFace (theFace, aPlane, aSurface, aSurfType, anOffset))
452 return Standard_False;
455 GeomAPI_ExtremaCurveSurface aDistAdaptor (aCurve, aSurface);
457 aDistAdaptor.NearestPoints (myFirstPoint, mySecondPoint);
459 return IsValidPoints (myFirstPoint, mySecondPoint);
462 //=======================================================================
463 //function : InitTwoShapesPoints
464 //purpose : Initialization of two points where dimension layouts
466 //=======================================================================
467 Standard_Boolean AIS_LengthDimension::InitTwoShapesPoints (const TopoDS_Shape& theFirstShape,
468 const TopoDS_Shape& theSecondShape,
469 gp_Pln& theComputedPlane,
470 Standard_Boolean& theIsPlaneComputed)
472 theIsPlaneComputed = Standard_False;
474 Standard_Boolean isInfinite = Standard_False;
475 Standard_Boolean isSuccess = Standard_False;
476 switch (theFirstShape.ShapeType())
480 // Initialization for face
482 Handle(Geom_Surface) aFirstSurface;
483 AIS_KindOfSurface aFirstSurfKind;
484 Standard_Real aFirstOffset;
486 TopoDS_Face aFirstFace = TopoDS::Face (theFirstShape);
488 AIS::InitFaceLength (TopoDS::Face (theFirstShape),
494 if (theSecondShape.ShapeType() == TopAbs_FACE)
496 // Initialization for face
497 myGeometryType = GeometryType_Faces;
499 Handle(Geom_Surface) aSecondSurface;
500 AIS_KindOfSurface aSecondSurfKind;
501 Standard_Real aSecondOffset;
503 TopoDS_Face aSecondFace = TopoDS::Face (theSecondShape);
505 AIS::InitFaceLength (aSecondFace,
511 if (aFirstSurfKind == AIS_KOS_Plane)
513 if (!aFirstPlane.Axis().Direction().IsParallel (aSecondPlane.Axis().Direction(), Precision::Angular()))
515 return Standard_False;
518 TopExp_Explorer anExplorer (theFirstShape, TopAbs_VERTEX);
520 // In case of infinite planes
521 if (!anExplorer.More())
523 myFirstPoint = aFirstPlane.Location();
527 myFirstPoint = BRep_Tool::Pnt (TopoDS::Vertex (anExplorer.Current()));
530 mySecondPoint = AIS::ProjectPointOnPlane (myFirstPoint, aSecondPlane);
532 Quantity_Parameter anU, aV;
533 ElSLib::Parameters (aSecondPlane, mySecondPoint, anU, aV);
535 BRepTopAdaptor_FClass2d aClassifier (aSecondFace, Precision::Confusion());
536 TopAbs_State aState = aClassifier.Perform (gp_Pnt2d (anU, aV), Standard_False);
538 if (aState == TopAbs_OUT || aState == TopAbs_UNKNOWN)
540 mySecondPoint = AIS::Nearest (aSecondFace, myFirstPoint);
543 isSuccess = IsValidPoints (myFirstPoint, mySecondPoint);
546 theComputedPlane = ComputePlane (aFirstPlane.Position().XDirection());
547 theIsPlaneComputed = Standard_True;
550 else // curvilinear faces
552 Standard_Real aU1Min, aV1Min, aU1Max, aV1Max;
553 Standard_Real aU2Min, aV2Min, aU2Max, aV2Max;
554 BRepTools::UVBounds (aFirstFace, aU1Min, aU1Max, aV1Min, aV1Max);
555 BRepTools::UVBounds (aSecondFace, aU2Min, aU2Max, aV2Min, aV2Max);
557 GeomAPI_ExtremaSurfaceSurface anExtrema (aFirstSurface, aSecondSurface,
558 aU1Min, aU1Max, aV1Min, aV1Max,
559 aU2Min, aU2Max, aV2Min, aV2Max);
561 Standard_Real aU1, aV1, aU2, aV2;
562 anExtrema.LowerDistanceParameters (aU1, aV1, aU2, aV2);
563 myFirstPoint = BRep_Tool::Surface (aFirstFace)->Value (aU1, aV1);
564 mySecondPoint = BRep_Tool::Surface (aSecondFace)->Value (aU2, aV2);
566 // Adjust automatic plane
567 gp_Ax2 aLocalAxes (myFirstPoint, gce_MakeDir (myFirstPoint, mySecondPoint));
568 aDirAttach = gce_MakeDir (aLocalAxes.XDirection ());
571 isSuccess = IsValidPoints (myFirstPoint, mySecondPoint);
574 theComputedPlane = ComputePlane (aDirAttach);
575 theIsPlaneComputed = Standard_True;
579 return isSuccess && IsValidPoints (myFirstPoint, mySecondPoint);
581 else if (theFirstShape.ShapeType() == TopAbs_EDGE)
583 myGeometryType = GeometryType_EdgeFace;
584 isSuccess = InitEdgeFaceLength (TopoDS::Edge (theFirstShape),
585 TopoDS::Face (theSecondShape),
590 theComputedPlane = ComputePlane (aDirAttach);
591 theIsPlaneComputed = Standard_True;
601 if (theSecondShape.ShapeType() == TopAbs_VERTEX)
603 myGeometryType = GeometryType_EdgeVertex;
604 isSuccess = InitEdgeVertexLength (TopoDS::Edge (theFirstShape),
605 TopoDS::Vertex (theSecondShape),
611 theComputedPlane = ComputePlane (aDirAttach);
612 theIsPlaneComputed = Standard_True;
617 else if (theSecondShape.ShapeType() == TopAbs_EDGE)
619 myGeometryType = GeometryType_Edges;
620 isSuccess = InitTwoEdgesLength (TopoDS::Edge (theFirstShape),
621 TopoDS::Edge (theSecondShape),
626 theComputedPlane = ComputePlane (aDirAttach);
627 theIsPlaneComputed = Standard_True;
637 if (theSecondShape.ShapeType() == TopAbs_VERTEX)
639 myGeometryType = GeometryType_Points;
640 myFirstPoint = BRep_Tool::Pnt (TopoDS::Vertex (theFirstShape));
641 mySecondPoint = BRep_Tool::Pnt (TopoDS::Vertex (theSecondShape));
643 return IsValidPoints (myFirstPoint, mySecondPoint);
645 else if (theSecondShape.ShapeType() == TopAbs_EDGE)
647 myGeometryType = GeometryType_EdgeVertex;
648 Standard_Boolean isSuccess = InitEdgeVertexLength (TopoDS::Edge(theSecondShape),
649 TopoDS::Vertex(theFirstShape),
654 theComputedPlane = ComputePlane (aDirAttach);
655 theIsPlaneComputed = Standard_True;
663 case TopAbs_COMPOUND:
664 case TopAbs_COMPSOLID:
672 return Standard_False;
675 //=======================================================================
676 //function : InitOneShapePoints
677 //purpose : Initialization of two points where dimension layouts
679 // Attention: 1) <theShape> can be only the edge in currect implementation
680 // 2) No length for infinite edge
681 //=======================================================================
682 Standard_Boolean AIS_LengthDimension::InitOneShapePoints (const TopoDS_Shape& theShape)
684 if (theShape.ShapeType() != TopAbs_EDGE)
686 return Standard_False;
689 TopoDS_Edge anEdge = TopoDS::Edge (theShape);
691 BRepAdaptor_Curve aBrepCurve(anEdge);
692 Standard_Real aFirst = aBrepCurve.FirstParameter();
693 Standard_Real aLast = aBrepCurve.LastParameter();
695 if (aBrepCurve.GetType() != GeomAbs_Line)
697 return Standard_False;
700 Standard_Boolean isInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
703 return Standard_False;
706 myFirstPoint = aBrepCurve.Value (aBrepCurve.FirstParameter());
707 mySecondPoint = aBrepCurve.Value (aBrepCurve.LastParameter());
709 return IsValidPoints (myFirstPoint, mySecondPoint);
712 //=======================================================================
713 //function : GetTextPosition
715 //=======================================================================
716 const gp_Pnt AIS_LengthDimension::GetTextPosition() const
718 if (IsTextPositionCustom())
720 return myFixedTextPosition;
723 // Counts text position according to the dimension parameters
724 return GetTextPositionForLinear (myFirstPoint, mySecondPoint);
727 //=======================================================================
728 //function : SetTextPosition
730 //=======================================================================
731 void AIS_LengthDimension::SetTextPosition (const gp_Pnt& theTextPos)
738 myIsTextPositionFixed = Standard_True;
739 myFixedTextPosition = theTextPos;