// Created on: 1995-02-15 // Created by: Roberc Coublanc // Copyright (c) 1995-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #ifndef _SelectMgr_ViewerSelector_HeaderFile #define _SelectMgr_ViewerSelector_HeaderFile #include "OSD_Chronometer.hxx" #include "SelectMgr_BVHThreadPool.hxx" #include "SelectMgr_EntityOwner.hxx" #include "SelectMgr_SortCriterion.hxx" #include "NCollection_IndexedDataMap.hxx" #include "SelectMgr_SelectingVolumeManager.hxx" #include "SelectMgr_Selection.hxx" #include "SelectMgr_SelectableObject.hxx" #include "SelectMgr_SelectableObjectSet.hxx" #include "SelectMgr_StateOfSelection.hxx" #include "SelectMgr_ToleranceMap.hxx" #include "SelectMgr_TypeOfDepthTolerance.hxx" #include "Standard_OStream.hxx" #include "Standard_Transient.hxx" #include "StdSelect_TypeOfSelectionImage.hxx" #include "Standard_Integer.hxx" #include "NCollection_Array1.hxx" #include "NCollection_HArray1.hxx" class SelectMgr_SensitiveEntitySet; class SelectMgr_EntityOwner; class Select3D_SensitiveEntity; class V3d_View; // resolve name collisions with X11 headers #ifdef Status #undef Status #endif //! A framework to define finding, sorting the sensitive //! primitives in a view. Services are also provided to //! define the return of the owners of those primitives //! selected. The primitives are sorted by criteria such //! as priority of the primitive or its depth in the view //! relative to that of other primitives. //! Note that in 3D, the inheriting framework //! StdSelect_ViewerSelector3d is only to be used //! if you do not want to use the services provided by //! AIS. //! Two tools are available to find and select objects //! found at a given position in the view. If you want to //! select the owners of all the objects detected at //! point x,y,z you use the Init - More - Next - Picked //! loop. If, on the other hand, you want to select only //! one object detected at that point, you use the Init - //! More - OnePicked loop. In this iteration, More is //! used to see if an object was picked and //! OnePicked, to get the object closest to the pick position. //! Viewer selectors are driven by //! SelectMgr_SelectionManager, and manipulate //! the SelectMgr_Selection objects given to them by //! the selection manager. //! //! Tolerances are applied to the entities in the following way: //! 1. tolerance value stored in mytolerance will be used to calculate initial //! selecting frustum, which will be applied for intersection testing during //! BVH traverse; //! 2. if tolerance of sensitive entity is less than mytolerance, the frustum for //! intersection detection will be resized according to its sensitivity. class SelectMgr_ViewerSelector : public Standard_Transient { DEFINE_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient) friend class SelectMgr_SelectionManager; public: //! Constructs an empty selector object. Standard_EXPORT SelectMgr_ViewerSelector(); //! Returns custom pixel tolerance value. int CustomPixelTolerance() const { return myTolerances.CustomTolerance(); } //! Sets the pixel tolerance . Standard_EXPORT void SetPixelTolerance(const int theTolerance); //! Returns the largest sensitivity of picking double Sensitivity() const { return myTolerances.Tolerance(); } //! Returns the largest pixel tolerance. int PixelTolerance() const { return myTolerances.Tolerance(); } //! Sorts the detected entities by priority and distance. Standard_EXPORT virtual void SortResult() const; //! Returns the picked element with the highest priority, //! and which is the closest to the last successful mouse position. occ::handle OnePicked() const { return mystored.IsEmpty() ? occ::handle() : Picked(1); } //! Return the flag determining precedence of picked depth (distance from eye to entity) over //! entity priority in sorted results; TRUE by default. When flag is TRUE, priority will be //! considered only if entities have the same depth within the tolerance. When flag is FALSE, //! entities with higher priority will be in front regardless of their depth (like x-ray). bool ToPickClosest() const { return myToPreferClosest; } //! Set flag determining precedence of picked depth over entity priority in sorted results. void SetPickClosest(bool theToPreferClosest) { myToPreferClosest = theToPreferClosest; } //! Return the type of tolerance for considering two entities having a similar depth (distance //! from eye to entity); SelectMgr_TypeOfDepthTolerance_SensitivityFactor by default. SelectMgr_TypeOfDepthTolerance DepthToleranceType() const { return myDepthTolType; } //! Return the tolerance for considering two entities having a similar depth (distance from eye to //! entity). double DepthTolerance() const { return myDepthTolerance; } //! Set the tolerance for considering two entities having a similar depth (distance from eye to //! entity). //! @param[in] theType type of tolerance value //! @param[in] theTolerance tolerance value in 3D scale (SelectMgr_TypeOfDepthTolerance_Uniform) //! or in pixels (SelectMgr_TypeOfDepthTolerance_UniformPixels); //! value is ignored in case of //! SelectMgr_TypeOfDepthTolerance_SensitivityFactor void SetDepthTolerance(SelectMgr_TypeOfDepthTolerance theType, double theTolerance) { myDepthTolType = theType; myDepthTolerance = theTolerance; } //! Returns the number of detected owners. int NbPicked() const { return mystored.Extent(); } //! Clears picking results. Standard_EXPORT void ClearPicked(); //! Empties all the tables, removes all selections... void Clear() { ClearPicked(); } //! Returns the entity Owner for the object picked at specified position. //! @param theRank rank of detected object within range 1...NbPicked() Standard_EXPORT occ::handle Picked(const int theRank) const; //! Returns the Entity for the object picked at specified position. //! @param theRank rank of detected object within range 1...NbPicked() Standard_EXPORT const SelectMgr_SortCriterion& PickedData(const int theRank) const; //! Returns the Entity for the object picked at specified position. //! @param theRank rank of detected object within range 1...NbPicked() const occ::handle& PickedEntity(const int theRank) const { return PickedData(theRank).Entity; } //! Returns the 3D point (intersection of picking axis with the object nearest to eye) //! for the object picked at specified position. //! @param theRank rank of detected object within range 1...NbPicked() gp_Pnt PickedPoint(const int theRank) const { return PickedData(theRank).Point; } //! Remove picked entities associated with specified object. Standard_EXPORT bool RemovePicked(const occ::handle& theObject); Standard_EXPORT bool Contains(const occ::handle& theObject) const; //! Returns the default builder used to construct BVH of entity set. const occ::handle EntitySetBuilder() { return myEntitySetBuilder; } //! Sets the default builder used to construct BVH of entity set. //! The new builder will be also assigned for already defined objects, but computed BVH trees will //! not be invalidated. Standard_EXPORT void SetEntitySetBuilder(const occ::handle& theBuilder); //! Returns the list of selection modes ModeList found in //! this selector for the selectable object aSelectableObject. //! Returns true if aSelectableObject is referenced inside //! this selector; returns false if the object is not present //! in this selector. Standard_EXPORT bool Modes( const occ::handle& theSelectableObject, NCollection_List& theModeList, const SelectMgr_StateOfSelection theWantedState = SelectMgr_SOS_Any) const; //! Returns true if the selectable object //! aSelectableObject having the selection mode aMode //! is active in this selector. Standard_EXPORT bool IsActive(const occ::handle& theSelectableObject, const int theMode) const; //! Returns true if the selectable object //! aSelectableObject having the selection mode aMode //! is in this selector. Standard_EXPORT bool IsInside(const occ::handle& theSelectableObject, const int theMode) const; //! Returns the selection status Status of the selection aSelection. Standard_EXPORT SelectMgr_StateOfSelection Status(const occ::handle& theSelection) const; Standard_EXPORT TCollection_AsciiString Status(const occ::handle& theSelectableObject) const; //! Returns the list of active entity owners Standard_EXPORT void ActiveOwners( NCollection_List>& theOwners) const; //! Adds new object to the map of selectable objects Standard_EXPORT void AddSelectableObject( const occ::handle& theObject); //! Adds new selection to the object and builds its BVH tree Standard_EXPORT void AddSelectionToObject( const occ::handle& theObject, const occ::handle& theSelection); //! Moves existing object from set of not transform persistence objects //! to set of transform persistence objects (or vice versa). Standard_EXPORT void MoveSelectableObject( const occ::handle& theObject); //! Removes selectable object from map of selectable ones Standard_EXPORT void RemoveSelectableObject( const occ::handle& theObject); //! Removes selection of the object and marks its BVH tree for rebuild Standard_EXPORT void RemoveSelectionOfObject( const occ::handle& theObject, const occ::handle& theSelection); //! Marks BVH of selectable objects for rebuild. Parameter theIsForce set as true //! guarantees that 1st level BVH for the viewer selector will be rebuilt during this call Standard_EXPORT void RebuildObjectsTree(const bool theIsForce = false); //! Marks BVH of sensitive entities of particular selectable object for rebuild. Parameter //! theIsForce set as true guarantees that 2nd level BVH for the object given will be //! rebuilt during this call Standard_EXPORT void RebuildSensitivesTree( const occ::handle& theObject, const bool theIsForce = false); //! Returns instance of selecting volume manager of the viewer selector SelectMgr_SelectingVolumeManager& GetManager() { return mySelectingVolumeMgr; } //! Return map of selectable objects. const SelectMgr_SelectableObjectSet& SelectableObjects() const { return mySelectableObjects; } //! Marks all added sensitive entities of all objects as non-selectable Standard_EXPORT void ResetSelectionActivationStatus(); //! Is used for rectangular selection only //! If theIsToAllow is false, only fully included sensitives will be detected, otherwise the //! algorithm will mark both included and overlapped entities as matched Standard_EXPORT void AllowOverlapDetection(const bool theIsToAllow); public: //! Picks the sensitive entity at the pixel coordinates of //! the mouse and . The selector looks for touched areas and owners. Standard_EXPORT void Pick(const int theXPix, const int theYPix, const occ::handle& theView); //! Picks the sensitive entity according to the minimum //! and maximum pixel values , , //! and defining a 2D area for selection in the 3D view aView. Standard_EXPORT void Pick(const int theXPMin, const int theYPMin, const int theXPMax, const int theYPMax, const occ::handle& theView); //! pick action - input pixel values for polyline selection for selection. Standard_EXPORT void Pick(const NCollection_Array1& thePolyline, const occ::handle& theView); //! Picks the sensitive entity according to the input axis. //! This is geometric intersection 3D objects by axis //! (camera parameters are ignored and objects with transform persistence are skipped). Standard_EXPORT void Pick(const gp_Ax1& theAxis, const occ::handle& theView); //! Dump of detection results into image. //! This method performs axis picking for each pixel in the image //! and generates a color depending on picking results and selection image type. //! @param theImage result image, should be initialized //! @param theView 3D view defining camera position //! @param theType type of image to define //! @param thePickedIndex index of picked entity (1 means topmost) Standard_EXPORT bool ToPixMap(Image_PixMap& theImage, const occ::handle& theView, const StdSelect_TypeOfSelectionImage theType, const int thePickedIndex = 1); public: //! Displays sensitives in view . Standard_EXPORT void DisplaySensitive(const occ::handle& theView); Standard_EXPORT void ClearSensitive(const occ::handle& theView); Standard_EXPORT void DisplaySensitive(const occ::handle& theSel, const gp_Trsf& theTrsf, const occ::handle& theView, const bool theToClearOthers = true); //! Dumps the content of me into the stream Standard_EXPORT void DumpJson(Standard_OStream& theOStream, int theDepth = -1) const; public: //! Enables/disables building BVH for sensitives in separate threads Standard_EXPORT void SetToPrebuildBVH(bool theToPrebuild, int theThreadsNum = -1); //! Queues a sensitive entity to build its BVH Standard_EXPORT void QueueBVHBuild(const occ::handle& theEntity); //! Waits BVH threads finished building Standard_EXPORT void WaitForBVHBuild(); //! Returns TRUE if building BVH for sensitives in separate threads is enabled bool ToPrebuildBVH() const { return myToPrebuildBVH; } protected: //! Traverses BVH containing all added selectable objects and //! finds candidates for further search of overlap Standard_EXPORT void TraverseSensitives(const int theViewId = -1); //! Internal function that checks if there is possible overlap between some entity of selectable //! object theObject and current selecting volume. //! @param[in] theObject the selectable object for traversal. //! @param[in] theMgr the (un)transformed copy of the selecting volume manager representing //! active selection frustum. //! @param theCamera, theProjectionMat, theWorldViewMat[in] the source camera and matrices for //! theMgr given. //! @param[in] theWinSize viewport (window) dimensions for evaluating //! object's transformation persistence. Standard_EXPORT void traverseObject(const occ::handle& theObject, const SelectMgr_SelectingVolumeManager& theMgr, const occ::handle& theCamera, const NCollection_Mat4& theProjectionMat, const NCollection_Mat4& theWorldViewMat, const NCollection_Vec2& theWinSize); //! Internal function that checks if a particular sensitive //! entity theEntity overlaps current selecting volume precisely Standard_EXPORT void checkOverlap(const occ::handle& theEntity, const gp_GTrsf& theInversedTrsf, SelectMgr_SelectingVolumeManager& theMgr); //! Update z-layers order map. Standard_EXPORT void updateZLayers(const occ::handle& theView); private: //! Checks if the entity given requires to scale current selecting frustum bool isToScaleFrustum(const occ::handle& theEntity); //! In case if custom tolerance is set, this method will return sum of entity sensitivity and //! custom tolerance. Otherwise, pure entity sensitivity factor will be returned. int sensitivity(const occ::handle& theEntity) const; void Activate(const occ::handle& theSelection); void Deactivate(const occ::handle& theSelection); //! removes a Selection from the Selector void Remove(const occ::handle& aSelection); //! Internal function that checks if a current selecting frustum needs to be scaled and //! transformed for the entity and performs necessary calculations. void computeFrustum(const occ::handle& theEnt, const SelectMgr_SelectingVolumeManager& theMgrGlobal, const SelectMgr_SelectingVolumeManager& theMgrObject, const gp_GTrsf& theInvTrsf, NCollection_DataMap& theCachedMgrs, SelectMgr_SelectingVolumeManager& theResMgr); private: //! Compute 3d position for detected entity. void updatePoint3d(SelectMgr_SortCriterion& theCriterion, const SelectBasics_PickResult& thePickResult, const occ::handle& theEntity, const gp_GTrsf& theInversedTrsf, const SelectMgr_SelectingVolumeManager& theMgr) const; protected: double myDepthTolerance; SelectMgr_TypeOfDepthTolerance myDepthTolType; bool myToPreferClosest; NCollection_IndexedDataMap, SelectMgr_SortCriterion> mystored; SelectMgr_SelectingVolumeManager mySelectingVolumeMgr; mutable SelectMgr_SelectableObjectSet mySelectableObjects; SelectMgr_ToleranceMap myTolerances; NCollection_DataMap myZLayerOrderMap; occ::handle myEntitySetBuilder; gp_Pnt myCameraEye; gp_Dir myCameraDir; double myCameraScale; bool myToPrebuildBVH; occ::handle myBVHThreadPool; mutable NCollection_Array1 myIndexes; mutable bool myIsSorted; bool myIsLeftChildQueuedFirst; NCollection_DataMap, occ::handle> myMapOfObjectSensitives; NCollection_Sequence> myStructs; //!< list of debug presentations }; #endif