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 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
21 #include <AIS_LengthDimension.hxx>
24 #include <BRep_Tool.hxx>
25 #include <BRepAdaptor_Curve.hxx>
26 #include <BRepGProp_Face.hxx>
27 #include <BRepLib_MakeVertex.hxx>
28 #include <BRepTopAdaptor_FClass2d.hxx>
31 #include <Geom_Line.hxx>
32 #include <gce_MakeDir.hxx>
33 #include <Graphic3d_Group.hxx>
34 #include <Graphic3d_ArrayOfSegments.hxx>
35 #include <PrsMgr_PresentationManager.hxx>
36 #include <Prs3d_Root.hxx>
38 #include <TopExp_Explorer.hxx>
40 IMPLEMENT_STANDARD_HANDLE(AIS_LengthDimension, AIS_Dimension)
41 IMPLEMENT_STANDARD_RTTIEXT(AIS_LengthDimension, AIS_Dimension)
43 //=======================================================================
44 //function : Constructor
45 //purpose : Dimension between two points
46 //=======================================================================
48 AIS_LengthDimension::AIS_LengthDimension (const gp_Pnt& theFirstPoint,
49 const gp_Pnt& theSecondPoint,
50 const gp_Pln& theDimensionPlane)
53 myIsInitialized = Standard_True;
54 myFirstPoint = theFirstPoint;
55 mySecondPoint = theSecondPoint;
56 myFirstShape = BRepLib_MakeVertex (myFirstPoint);
57 mySecondShape = BRepLib_MakeVertex (mySecondPoint);
59 SetKindOfDimension (AIS_KOD_LENGTH);
60 SetWorkingPlane (theDimensionPlane);
64 //=======================================================================
65 //function : Constructor
66 //purpose : Dimension between two shape
67 //=======================================================================
69 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Shape& theFirstShape,
70 const TopoDS_Shape& theSecondShape,
71 const gp_Pln& theWorkingPlane)
74 myIsInitialized = Standard_False;
75 myFirstShape = theFirstShape;
76 mySecondShape = theSecondShape;
78 SetKindOfDimension (AIS_KOD_LENGTH);
79 SetWorkingPlane (theWorkingPlane);
83 //=======================================================================
84 //function : Constructor
85 //purpose : Dimension of one edge
86 //=======================================================================
88 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Edge& theEdge,
89 const gp_Pln& theWorkingPlane)
92 myIsInitialized = Standard_False;
93 myFirstShape = theEdge;
95 SetKindOfDimension (AIS_KOD_LENGTH);
96 SetWorkingPlane (theWorkingPlane);
100 //=======================================================================
101 //function : Constructor
102 //purpose : Dimension between two faces
103 //=======================================================================
105 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFirstFace,
106 const TopoDS_Face& theSecondFace)
109 myIsInitialized = Standard_False;
110 myFirstShape = theFirstFace;
111 mySecondShape = theSecondFace;
113 SetKindOfDimension (AIS_KOD_LENGTH);
117 //=======================================================================
118 //function : Constructor
119 //purpose : Dimension between two shape
120 //=======================================================================
122 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFace,
123 const TopoDS_Edge& theEdge)
126 myIsInitialized = Standard_False;
127 myFirstShape = theFace;
128 mySecondShape = theEdge;
130 SetKindOfDimension (AIS_KOD_LENGTH);
134 //=======================================================================
135 //function : initTwoEdgesLength
136 //purpose : Initialization of dimanesion between two linear edges
137 //=======================================================================
139 Standard_Boolean AIS_LengthDimension::initTwoEdgesLength (const TopoDS_Edge & theFirstEdge,
140 const TopoDS_Edge& theSecondEdge,
141 gp_Dir& theDirAttach)
143 Standard_Integer anExtShapeIndex = 0;
144 BRepAdaptor_Curve aFirstCurveAdapt (theFirstEdge);
145 if (aFirstCurveAdapt.GetType() != GeomAbs_Line)
146 return Standard_False;
147 BRepAdaptor_Curve aSecondCurveAdapt (theSecondEdge);
148 if (aSecondCurveAdapt.GetType() != GeomAbs_Line)
149 return Standard_False;
150 Handle(Geom_Curve) aFirstCurve, aSecondCurve;
151 gp_Pnt aPoint11,aPoint12,aPoint21,aPoint22;
152 Standard_Boolean isFirstInfinite (Standard_False),
153 isSecondInfinite (Standard_False);
154 Handle(Geom_Curve) anExtCurve;
156 if (!AIS::ComputeGeometry (theFirstEdge, theSecondEdge,anExtShapeIndex,
157 aFirstCurve, aSecondCurve, aPoint11, aPoint12,
158 aPoint21, aPoint22, anExtCurve, isFirstInfinite,
159 isSecondInfinite, new Geom_Plane(GetWorkingPlane())))
160 return Standard_False;
162 const Handle(Geom_Line)& aGeomLine1 = (Handle(Geom_Line)&) aFirstCurve;
163 const Handle(Geom_Line)& aGeomLine2 = (Handle(Geom_Line)&) aSecondCurve;
164 const gp_Lin& aLin1 = aGeomLine1->Lin();
165 const gp_Lin& aLin2 = aGeomLine2->Lin();
167 myValue = aLin1.Distance (aLin2);
168 theDirAttach = aLin1.Direction();
171 if (!isFirstInfinite)
173 gp_Pnt aPoint2 = ElCLib::Value(ElCLib::Parameter (aLin2, aPoint11), aLin2);
174 aCurPos.SetXYZ((aPoint11.XYZ() + aPoint2.XYZ()) / 2.);
176 else if (!isSecondInfinite)
178 gp_Pnt aPoint2 = ElCLib::Value (ElCLib::Parameter (aLin1, aPoint21), aLin1);
179 aCurPos.SetXYZ ((aPoint21.XYZ() + aPoint2.XYZ()) / 2.);
182 aCurPos.SetXYZ((aLin1.Location().XYZ() + aLin2.Location().XYZ()) / 2.);
184 // Offset to avoid confusion Edge and Dimension
185 gp_Vec anOffset(theDirAttach);
186 anOffset = anOffset * myDrawer->DimensionAspect()->ArrowAspect()->Length()*(-10.);
187 aCurPos.Translate (anOffset);
189 // Find attachment points
190 if (!isFirstInfinite)
192 if (aCurPos.Distance (aPoint11) > aCurPos.Distance (aPoint12))
193 myFirstPoint = aPoint12;
195 myFirstPoint = aPoint11;
198 myFirstPoint = ElCLib::Value (ElCLib::Parameter (aLin1, aCurPos), aLin1);
200 if (!isSecondInfinite)
202 if (aCurPos.Distance (aPoint21) > aCurPos.Distance (aPoint22))
203 mySecondPoint = aPoint22;
205 mySecondPoint = aPoint21;
208 mySecondPoint = ElCLib::Value (ElCLib::Parameter (aLin2, aCurPos), aLin2);
210 return Standard_True;
213 //=======================================================================
214 //function : initEdgeVertexLength
215 //purpose : for first edge and second vertex shapes
216 //=======================================================================
218 Standard_Boolean AIS_LengthDimension::initEdgeVertexLength (const TopoDS_Edge & theEdge,
219 const TopoDS_Vertex & theVertex,
220 gp_Dir & theDirAttach,
221 Standard_Boolean isInfinite)
223 gp_Pnt anEdgePoint1,anEdgePoint2;
224 Handle(Geom_Curve) aCurve;
225 Handle(Geom_Curve) anExtCurve;
226 Standard_Boolean isEdgeOnPlane, isVertexOnPlane;
227 if (!AIS::ComputeGeometry(theEdge,aCurve,anEdgePoint1,anEdgePoint2,
228 anExtCurve,isInfinite,isEdgeOnPlane, new Geom_Plane (GetWorkingPlane())))
229 return Standard_False;
230 AIS::ComputeGeometry (theVertex, myFirstPoint, new Geom_Plane(GetWorkingPlane()), isVertexOnPlane);
232 const Handle(Geom_Line)& aGeomLine = (Handle(Geom_Line)&) aCurve;
233 const gp_Lin& aLin = aGeomLine->Lin();
235 myValue = aLin.Distance( myFirstPoint);
236 theDirAttach = aLin.Direction();
238 gp_Pnt aPoint = ElCLib::Value(ElCLib::Parameter(aLin,myFirstPoint),aLin);
239 gp_Pnt aCurPos((myFirstPoint.XYZ() + aPoint.XYZ())/2.);
243 if (aCurPos.Distance (anEdgePoint1) > aCurPos.Distance (anEdgePoint2))
244 mySecondPoint = anEdgePoint2;
246 mySecondPoint = anEdgePoint1;
249 mySecondPoint = ElCLib::Value (ElCLib::Parameter (aLin, aCurPos), aLin);
250 return Standard_True;
253 //=======================================================================
254 //function : initEdgeVertexLength
256 //=======================================================================
258 Standard_Boolean AIS_LengthDimension::initEdgeFaceLength (const TopoDS_Edge& theEdge,
259 const TopoDS_Face& theFace,
260 gp_Dir& theDirAttach)
262 // The first attachment point is <aPoint1> from the reference <anEdge>.
263 // Find the second attachment point which belongs to the reference face
264 // Iterate over the edges of the face and find the point <aFacePoint1>.
265 // It is the closest point according to <aPoint1>.
266 TopoDS_Vertex aVertex1, aVertex2;
267 TopExp::Vertices (theEdge, aVertex1, aVertex2);
268 myFirstPoint = BRep_Tool::Pnt (aVertex1);
269 gp_Pnt aPoint = BRep_Tool::Pnt (aVertex2);
270 gp_Pnt2d aFacePoint1uv, aFacePoint2uv;
271 Standard_Real aDist1 = RealLast ();
272 Standard_Real aDist2 = RealLast ();
274 TopExp_Explorer anIt (theFace, TopAbs_EDGE);
275 for (; anIt.More (); anIt.Next ())
277 const TopoDS_Edge aFaceEdge = TopoDS::Edge(anIt.Current ());
278 if (aFaceEdge == theEdge)
279 return Standard_False;
280 TopExp::Vertices (aFaceEdge, aVertex1, aVertex2);
281 gp_Pnt aFacePoint1c = BRep_Tool::Pnt (aVertex1);
282 gp_Pnt aFacePoint2c = BRep_Tool::Pnt (aVertex2);
283 Standard_Real aDistc1 = myFirstPoint.SquareDistance (aFacePoint1c);
284 Standard_Real aDistc2 = myFirstPoint.SquareDistance (aFacePoint2c);
285 if (aDistc1 <= aDistc2)
287 if (aDistc1 <= aDist1)
289 aDistc2 = aPoint.SquareDistance (aFacePoint2c);
290 if (aDistc2 <= aDist2)
292 mySecondPoint = aFacePoint1c;
295 BRep_Tool::UVPoints (aFaceEdge, theFace, aFacePoint1uv, aFacePoint2uv);
301 if (aDistc2 <= aDist1)
303 aDistc1 = aPoint.SquareDistance (aFacePoint1c);
304 if (aDistc1 <= aDist2)
306 mySecondPoint = aFacePoint2c;
309 BRep_Tool::UVPoints (aFaceEdge, theFace, aFacePoint2uv, aFacePoint1uv);
315 gp_Vec anOffsetDirection (0.0, 0.0, 0.0);
317 //The offset direction is the normal to the face at the point FP1
318 BRepGProp_Face aGFace;
319 aGFace.Load (theFace);
320 aGFace.Normal (aFacePoint1uv.X(), aFacePoint1uv.Y(), aPoint, anOffsetDirection);
322 if (anOffsetDirection.Magnitude () > Precision::Confusion ())
324 theDirAttach = gp_Dir (anOffsetDirection);
326 else theDirAttach = gp::DZ ();
328 gp_Vec aVector (theDirAttach);
329 aVector.Multiply (1.5 * myValue);
331 return Standard_True;
334 //=======================================================================
335 //function : initTwoShapesPoints
336 //purpose : Initialization of two points where dimension layouts
338 //=======================================================================
340 Standard_Boolean AIS_LengthDimension::initTwoShapesPoints (const TopoDS_Shape& theFirstShape,
341 const TopoDS_Shape& theSecondShape)
344 Standard_Boolean isInfinite = Standard_False;
345 Standard_Boolean isSuccess = Standard_False;
346 switch (theFirstShape.ShapeType())
350 // Initialization for face
352 Handle(Geom_Surface) aFirstSurface;
353 AIS_KindOfSurface aFirstSurfKind;
354 Standard_Real aFirstOffset;
355 TopoDS_Face aFirstFace = TopoDS::Face (theFirstShape);
356 AIS::InitFaceLength (TopoDS::Face (theFirstShape), aFirstPlane,
357 aFirstSurface,aFirstSurfKind, aFirstOffset);
359 if (theSecondShape.ShapeType () == TopAbs_FACE)
361 // Initialization for face
363 Handle(Geom_Surface) aSecondSurface;
364 AIS_KindOfSurface aSecondSurfKind;
365 Standard_Real aSecondOffset;
366 TopoDS_Face aSecondFace = TopoDS::Face (theSecondShape);
367 AIS::InitFaceLength (aSecondFace, aSecondPlane,
368 aSecondSurface, aSecondSurfKind, aSecondOffset);
369 if (aFirstSurfKind == AIS_KOS_Plane)
371 TopExp_Explorer anExplorer (theFirstShape, TopAbs_VERTEX);
372 // In case of infinite planes
373 if (!anExplorer.More())
374 myFirstPoint = aFirstPlane.Location();
375 else myFirstPoint = BRep_Tool::Pnt (TopoDS::Vertex (anExplorer.Current()));
376 mySecondPoint = AIS::ProjectPointOnPlane (myFirstPoint, aSecondPlane);
378 gp_Dir aLengthDir = aFirstPlane.Axis().Direction();
379 gp_Dir aDirAttach = aFirstPlane.Position().XDirection();
380 Quantity_Parameter anU, aV;
381 ElSLib::Parameters (aSecondPlane, mySecondPoint, anU, aV);
382 BRepTopAdaptor_FClass2d aClassifier (aSecondFace, Precision::Confusion());
383 TopAbs_State aState = aClassifier.Perform (gp_Pnt2d (anU, aV), Standard_False);
384 if (aState == TopAbs_OUT || aState == TopAbs_UNKNOWN)
386 mySecondPoint = AIS::Nearest(aSecondFace, myFirstPoint);
387 if (myFirstPoint.Distance(mySecondPoint) > Precision::Confusion())
389 gp_Vec aVec = gp_Vec(myFirstPoint, mySecondPoint) ^ aLengthDir;
390 if (aVec.SquareMagnitude() > Precision::SquareConfusion())
391 aDirAttach = aVec ^ aLengthDir;
394 isSuccess = Standard_True;
396 else // curvilinear faces
398 AIS::ComputeLengthBetweenCurvilinearFaces (aFirstFace, aSecondFace, aFirstSurface,
399 aSecondSurface, Standard_True, myValue,
400 mySelectionGeom.TextPos, myFirstPoint,
401 mySecondPoint, aDirAttach);
402 isSuccess = Standard_True;
405 else if (theFirstShape.ShapeType() == TopAbs_EDGE)
407 isSuccess = initEdgeFaceLength (TopoDS::Edge (theFirstShape),
408 TopoDS::Face (theSecondShape),
411 if (!myIsWorkingPlaneCustom)
412 resetWorkingPlane(gp_Pln(myFirstPoint, aDirAttach));
417 if (theSecondShape.ShapeType() == TopAbs_VERTEX)
419 return initEdgeVertexLength (TopoDS::Edge(theFirstShape),
420 TopoDS::Vertex(theSecondShape),
421 aDirAttach, isInfinite);
423 else if (theSecondShape.ShapeType() == TopAbs_EDGE)
425 return initTwoEdgesLength (TopoDS::Edge(theFirstShape),
426 TopoDS::Edge(theSecondShape),
433 if (theSecondShape.ShapeType() == TopAbs_VERTEX)
435 myFirstPoint = BRep_Tool::Pnt (TopoDS::Vertex (theFirstShape));
436 mySecondPoint = BRep_Tool::Pnt (TopoDS::Vertex (theSecondShape));
437 isSuccess = Standard_True;
439 else if (theSecondShape.ShapeType() == TopAbs_EDGE)
441 return initEdgeVertexLength (TopoDS::Edge(theSecondShape),
442 TopoDS::Vertex(theFirstShape),
443 aDirAttach, isInfinite);
447 case TopAbs_COMPOUND:
448 case TopAbs_COMPSOLID:
453 // nothing to do for these kinds
459 //=======================================================================
460 //function : initOneShapePoints
461 //purpose : Initialization of two points where dimension layouts
463 // Attention: 1) <theShape> can be only the edge in currect implementation
464 // 2) No length for infinite edge
465 //=======================================================================
467 Standard_Boolean AIS_LengthDimension::initOneShapePoints (const TopoDS_Shape& theShape)
469 if (theShape.ShapeType() == TopAbs_EDGE)
471 TopoDS_Edge anEdge = TopoDS::Edge (theShape);
472 BRepAdaptor_Curve aBrepCurve(anEdge);
473 Standard_Real aFirst = aBrepCurve.FirstParameter(),
474 aLast = aBrepCurve.LastParameter();
475 Standard_Boolean isInfinite = (Precision::IsInfinite (aFirst)
476 || Precision::IsInfinite (aLast));
478 return Standard_False;
480 myFirstPoint = aBrepCurve.Value (aBrepCurve.FirstParameter());
481 mySecondPoint = aBrepCurve.Value (aBrepCurve.LastParameter());
483 else // Some other kinds of shapes
484 return Standard_False;
485 return Standard_True;
488 //=======================================================================
491 //=======================================================================
493 void AIS_LengthDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
494 const Handle(Prs3d_Presentation)& thePresentation,
495 const Standard_Integer theMode)
497 thePresentation->Clear();
498 mySelectionGeom.Clear (theMode);
500 // Initialization of points, if they are not set
501 if (!myIsInitialized)
503 if (myShapesNumber == 1)
505 myIsInitialized = initOneShapePoints (myFirstShape);
507 else if (myShapesNumber == 2)
509 myIsInitialized = initTwoShapesPoints (myFirstShape, mySecondShape);
517 // If initialization failed
518 if (!myIsInitialized)
523 drawLinearDimension (thePresentation, theMode);
526 //=======================================================================
527 //function : ComputeValue
529 //=======================================================================
531 void AIS_LengthDimension::computeValue()
533 myValue = myFirstPoint.Distance (mySecondPoint);
534 AIS_Dimension::computeValue ();