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 <BRepExtrema_DistShapeShape.hxx>
23 #include <BRepLib_MakeVertex.hxx>
24 #include <BRepTopAdaptor_FClass2d.hxx>
25 #include <BRepTools.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>
36 #include <TopExp_Explorer.hxx>
39 IMPLEMENT_STANDARD_RTTIEXT(AIS_LengthDimension,AIS_Dimension)
41 //=======================================================================
42 //function : Constructor
43 //purpose : Dimension between two faces
44 //=======================================================================
45 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFirstFace,
46 const TopoDS_Face& theSecondFace)
47 : AIS_Dimension (AIS_KOD_LENGTH)
49 SetMeasuredGeometry (theFirstFace, theSecondFace);
53 //=======================================================================
54 //function : Constructor
55 //purpose : Dimension between two shape
56 //=======================================================================
57 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFace,
58 const TopoDS_Edge& theEdge)
59 : AIS_Dimension (AIS_KOD_LENGTH)
61 SetMeasuredGeometry (theFace, theEdge);
65 //=======================================================================
66 //function : Constructor
67 //purpose : Dimension between two points
68 //=======================================================================
69 AIS_LengthDimension::AIS_LengthDimension (const gp_Pnt& theFirstPoint,
70 const gp_Pnt& theSecondPoint,
71 const gp_Pln& thePlane)
72 : AIS_Dimension (AIS_KOD_LENGTH)
74 SetMeasuredGeometry (theFirstPoint, theSecondPoint, thePlane);
78 //=======================================================================
79 //function : Constructor
80 //purpose : Dimension between two shape
81 //=======================================================================
82 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Shape& theFirstShape,
83 const TopoDS_Shape& theSecondShape,
84 const gp_Pln& thePlane)
85 : AIS_Dimension (AIS_KOD_LENGTH)
87 SetCustomPlane (thePlane);
88 SetMeasuredShapes (theFirstShape, theSecondShape);
92 //=======================================================================
93 //function : Constructor
94 //purpose : Dimension of one edge
95 //=======================================================================
96 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Edge& theEdge,
97 const gp_Pln& thePlane)
98 : AIS_Dimension (AIS_KOD_LENGTH)
100 SetMeasuredGeometry (theEdge, thePlane);
104 //=======================================================================
105 //function : SetMeasuredGeometry
107 //=======================================================================
108 void AIS_LengthDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
109 const gp_Pnt& theSecondPoint,
110 const gp_Pln& thePlane)
112 myFirstPoint = theFirstPoint;
113 mySecondPoint = theSecondPoint;
114 myFirstShape = BRepLib_MakeVertex (myFirstPoint);
115 mySecondShape = BRepLib_MakeVertex (mySecondPoint);
116 myGeometryType = GeometryType_Points;
117 SetCustomPlane (thePlane);
118 myIsGeometryValid = IsValidPoints (theFirstPoint, theSecondPoint);
123 //=======================================================================
124 //function : SetMeasuredGeometry
126 //=======================================================================
127 void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Edge& theEdge,
128 const gp_Pln& thePlane)
130 myFirstShape = theEdge;
131 mySecondShape = TopoDS_Shape();
132 myGeometryType = GeometryType_Edge;
133 SetCustomPlane (thePlane);
134 myIsGeometryValid = InitOneShapePoints (myFirstShape);
139 //=======================================================================
140 //function : SetMeasuredGeometry
142 //=======================================================================
143 void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
144 const TopoDS_Face& theSecondFace)
146 SetMeasuredShapes (theFirstFace, theSecondFace);
149 //=======================================================================
150 //function : SetMeasuredGeometry
152 //=======================================================================
153 void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Face& theFace,
154 const TopoDS_Edge& theEdge)
156 SetMeasuredShapes (theFace, theEdge);
159 //=======================================================================
160 //function : SetMeasuredShapes
162 //=======================================================================
163 void AIS_LengthDimension::SetMeasuredShapes (const TopoDS_Shape& theFirstShape,
164 const TopoDS_Shape& theSecondShape)
166 gp_Pln aComputedPlane;
167 Standard_Boolean isPlaneReturned = Standard_False;
169 myFirstShape = theFirstShape;
170 mySecondShape = theSecondShape;
171 myIsGeometryValid = InitTwoShapesPoints (myFirstShape, mySecondShape, aComputedPlane, isPlaneReturned);
173 if (myIsGeometryValid && !myIsPlaneCustom)
177 myPlane = aComputedPlane;
181 myIsGeometryValid = Standard_False;
188 //=======================================================================
189 //function : CheckPlane
191 //=======================================================================
192 Standard_Boolean AIS_LengthDimension::CheckPlane (const gp_Pln& thePlane) const
194 Standard_Boolean anIsFaultyNormal =
195 thePlane.Axis().Direction().IsParallel(gce_MakeDir (myFirstPoint, mySecondPoint), Precision::Angular());
197 if ((!thePlane.Contains (myFirstPoint, Precision::Confusion()) && !thePlane.Contains (mySecondPoint, Precision::Confusion()))
200 return Standard_False;
203 return Standard_True;
206 //=======================================================================
207 //function : ComputePlane
209 //=======================================================================
210 gp_Pln AIS_LengthDimension::ComputePlane (const gp_Dir& theAttachDir) const
212 if (!IsValidPoints (myFirstPoint, mySecondPoint))
217 gp_Pnt aThirdPoint (myFirstPoint.Translated (gp_Vec(theAttachDir)));
218 gce_MakePln aPlaneConstrustor (myFirstPoint, mySecondPoint, aThirdPoint);
219 return aPlaneConstrustor.Value();
222 //=======================================================================
223 //function : GetModelUnits
225 //=======================================================================
226 const TCollection_AsciiString& AIS_LengthDimension::GetModelUnits() const
228 return myDrawer->DimLengthModelUnits();
231 //=======================================================================
232 //function : GetDisplayUnits
234 //=======================================================================
235 const TCollection_AsciiString& AIS_LengthDimension::GetDisplayUnits() const
237 return myDrawer->DimLengthDisplayUnits();
240 //=======================================================================
241 //function : SetModelUnits
243 //=======================================================================
244 void AIS_LengthDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
246 myDrawer->SetDimLengthModelUnits (theUnits);
249 //=======================================================================
250 //function : SetDisplayUnits
252 //=======================================================================
253 void AIS_LengthDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
255 myDrawer->SetDimLengthDisplayUnits (theUnits);
258 //=======================================================================
259 //function : ComputeValue
261 //=======================================================================
262 Standard_Real AIS_LengthDimension::ComputeValue() const
264 return IsValid() ? myFirstPoint.Distance (mySecondPoint) : 0.0;
267 //=======================================================================
270 //=======================================================================
271 void AIS_LengthDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
272 const Handle(Prs3d_Presentation)& thePresentation,
273 const Standard_Integer theMode)
275 thePresentation->Clear();
276 mySelectionGeom.Clear (theMode);
283 DrawLinearDimension (thePresentation, theMode, myFirstPoint, mySecondPoint);
286 //=======================================================================
287 //function : ComputeFlyoutSelection
289 //=======================================================================
290 void AIS_LengthDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
291 const Handle(SelectMgr_EntityOwner)& theEntityOwner)
298 ComputeLinearFlyouts (theSelection, theEntityOwner, myFirstPoint, mySecondPoint);
301 //=======================================================================
302 //function : IsValidPoints
304 //=======================================================================
305 Standard_Boolean AIS_LengthDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
306 const gp_Pnt& theSecondPoint) const
308 return theFirstPoint.Distance (theSecondPoint) > Precision::Confusion();
311 //=======================================================================
312 //function : InitTwoEdgesLength
313 //purpose : Initialization of dimension between two linear edges
314 //=======================================================================
315 Standard_Boolean AIS_LengthDimension::InitTwoEdgesLength (const TopoDS_Edge& theFirstEdge,
316 const TopoDS_Edge& theSecondEdge,
317 gp_Dir& theDirAttach)
319 BRepAdaptor_Curve aFirstCurveAdapt (theFirstEdge);
320 if (aFirstCurveAdapt.GetType() != GeomAbs_Line)
322 return Standard_False;
325 BRepAdaptor_Curve aSecondCurveAdapt (theSecondEdge);
326 if (aSecondCurveAdapt.GetType() != GeomAbs_Line)
328 return Standard_False;
331 Handle(Geom_Curve) aFirstCurve;
332 Handle(Geom_Curve) aSecondCurve;
334 gp_Pnt aPoint11 (gp::Origin());
335 gp_Pnt aPoint12 (gp::Origin());
336 gp_Pnt aPoint21 (gp::Origin());
337 gp_Pnt aPoint22 (gp::Origin());
338 Standard_Boolean isFirstInfinite = Standard_False;
339 Standard_Boolean isSecondInfinite = Standard_False;
341 if (!AIS::ComputeGeometry (theFirstEdge, theSecondEdge,
342 aFirstCurve, aSecondCurve,
348 return Standard_False;
351 const Handle(Geom_Line) aFirstLine = Handle(Geom_Line)::DownCast (aFirstCurve);
352 const Handle(Geom_Line) aSecondLine = Handle(Geom_Line)::DownCast (aSecondCurve);
354 if (!aFirstLine->Lin().Direction().IsParallel (aSecondLine->Lin().Direction(),Precision::Angular()))
356 return Standard_False;
359 theDirAttach = aFirstLine->Lin().Direction();
363 if (!isFirstInfinite)
365 if (AIS::Nearest (aSecondCurve, aPoint11, aPoint21, aPoint22, aPoint))
367 myFirstPoint = aPoint11;
368 mySecondPoint = aPoint;
369 return IsValidPoints (myFirstPoint, mySecondPoint);
371 else if (AIS::Nearest (aSecondCurve, aPoint12, aPoint21, aPoint22, aPoint))
373 myFirstPoint = aPoint12;
374 mySecondPoint = aPoint;
375 return IsValidPoints (myFirstPoint, mySecondPoint);
379 if (!isSecondInfinite)
381 if (AIS::Nearest (aFirstCurve, aPoint21, aPoint11, aPoint12, aPoint))
383 myFirstPoint = aPoint;
384 mySecondPoint = aPoint21;
385 return IsValidPoints (myFirstPoint, mySecondPoint);
387 if (AIS::Nearest (aFirstCurve, aPoint22, aPoint11, aPoint12, aPoint))
389 myFirstPoint = aPoint;
390 mySecondPoint = aPoint22;
391 return IsValidPoints (myFirstPoint, mySecondPoint);
395 GeomAPI_ExtremaCurveCurve anExtrema (aFirstCurve, aSecondCurve);
396 anExtrema.NearestPoints (myFirstPoint, mySecondPoint);
397 return IsValidPoints (myFirstPoint, mySecondPoint);
400 //=======================================================================
401 //function : InitEdgeVertexLength
402 //purpose : for first edge and second vertex shapes
403 //=======================================================================
404 Standard_Boolean AIS_LengthDimension::InitEdgeVertexLength (const TopoDS_Edge& theEdge,
405 const TopoDS_Vertex& theVertex,
407 Standard_Boolean isInfinite)
409 gp_Pnt anEdgePoint1 (gp::Origin());
410 gp_Pnt anEdgePoint2 (gp::Origin());
411 Handle(Geom_Curve) aCurve;
413 if (!AIS::ComputeGeometry (theEdge, aCurve, anEdgePoint1, anEdgePoint2, isInfinite))
415 return Standard_False;
418 myFirstPoint = BRep_Tool::Pnt (theVertex);
420 Handle(Geom_Line) aGeomLine (Handle(Geom_Line)::DownCast (aCurve));
421 const gp_Lin& aLin = aGeomLine->Lin();
423 // Get direction of edge to build plane automatically.
424 theEdgeDir = aLin.Direction();
426 mySecondPoint = AIS::Nearest (aLin, myFirstPoint);
428 return IsValidPoints (myFirstPoint, mySecondPoint);
431 //=======================================================================
432 //function : InitEdgeFaceLength
434 //=======================================================================
435 Standard_Boolean AIS_LengthDimension::InitEdgeFaceLength (const TopoDS_Edge& theEdge,
436 const TopoDS_Face& theFace,
439 // Compute edge direction
440 BRepAdaptor_Curve aCurveAdaptor (theEdge);
441 Handle(Geom_Curve) aCurve = Handle(Geom_Curve)::DownCast (aCurveAdaptor.Curve().Curve()->Transformed (aCurveAdaptor.Trsf()));
444 return Standard_False;
446 Standard_Real aFirst = aCurveAdaptor.FirstParameter();
447 Standard_Real aLast = aCurveAdaptor.LastParameter();
448 gp_Pnt aFirstPoint = !Precision::IsInfinite (aFirst) ? aCurve->Value (aFirst) : gp::Origin();
449 gp_Pnt aSecondPoint = !Precision::IsInfinite (aLast) ? aCurve->Value (aLast) : gp::Origin();
450 gce_MakeDir aMakeDir (aFirstPoint, aSecondPoint);
451 if (!aMakeDir.IsDone())
453 return Standard_False;
455 theEdgeDir = aMakeDir.Value();
457 // Find attachment points
458 BRepExtrema_DistShapeShape aDistAdaptor (theEdge, theFace, Extrema_ExtFlag_MIN);
459 if (!aDistAdaptor.IsDone())
461 return Standard_False;
463 myFirstPoint = aDistAdaptor.PointOnShape1 (1);
464 mySecondPoint = aDistAdaptor.PointOnShape2 (1);
466 return IsValidPoints (myFirstPoint, mySecondPoint);
469 //=======================================================================
470 //function : InitTwoShapesPoints
471 //purpose : Initialization of two points where dimension layouts
473 //=======================================================================
474 Standard_Boolean AIS_LengthDimension::InitTwoShapesPoints (const TopoDS_Shape& theFirstShape,
475 const TopoDS_Shape& theSecondShape,
476 gp_Pln& theComputedPlane,
477 Standard_Boolean& theIsPlaneComputed)
479 theIsPlaneComputed = Standard_False;
481 Standard_Boolean isInfinite = Standard_False;
482 Standard_Boolean isSuccess = Standard_False;
483 switch (theFirstShape.ShapeType())
487 // Initialization for face
489 Handle(Geom_Surface) aFirstSurface;
490 AIS_KindOfSurface aFirstSurfKind;
491 Standard_Real aFirstOffset;
493 TopoDS_Face aFirstFace = TopoDS::Face (theFirstShape);
495 AIS::InitFaceLength (TopoDS::Face (theFirstShape),
501 if (theSecondShape.ShapeType() == TopAbs_FACE)
503 // Initialization for face
504 myGeometryType = GeometryType_Faces;
506 Handle(Geom_Surface) aSecondSurface;
507 AIS_KindOfSurface aSecondSurfKind;
508 Standard_Real aSecondOffset;
510 TopoDS_Face aSecondFace = TopoDS::Face (theSecondShape);
512 AIS::InitFaceLength (aSecondFace,
518 if (aFirstSurfKind == AIS_KOS_Plane)
520 if (!aFirstPlane.Axis().Direction().IsParallel (aSecondPlane.Axis().Direction(), Precision::Angular()))
522 return Standard_False;
525 TopExp_Explorer anExplorer (theFirstShape, TopAbs_VERTEX);
527 // In case of infinite planes
528 if (!anExplorer.More())
530 myFirstPoint = aFirstPlane.Location();
534 myFirstPoint = BRep_Tool::Pnt (TopoDS::Vertex (anExplorer.Current()));
537 mySecondPoint = AIS::ProjectPointOnPlane (myFirstPoint, aSecondPlane);
539 Quantity_Parameter anU, aV;
540 ElSLib::Parameters (aSecondPlane, mySecondPoint, anU, aV);
542 BRepTopAdaptor_FClass2d aClassifier (aSecondFace, Precision::Confusion());
543 TopAbs_State aState = aClassifier.Perform (gp_Pnt2d (anU, aV), Standard_False);
545 if (aState == TopAbs_OUT || aState == TopAbs_UNKNOWN)
547 mySecondPoint = AIS::Nearest (aSecondFace, myFirstPoint);
550 isSuccess = IsValidPoints (myFirstPoint, mySecondPoint);
553 theComputedPlane = ComputePlane (aFirstPlane.Position().XDirection());
554 theIsPlaneComputed = Standard_True;
557 else // curvilinear faces
559 Standard_Real aU1Min, aV1Min, aU1Max, aV1Max;
560 Standard_Real aU2Min, aV2Min, aU2Max, aV2Max;
561 BRepTools::UVBounds (aFirstFace, aU1Min, aU1Max, aV1Min, aV1Max);
562 BRepTools::UVBounds (aSecondFace, aU2Min, aU2Max, aV2Min, aV2Max);
564 GeomAPI_ExtremaSurfaceSurface anExtrema (aFirstSurface, aSecondSurface,
565 aU1Min, aU1Max, aV1Min, aV1Max,
566 aU2Min, aU2Max, aV2Min, aV2Max);
568 Standard_Real aU1, aV1, aU2, aV2;
569 anExtrema.LowerDistanceParameters (aU1, aV1, aU2, aV2);
570 myFirstPoint = BRep_Tool::Surface (aFirstFace)->Value (aU1, aV1);
571 mySecondPoint = BRep_Tool::Surface (aSecondFace)->Value (aU2, aV2);
573 // Adjust automatic plane
574 gp_Ax2 aLocalAxes (myFirstPoint, gce_MakeDir (myFirstPoint, mySecondPoint));
575 aDirAttach = gce_MakeDir (aLocalAxes.XDirection ());
578 isSuccess = IsValidPoints (myFirstPoint, mySecondPoint);
581 theComputedPlane = ComputePlane (aDirAttach);
582 theIsPlaneComputed = Standard_True;
586 return isSuccess && IsValidPoints (myFirstPoint, mySecondPoint);
588 else if (theSecondShape.ShapeType() == TopAbs_EDGE)
590 myGeometryType = GeometryType_EdgeFace;
591 isSuccess = InitEdgeFaceLength (TopoDS::Edge (theSecondShape),
592 TopoDS::Face (theFirstShape),
597 theComputedPlane = ComputePlane (aDirAttach);
598 theIsPlaneComputed = Standard_True;
608 if (theSecondShape.ShapeType() == TopAbs_VERTEX)
610 myGeometryType = GeometryType_EdgeVertex;
611 isSuccess = InitEdgeVertexLength (TopoDS::Edge (theFirstShape),
612 TopoDS::Vertex (theSecondShape),
618 theComputedPlane = ComputePlane (aDirAttach);
619 theIsPlaneComputed = Standard_True;
624 else if (theSecondShape.ShapeType() == TopAbs_EDGE)
626 myGeometryType = GeometryType_Edges;
627 isSuccess = InitTwoEdgesLength (TopoDS::Edge (theFirstShape),
628 TopoDS::Edge (theSecondShape),
633 theComputedPlane = ComputePlane (aDirAttach);
634 theIsPlaneComputed = Standard_True;
639 else if (theSecondShape.ShapeType() == TopAbs_FACE)
641 myGeometryType = GeometryType_EdgeFace;
642 isSuccess = InitEdgeFaceLength (TopoDS::Edge (theFirstShape),
643 TopoDS::Face (theSecondShape),
648 theComputedPlane = ComputePlane (aDirAttach);
649 theIsPlaneComputed = Standard_True;
659 if (theSecondShape.ShapeType() == TopAbs_VERTEX)
661 myGeometryType = GeometryType_Points;
662 myFirstPoint = BRep_Tool::Pnt (TopoDS::Vertex (theFirstShape));
663 mySecondPoint = BRep_Tool::Pnt (TopoDS::Vertex (theSecondShape));
665 return IsValidPoints (myFirstPoint, mySecondPoint);
667 else if (theSecondShape.ShapeType() == TopAbs_EDGE)
669 myGeometryType = GeometryType_EdgeVertex;
670 isSuccess = InitEdgeVertexLength (TopoDS::Edge(theSecondShape),
671 TopoDS::Vertex(theFirstShape),
676 theComputedPlane = ComputePlane (aDirAttach);
677 theIsPlaneComputed = Standard_True;
685 case TopAbs_COMPOUND:
686 case TopAbs_COMPSOLID:
694 return Standard_False;
697 //=======================================================================
698 //function : InitOneShapePoints
699 //purpose : Initialization of two points where dimension layouts
701 // Attention: 1) <theShape> can be only the edge in currect implementation
702 // 2) No length for infinite edge
703 //=======================================================================
704 Standard_Boolean AIS_LengthDimension::InitOneShapePoints (const TopoDS_Shape& theShape)
706 if (theShape.ShapeType() != TopAbs_EDGE)
708 return Standard_False;
711 TopoDS_Edge anEdge = TopoDS::Edge (theShape);
713 BRepAdaptor_Curve aBrepCurve(anEdge);
714 Standard_Real aFirst = aBrepCurve.FirstParameter();
715 Standard_Real aLast = aBrepCurve.LastParameter();
717 if (aBrepCurve.GetType() != GeomAbs_Line)
719 return Standard_False;
722 Standard_Boolean isInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
725 return Standard_False;
728 myFirstPoint = aBrepCurve.Value (aBrepCurve.FirstParameter());
729 mySecondPoint = aBrepCurve.Value (aBrepCurve.LastParameter());
731 return IsValidPoints (myFirstPoint, mySecondPoint);
734 //=======================================================================
735 //function : GetTextPosition
737 //=======================================================================
738 const gp_Pnt AIS_LengthDimension::GetTextPosition() const
740 if (IsTextPositionCustom())
742 return myFixedTextPosition;
745 // Counts text position according to the dimension parameters
746 return GetTextPositionForLinear (myFirstPoint, mySecondPoint);
749 //=======================================================================
750 //function : SetTextPosition
752 //=======================================================================
753 void AIS_LengthDimension::SetTextPosition (const gp_Pnt& theTextPos)
760 myIsTextPositionFixed = Standard_True;
761 myFixedTextPosition = theTextPos;