0030520: VIS - IVtkTools_ShapePicker::GetPickPosition() returns incorrect point
[occt.git] / src / IVtkOCC / IVtkOCC_SelectableObject.cxx
1 // Created on: 2011-10-20 
2 // Created by: Roman KOZLOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS 
4 // 
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <AIS_Shape.hxx>
17 #include <BRepBndLib.hxx>
18 #include <IVtkOCC_SelectableObject.hxx>
19 #include <Select3D_SensitiveBox.hxx>
20 #include <SelectMgr_Selection.hxx>
21 #include <Standard_ErrorHandler.hxx>
22 #include <StdSelect_BRepOwner.hxx>
23 #include <StdSelect_BRepSelectionTool.hxx>
24 #include <TopoDS_Iterator.hxx>
25
26 IMPLEMENT_STANDARD_RTTIEXT(IVtkOCC_SelectableObject,SelectMgr_SelectableObject)
27
28 // Handle implementation
29
30
31 //============================================================================
32 // Method:  Constructor
33 // Purpose: Constructs a selectable object initalized by the given shape
34 //============================================================================
35 IVtkOCC_SelectableObject::IVtkOCC_SelectableObject (const IVtkOCC_Shape::Handle& theShape)
36 : SelectMgr_SelectableObject (PrsMgr_TOP_AllView),
37   myShape (theShape)
38 {
39   if (!myShape.IsNull())
40   {
41     myShape->SetSelectableObject (this);
42   }
43
44   // Minor stuff - but it facilitates usage of OCCT selection 
45   // classes dealing with deflection, see ComputeSelection() below
46   myOCCTDrawer = new Prs3d_Drawer();
47 }
48
49 //============================================================================
50 // Method:  Constructor
51 // Purpose: Constructs uninitialized selectable object.
52 //          setShape() should be called later.
53 //============================================================================
54 IVtkOCC_SelectableObject::IVtkOCC_SelectableObject()
55 : SelectMgr_SelectableObject (PrsMgr_TOP_AllView),
56   myShape (0)
57 { }
58
59 //============================================================================
60 // Method:  Destructor
61 // Purpose: 
62 //============================================================================
63 IVtkOCC_SelectableObject::~IVtkOCC_SelectableObject()
64 { }
65
66 //============================================================================
67 // Method:  SetShape
68 // Purpose: Sets the selectable shape
69 //============================================================================
70 void IVtkOCC_SelectableObject::SetShape (const IVtkOCC_Shape::Handle& theShape)
71 {
72   myShape = theShape;
73   if (! myShape.IsNull())
74   {
75     myShape->SetSelectableObject (this);
76   }
77
78   // Shape has changed -> Clear all internal data
79   myBndBox.SetVoid();
80   myselections.Clear();
81 }
82
83 //============================================================================
84 // Method:  ComputeSelection
85 // Purpose: Internal method, computes selection data for viewer selector
86 //============================================================================
87 void IVtkOCC_SelectableObject::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
88                                                  const Standard_Integer theMode)
89 {
90   if (myShape.IsNull())
91   {
92     return;
93   }
94
95   TopoDS_Shape anOcctShape = myShape->GetShape();
96
97   if (anOcctShape.ShapeType() == TopAbs_COMPOUND && anOcctShape.NbChildren() == 0)
98   {
99     // Shape empty -> go away
100     return;
101   }
102
103   TopAbs_ShapeEnum aTypeOfSel = AIS_Shape::SelectionType (theMode);
104
105   Standard_Real aDeflection = myOCCTDrawer->MaximalChordialDeviation();
106   if (myOCCTDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE)
107   {
108     Bnd_Box aBndBox;
109     BRepBndLib::Add (anOcctShape, aBndBox);
110     if (!aBndBox.IsVoid())
111     {
112       Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
113       aBndBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
114       aDeflection = Max (aXmax - aXmin, Max (aYmax - aYmin, aZmax - aZmin)) * 
115         myOCCTDrawer->DeviationCoefficient();
116     }
117   }
118
119   // Assume the shape has been displayed already -> triangulation should exist
120   Standard_Boolean isAutoTriangulation = Standard_False;
121
122   try
123   {
124     OCC_CATCH_SIGNALS
125     StdSelect_BRepSelectionTool::Load (theSelection,
126                                        this,
127                                        anOcctShape,
128                                        aTypeOfSel,
129                                        aDeflection,
130                                        myOCCTDrawer->DeviationAngle(),
131                                        isAutoTriangulation);
132   }
133   catch (Standard_Failure)
134   {
135     if (theMode == 0)
136     {
137       Bnd_Box aBndBox = BoundingBox();
138       Handle(StdSelect_BRepOwner) aOwner = new StdSelect_BRepOwner (anOcctShape, this);
139       Handle(Select3D_SensitiveBox) aSensitiveBox = 
140         new Select3D_SensitiveBox (aOwner, aBndBox);
141       theSelection->Add (aSensitiveBox);
142     }
143   }
144 }
145
146 //============================================================================
147 // Method:  BoundingBox
148 // Purpose:
149 //============================================================================
150 const Bnd_Box& IVtkOCC_SelectableObject::BoundingBox()
151 {
152   if (myShape.IsNull())
153   {
154     myBndBox.SetVoid();
155     return myBndBox;
156   }
157
158   TopoDS_Shape anOcctShape = myShape->GetShape();
159
160   if (anOcctShape.ShapeType() == TopAbs_COMPOUND && anOcctShape.NbChildren() == 0)
161   {
162     // Shape empty -> nothing to do
163     myBndBox.SetVoid ();
164     return myBndBox;
165   }
166
167   if (myBndBox.IsVoid())
168   {
169     // Add only edges and vertices, in case of troubles this should work anyway
170     BRepBndLib::AddClose (anOcctShape, myBndBox);
171   }
172
173   return myBndBox;
174 }
175
176 //============================================================================
177 // Method:  BoundingBox
178 // Purpose:
179 //============================================================================
180 void IVtkOCC_SelectableObject::BoundingBox (Bnd_Box& theBndBox)
181 {
182   BoundingBox();
183   theBndBox = myBndBox;
184 }