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 myIsGeometryValid = IsValidPoints (theFirstPoint, theSecondPoint);
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 myIsGeometryValid = InitOneShapePoints (myFirstShape);
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;
168 myFirstShape = theFirstShape;
169 mySecondShape = theSecondShape;
170 myIsGeometryValid = InitTwoShapesPoints (myFirstShape, mySecondShape, aComputedPlane, isPlaneReturned);
172 if (myIsGeometryValid && !myIsPlaneCustom)
176 myPlane = aComputedPlane;
180 myIsGeometryValid = Standard_False;
187 //=======================================================================
188 //function : CheckPlane
190 //=======================================================================
191 Standard_Boolean AIS_LengthDimension::CheckPlane (const gp_Pln& thePlane) const
193 if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
194 !thePlane.Contains (mySecondPoint, Precision::Confusion()))
196 return Standard_False;
199 return Standard_True;
202 //=======================================================================
203 //function : ComputePlane
205 //=======================================================================
206 gp_Pln AIS_LengthDimension::ComputePlane (const gp_Dir& theAttachDir) const
208 if (!IsValidPoints (myFirstPoint, mySecondPoint))
213 gp_Pnt aThirdPoint (myFirstPoint.Translated (gp_Vec(theAttachDir)));
214 gce_MakePln aPlaneConstrustor (myFirstPoint, mySecondPoint, aThirdPoint);
215 return aPlaneConstrustor.Value();
218 //=======================================================================
219 //function : GetModelUnits
221 //=======================================================================
222 const TCollection_AsciiString& AIS_LengthDimension::GetModelUnits() const
224 return myDrawer->DimLengthModelUnits();
227 //=======================================================================
228 //function : GetDisplayUnits
230 //=======================================================================
231 const TCollection_AsciiString& AIS_LengthDimension::GetDisplayUnits() const
233 return myDrawer->DimLengthDisplayUnits();
236 //=======================================================================
237 //function : SetModelUnits
239 //=======================================================================
240 void AIS_LengthDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
242 myDrawer->SetDimLengthModelUnits (theUnits);
245 //=======================================================================
246 //function : SetDisplayUnits
248 //=======================================================================
249 void AIS_LengthDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
251 myDrawer->SetDimLengthDisplayUnits (theUnits);
254 //=======================================================================
255 //function : ComputeValue
257 //=======================================================================
258 Standard_Real AIS_LengthDimension::ComputeValue() const
260 return IsValid() ? myFirstPoint.Distance (mySecondPoint) : 0.0;
263 //=======================================================================
266 //=======================================================================
267 void AIS_LengthDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
268 const Handle(Prs3d_Presentation)& thePresentation,
269 const Standard_Integer theMode)
271 thePresentation->Clear();
272 mySelectionGeom.Clear (theMode);
279 DrawLinearDimension (thePresentation, theMode, myFirstPoint, mySecondPoint);
282 //=======================================================================
283 //function : ComputeFlyoutSelection
285 //=======================================================================
286 void AIS_LengthDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
287 const Handle(SelectMgr_EntityOwner)& theEntityOwner)
294 ComputeLinearFlyouts (theSelection, theEntityOwner, myFirstPoint, mySecondPoint);
297 //=======================================================================
298 //function : IsValidPoints
300 //=======================================================================
301 Standard_Boolean AIS_LengthDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
302 const gp_Pnt& theSecondPoint) const
304 return theFirstPoint.Distance (theSecondPoint) > Precision::Confusion();
307 //=======================================================================
308 //function : InitTwoEdgesLength
309 //purpose : Initialization of dimension between two linear edges
310 //=======================================================================
311 Standard_Boolean AIS_LengthDimension::InitTwoEdgesLength (const TopoDS_Edge& theFirstEdge,
312 const TopoDS_Edge& theSecondEdge,
313 gp_Dir& theDirAttach)
315 BRepAdaptor_Curve aFirstCurveAdapt (theFirstEdge);
316 if (aFirstCurveAdapt.GetType() != GeomAbs_Line)
318 return Standard_False;
321 BRepAdaptor_Curve aSecondCurveAdapt (theSecondEdge);
322 if (aSecondCurveAdapt.GetType() != GeomAbs_Line)
324 return Standard_False;
327 Handle(Geom_Curve) aFirstCurve;
328 Handle(Geom_Curve) aSecondCurve;
330 gp_Pnt aPoint11 (gp::Origin());
331 gp_Pnt aPoint12 (gp::Origin());
332 gp_Pnt aPoint21 (gp::Origin());
333 gp_Pnt aPoint22 (gp::Origin());
334 Standard_Boolean isFirstInfinite = Standard_False;
335 Standard_Boolean isSecondInfinite = Standard_False;
337 if (!AIS::ComputeGeometry (theFirstEdge, theSecondEdge,
338 aFirstCurve, aSecondCurve,
344 return Standard_False;
347 const Handle(Geom_Line) aFirstLine = Handle(Geom_Line)::DownCast (aFirstCurve);
348 const Handle(Geom_Line) aSecondLine = Handle(Geom_Line)::DownCast (aSecondCurve);
350 if (!aFirstLine->Lin().Direction().IsParallel (aSecondLine->Lin().Direction(),Precision::Angular()))
352 return Standard_False;
355 theDirAttach = aFirstLine->Lin().Direction();
359 if (!isFirstInfinite)
361 if (AIS::Nearest (aSecondCurve, aPoint11, aPoint21, aPoint22, aPoint))
363 myFirstPoint = aPoint11;
364 mySecondPoint = aPoint;
365 return IsValidPoints (myFirstPoint, mySecondPoint);
367 else if (AIS::Nearest (aSecondCurve, aPoint12, aPoint21, aPoint22, aPoint))
369 myFirstPoint = aPoint12;
370 mySecondPoint = aPoint;
371 return IsValidPoints (myFirstPoint, mySecondPoint);
375 if (!isSecondInfinite)
377 if (AIS::Nearest (aFirstCurve, aPoint21, aPoint11, aPoint12, aPoint))
379 myFirstPoint = aPoint;
380 mySecondPoint = aPoint21;
381 return IsValidPoints (myFirstPoint, mySecondPoint);
383 if (AIS::Nearest (aFirstCurve, aPoint22, aPoint11, aPoint12, aPoint))
385 myFirstPoint = aPoint;
386 mySecondPoint = aPoint22;
387 return IsValidPoints (myFirstPoint, mySecondPoint);
391 GeomAPI_ExtremaCurveCurve anExtrema (aFirstCurve, aSecondCurve);
392 anExtrema.NearestPoints (myFirstPoint, mySecondPoint);
393 return IsValidPoints (myFirstPoint, mySecondPoint);
396 //=======================================================================
397 //function : InitEdgeVertexLength
398 //purpose : for first edge and second vertex shapes
399 //=======================================================================
400 Standard_Boolean AIS_LengthDimension::InitEdgeVertexLength (const TopoDS_Edge& theEdge,
401 const TopoDS_Vertex& theVertex,
403 Standard_Boolean isInfinite)
405 gp_Pnt anEdgePoint1 (gp::Origin());
406 gp_Pnt anEdgePoint2 (gp::Origin());
407 Handle(Geom_Curve) aCurve;
409 if (!AIS::ComputeGeometry (theEdge, aCurve, anEdgePoint1, anEdgePoint2, isInfinite))
411 return Standard_False;
414 myFirstPoint = BRep_Tool::Pnt (theVertex);
416 const Handle(Geom_Line)& aGeomLine = (Handle(Geom_Line)&) aCurve;
417 const gp_Lin& aLin = aGeomLine->Lin();
419 // Get direction of edge to build plane automatically.
420 theEdgeDir = aLin.Direction();
422 mySecondPoint = AIS::Nearest (aLin, myFirstPoint);
424 return IsValidPoints (myFirstPoint, mySecondPoint);
427 //=======================================================================
428 //function : InitEdgeFaceLength
430 //=======================================================================
431 Standard_Boolean AIS_LengthDimension::InitEdgeFaceLength (const TopoDS_Edge& theEdge,
432 const TopoDS_Face& theFace,
435 Handle(Geom_Curve) aCurve;
436 gp_Pnt aFirstPoint, aSecondPoint;
437 Standard_Boolean isInfinite = Standard_False;
439 if (!AIS::ComputeGeometry (theEdge, aCurve, aFirstPoint, aSecondPoint, isInfinite))
441 return Standard_False;
443 theEdgeDir = gce_MakeDir (aFirstPoint, aSecondPoint);
445 Handle(Geom_Surface) aSurface;
446 AIS_KindOfSurface aSurfType;
447 Standard_Real anOffset;
449 if (!AIS::GetPlaneFromFace (theFace, aPlane, aSurface, aSurfType, anOffset))
451 return Standard_False;
454 GeomAPI_ExtremaCurveSurface aDistAdaptor (aCurve, aSurface);
456 aDistAdaptor.NearestPoints (myFirstPoint, mySecondPoint);
458 return IsValidPoints (myFirstPoint, mySecondPoint);
461 //=======================================================================
462 //function : InitTwoShapesPoints
463 //purpose : Initialization of two points where dimension layouts
465 //=======================================================================
466 Standard_Boolean AIS_LengthDimension::InitTwoShapesPoints (const TopoDS_Shape& theFirstShape,
467 const TopoDS_Shape& theSecondShape,
468 gp_Pln& theComputedPlane,
469 Standard_Boolean& theIsPlaneComputed)
471 theIsPlaneComputed = Standard_False;
473 Standard_Boolean isInfinite = Standard_False;
474 Standard_Boolean isSuccess = Standard_False;
475 switch (theFirstShape.ShapeType())
479 // Initialization for face
481 Handle(Geom_Surface) aFirstSurface;
482 AIS_KindOfSurface aFirstSurfKind;
483 Standard_Real aFirstOffset;
485 TopoDS_Face aFirstFace = TopoDS::Face (theFirstShape);
487 AIS::InitFaceLength (TopoDS::Face (theFirstShape),
493 if (theSecondShape.ShapeType() == TopAbs_FACE)
495 // Initialization for face
496 myGeometryType = GeometryType_Faces;
498 Handle(Geom_Surface) aSecondSurface;
499 AIS_KindOfSurface aSecondSurfKind;
500 Standard_Real aSecondOffset;
502 TopoDS_Face aSecondFace = TopoDS::Face (theSecondShape);
504 AIS::InitFaceLength (aSecondFace,
510 if (aFirstSurfKind == AIS_KOS_Plane)
512 if (!aFirstPlane.Axis().Direction().IsParallel (aSecondPlane.Axis().Direction(), Precision::Angular()))
514 return Standard_False;
517 TopExp_Explorer anExplorer (theFirstShape, TopAbs_VERTEX);
519 // In case of infinite planes
520 if (!anExplorer.More())
522 myFirstPoint = aFirstPlane.Location();
526 myFirstPoint = BRep_Tool::Pnt (TopoDS::Vertex (anExplorer.Current()));
529 mySecondPoint = AIS::ProjectPointOnPlane (myFirstPoint, aSecondPlane);
531 Quantity_Parameter anU, aV;
532 ElSLib::Parameters (aSecondPlane, mySecondPoint, anU, aV);
534 BRepTopAdaptor_FClass2d aClassifier (aSecondFace, Precision::Confusion());
535 TopAbs_State aState = aClassifier.Perform (gp_Pnt2d (anU, aV), Standard_False);
537 if (aState == TopAbs_OUT || aState == TopAbs_UNKNOWN)
539 mySecondPoint = AIS::Nearest (aSecondFace, myFirstPoint);
542 isSuccess = IsValidPoints (myFirstPoint, mySecondPoint);
545 theComputedPlane = ComputePlane (aFirstPlane.Position().XDirection());
546 theIsPlaneComputed = Standard_True;
549 else // curvilinear faces
551 Standard_Real aU1Min, aV1Min, aU1Max, aV1Max;
552 Standard_Real aU2Min, aV2Min, aU2Max, aV2Max;
553 BRepTools::UVBounds (aFirstFace, aU1Min, aU1Max, aV1Min, aV1Max);
554 BRepTools::UVBounds (aSecondFace, aU2Min, aU2Max, aV2Min, aV2Max);
556 GeomAPI_ExtremaSurfaceSurface anExtrema (aFirstSurface, aSecondSurface,
557 aU1Min, aU1Max, aV1Min, aV1Max,
558 aU2Min, aU2Max, aV2Min, aV2Max);
560 Standard_Real aU1, aV1, aU2, aV2;
561 anExtrema.LowerDistanceParameters (aU1, aV1, aU2, aV2);
562 myFirstPoint = BRep_Tool::Surface (aFirstFace)->Value (aU1, aV1);
563 mySecondPoint = BRep_Tool::Surface (aSecondFace)->Value (aU2, aV2);
565 // Adjust automatic plane
566 gp_Ax2 aLocalAxes (myFirstPoint, gce_MakeDir (myFirstPoint, mySecondPoint));
567 aDirAttach = gce_MakeDir (aLocalAxes.XDirection ());
570 isSuccess = IsValidPoints (myFirstPoint, mySecondPoint);
573 theComputedPlane = ComputePlane (aDirAttach);
574 theIsPlaneComputed = Standard_True;
578 return isSuccess && IsValidPoints (myFirstPoint, mySecondPoint);
580 else if (theFirstShape.ShapeType() == TopAbs_EDGE)
582 myGeometryType = GeometryType_EdgeFace;
583 isSuccess = InitEdgeFaceLength (TopoDS::Edge (theFirstShape),
584 TopoDS::Face (theSecondShape),
589 theComputedPlane = ComputePlane (aDirAttach);
590 theIsPlaneComputed = Standard_True;
600 if (theSecondShape.ShapeType() == TopAbs_VERTEX)
602 myGeometryType = GeometryType_EdgeVertex;
603 isSuccess = InitEdgeVertexLength (TopoDS::Edge (theFirstShape),
604 TopoDS::Vertex (theSecondShape),
610 theComputedPlane = ComputePlane (aDirAttach);
611 theIsPlaneComputed = Standard_True;
616 else if (theSecondShape.ShapeType() == TopAbs_EDGE)
618 myGeometryType = GeometryType_Edges;
619 isSuccess = InitTwoEdgesLength (TopoDS::Edge (theFirstShape),
620 TopoDS::Edge (theSecondShape),
625 theComputedPlane = ComputePlane (aDirAttach);
626 theIsPlaneComputed = Standard_True;
636 if (theSecondShape.ShapeType() == TopAbs_VERTEX)
638 myGeometryType = GeometryType_Points;
639 myFirstPoint = BRep_Tool::Pnt (TopoDS::Vertex (theFirstShape));
640 mySecondPoint = BRep_Tool::Pnt (TopoDS::Vertex (theSecondShape));
642 return IsValidPoints (myFirstPoint, mySecondPoint);
644 else if (theSecondShape.ShapeType() == TopAbs_EDGE)
646 myGeometryType = GeometryType_EdgeVertex;
647 Standard_Boolean isSuccess = InitEdgeVertexLength (TopoDS::Edge(theSecondShape),
648 TopoDS::Vertex(theFirstShape),
653 theComputedPlane = ComputePlane (aDirAttach);
654 theIsPlaneComputed = Standard_True;
662 case TopAbs_COMPOUND:
663 case TopAbs_COMPSOLID:
671 return Standard_False;
674 //=======================================================================
675 //function : InitOneShapePoints
676 //purpose : Initialization of two points where dimension layouts
678 // Attention: 1) <theShape> can be only the edge in currect implementation
679 // 2) No length for infinite edge
680 //=======================================================================
681 Standard_Boolean AIS_LengthDimension::InitOneShapePoints (const TopoDS_Shape& theShape)
683 if (theShape.ShapeType() != TopAbs_EDGE)
685 return Standard_False;
688 TopoDS_Edge anEdge = TopoDS::Edge (theShape);
690 BRepAdaptor_Curve aBrepCurve(anEdge);
691 Standard_Real aFirst = aBrepCurve.FirstParameter();
692 Standard_Real aLast = aBrepCurve.LastParameter();
694 if (aBrepCurve.GetType() != GeomAbs_Line)
696 return Standard_False;
699 Standard_Boolean isInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
702 return Standard_False;
705 myFirstPoint = aBrepCurve.Value (aBrepCurve.FirstParameter());
706 mySecondPoint = aBrepCurve.Value (aBrepCurve.LastParameter());
708 return IsValidPoints (myFirstPoint, mySecondPoint);
711 //=======================================================================
712 //function : GetTextPosition
714 //=======================================================================
715 const gp_Pnt AIS_LengthDimension::GetTextPosition() const
717 if (IsTextPositionCustom())
719 return myFixedTextPosition;
722 // Counts text position according to the dimension parameters
723 return GetTextPositionForLinear (myFirstPoint, mySecondPoint);
726 //=======================================================================
727 //function : SetTextPosition
729 //=======================================================================
730 void AIS_LengthDimension::SetTextPosition (const gp_Pnt& theTextPos)
737 myIsTextPositionFixed = Standard_True;
738 myFixedTextPosition = theTextPos;