1 // Created on: 1998-03-26
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16 
17 #ifndef _SelectMgr_SortCriterion_HeaderFile
18 #define _SelectMgr_SortCriterion_HeaderFile
19 
20 #include <Graphic3d_ZLayerId.hxx>
21 #include <Precision.hxx>
22 #include <Select3D_SensitiveEntity.hxx>
23 
24 //! This class provides data and criterion for sorting candidate
25 //! entities in the process of interactive selection by mouse click
26 class SelectMgr_SortCriterion
27 {
28 public:
29 
30   Handle(Select3D_SensitiveEntity) Entity; //!< detected entity
31   gp_Pnt             Point;           //!< 3D point
32   Standard_Real      Depth;           //!< distance from the view plane to the entity
33   Standard_Real      MinDist;         //!< distance from the clicked point to the entity on the view plane
34   Standard_Real      Tolerance;       //!< tolerance used for selecting candidates
35   Standard_Integer   Priority;        //!< selection priority
36   Standard_Integer   ZLayerPosition;  //!< ZLayer rendering order index, stronger than a depth
37   Standard_Integer   NbOwnerMatches;  //!< overall number of entities collected for the same owner
38   Standard_Boolean   ToPreferClosest; //!< whether closest object is preferred even if has less priority
39 
40 public:
41   DEFINE_STANDARD_ALLOC
42 
43   //! Empty constructor.
SelectMgr_SortCriterion()44   SelectMgr_SortCriterion()
45   : Depth    (0.0),
46     MinDist  (0.0),
47     Tolerance(0.0),
48     Priority (0),
49     ZLayerPosition  (0),
50     NbOwnerMatches  (0),
51     ToPreferClosest (Standard_True) {}
52 
53   //! Comparison operator.
operator >(const SelectMgr_SortCriterion & theOther) const54   bool operator> (const SelectMgr_SortCriterion& theOther) const { return IsGreater (theOther); }
55 
56   //! Comparison operator.
operator <(const SelectMgr_SortCriterion & theOther) const57   bool operator< (const SelectMgr_SortCriterion& theOther) const { return IsLower   (theOther); }
58 
59   //! Compare with another item.
IsGreater(const SelectMgr_SortCriterion & theOther) const60   bool IsGreater (const SelectMgr_SortCriterion& theOther) const
61   {
62     // the object within different ZLayer groups can not be compared by depth
63     if (ZLayerPosition != theOther.ZLayerPosition)
64     {
65       return ZLayerPosition > theOther.ZLayerPosition;
66     }
67 
68     if (ToPreferClosest)
69     {
70       // closest object is selected unless difference is within tolerance
71       if (Abs (Depth - theOther.Depth) > (Tolerance + theOther.Tolerance))
72       {
73         return Depth < theOther.Depth;
74       }
75 
76       // if two objects have similar depth, select the one with higher priority
77       if (Priority > theOther.Priority)
78       {
79         return true;
80       }
81 
82       // if priorities are equal, one closest to the mouse
83       return Priority == theOther.Priority
84           && MinDist  <  theOther.MinDist;
85     }
86 
87     // old logic (OCCT version <= 6.3.1)
88     if (Priority > theOther.Priority)
89     {
90       return true;
91     }
92     else if (Priority != theOther.Priority)
93     {
94       return false;
95     }
96 
97     if (Abs (Depth - theOther.Depth) <= Precision::Confusion())
98     {
99       return MinDist < theOther.MinDist;
100     }
101 
102     return Depth < theOther.Depth;
103   }
104 
105   //! Compare with another item.
IsLower(const SelectMgr_SortCriterion & theOther) const106   bool IsLower (const SelectMgr_SortCriterion& theOther) const
107   {
108     // the object within different ZLayer groups can not be compared by depth
109     if (ZLayerPosition != theOther.ZLayerPosition)
110     {
111       return ZLayerPosition < theOther.ZLayerPosition;
112     }
113 
114     if (ToPreferClosest)
115     {
116       // closest object is selected unless difference is within tolerance
117       if (ToPreferClosest
118        && Abs (Depth - theOther.Depth) > (Tolerance + theOther.Tolerance))
119       {
120         return Depth > theOther.Depth;
121       }
122 
123       // if two objects have similar depth, select the one with higher priority
124       if (Priority < theOther.Priority)
125       {
126         return true;
127       }
128 
129       // if priorities are equal, one closest to the mouse
130       return Priority == theOther.Priority
131           && MinDist  >  theOther.MinDist;
132     }
133 
134     // old logic (OCCT version <= 6.3.1)
135     if (Priority > theOther.Priority)
136     {
137       return false;
138     }
139     else if (Priority != theOther.Priority)
140     {
141       return true;
142     }
143 
144     if (Abs (Depth - theOther.Depth) <= Precision::Confusion())
145     {
146       return MinDist > theOther.MinDist;
147     }
148 
149     return Depth > theOther.Depth;
150   }
151 
152 };
153 
154 #endif // _SelectMgr_SortCriterion_HeaderFile
155