EXTERNLIB
FILES
+NIS_Allocator.cxx
+NIS_Allocator.hxx
NIS_Drawer.cxx
NIS_Drawer.hxx
NIS_DrawList.cxx
--- /dev/null
+// File: NIS_Allocator.cpp
+// Created: 22.10.10 17:35
+// Author: Alexander GRIGORIEV
+// Copyright: Open Cascade 2010
+
+#include <NIS_Allocator.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (NIS_Allocator, NCollection_IncAllocator)
+IMPLEMENT_STANDARD_RTTIEXT (NIS_Allocator, NCollection_IncAllocator)
+
+//=======================================================================
+//function : NIS_Allocator
+//purpose :
+//=======================================================================
+
+NIS_Allocator::NIS_Allocator (const size_t theBlockSize)
+ : NCollection_IncAllocator (theBlockSize),
+ myNAllocated (0),
+ myNFreed (0)
+{}
+
+//=======================================================================
+//function : ResetCounters
+//purpose :
+//=======================================================================
+
+void NIS_Allocator::ResetCounters ()
+{
+ myNAllocated = 0;
+ myNFreed = 0;
+}
+
+//=======================================================================
+//function : Allocate
+//purpose :
+//=======================================================================
+
+void* NIS_Allocator::Allocate (const size_t size)
+{
+ size_t* pResult = reinterpret_cast<size_t*>
+ (NCollection_IncAllocator::Allocate(size + sizeof(size_t)));
+ pResult[0] = size;
+ myNAllocated += size;
+ return &pResult[1];
+}
+
+//=======================================================================
+//function : Free
+//purpose :
+//=======================================================================
+
+void NIS_Allocator::Free (void *anAddress)
+{
+ if (anAddress) {
+ size_t* pAddress = reinterpret_cast<size_t*>(anAddress) - 1;
+ myNFreed += pAddress[0];
+ NCollection_IncAllocator::Free(pAddress);
+ }
+}
--- /dev/null
+// File: NIS_Allocator.h
+// Created: 22.10.10 17:22
+// Author: Alexander GRIGORIEV
+// Copyright: Open Cascade 2010
+
+
+#ifndef NIS_Allocator_HeaderFile
+#define NIS_Allocator_HeaderFile
+
+#include <NCollection_IncAllocator.hxx>
+
+/**
+ * Subclass of Incremental Allocator. It is aware of the total
+ * allocated and released memory. Used in NIS_Interactive context as
+ * private allocator that manages all memory used by interactive objects.
+ */
+
+class NIS_Allocator : public NCollection_IncAllocator
+{
+ public:
+ // ---------- PUBLIC METHODS ----------
+
+
+ /**
+ * Constructor.
+ */
+ Standard_EXPORT NIS_Allocator (const size_t theBlockSize = 24600);
+
+ /**
+ * Query the total number of allocated bytes
+ */
+ inline Standard_Size NAllocated () const
+ {
+ return myNAllocated;
+ }
+
+ /**
+ * Query the total number of released bytes
+ */
+ inline Standard_Size NFreed () const
+ {
+ return myNFreed;
+ }
+
+ /**
+ * Set both counters to zero. Should be called with method Reset of the base
+ * class NCollection_IncAlocator.
+ */
+ Standard_EXPORT void ResetCounters ();
+
+ /**
+ * Allocate memory with given size. Returns NULL on failure
+ */
+ Standard_EXPORT virtual void* Allocate (const size_t size);
+
+ /*
+ * Free a previously allocated memory. Does nothing but count released bytes.
+ */
+ Standard_EXPORT virtual void Free (void *anAddress);
+
+ private:
+ // ---------- PRIVATE FIELDS ----------
+
+ Standard_Size myNAllocated;
+ Standard_Size myNFreed;
+
+ public:
+// Declaration of CASCADE RTTI
+DEFINE_STANDARD_RTTI (NIS_Allocator)
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NIS_Allocator, NCollection_IncAllocator)
+
+
+#endif
// Copyright: Open Cascade 2007
#include <NIS_Drawer.hxx>
+#include <NIS_View.hxx>
#ifdef WNT
#include <windows.h>
//=======================================================================
NIS_DrawList::NIS_DrawList ()
- : myListID (0)
{
+#ifdef ARRAY_LISTS
+ myListID = 0;
+#else
+ myListID[0] = 0;
+ myListID[1] = 0;
+ myListID[2] = 0;
+ myListID[3] = 0;
+ myListID[4] = 0;
+#endif
myIsUpdated[0] = Standard_True;
myIsUpdated[1] = Standard_True;
myIsUpdated[2] = Standard_True;
myIsUpdated[3] = Standard_True;
+ myIsUpdated[4] = Standard_True;
}
//=======================================================================
//=======================================================================
NIS_DrawList::NIS_DrawList (const Handle_NIS_View& theView)
- : myView (theView),
- myListID (0)
+ : myView (theView)
{
+#ifdef ARRAY_LISTS
+ myListID = 0;
+#else
+ myListID[0] = 0;
+ myListID[1] = 0;
+ myListID[2] = 0;
+ myListID[3] = 0;
+ myListID[4] = 0;
+#endif
myIsUpdated[0] = Standard_True;
myIsUpdated[1] = Standard_True;
myIsUpdated[2] = Standard_True;
myIsUpdated[3] = Standard_True;
+ myIsUpdated[4] = Standard_True;
}
//=======================================================================
NIS_DrawList::~NIS_DrawList ()
{
- if (myListID != 0)
- glDeleteLists (myListID, 4);
+ //if (myListID != 0)
+ //glDeleteLists (myListID, 5);
+}
+
+//=======================================================================
+//function : ClearListID
+//purpose : Set myListID to 0.
+//=======================================================================
+
+void NIS_DrawList::ClearListID (const Standard_Integer theType)
+{
+#ifndef ARRAY_LISTS
+ if (theType >= 0) {
+ // To be called only in Callback context (i.e. when GL context is active)
+ if (myListID[theType] > 0) {
+ glDeleteLists(myListID[theType], 1);
+ myListID[theType] = 0;
+ }
+ myIsUpdated[theType] = Standard_False;
+ }
+#endif
+}
+
+//=======================================================================
+//function : ClearListID
+//purpose : Set myListID to 0.
+//=======================================================================
+
+void NIS_DrawList::ClearListID (const Handle_NIS_View& theView)
+{
+#ifdef ARRAY_LISTS
+ if (myListID > 0)
+ myView->GetExListId().Add(myListID);
+ myListID = 0;
+#else
+ NIS_View * pView = (myView.IsNull()) ?
+ theView.operator->() : myView.operator->();
+ if (pView) {
+ if (myListID[0] > 0)
+ pView->GetExListId().Add(myListID[0]);
+ myListID[0] = 0;
+ if (myListID[1] > 0)
+ pView->GetExListId().Add(myListID[1]);
+ myListID[1] = 0;
+ if (myListID[2] > 0)
+ pView->GetExListId().Add(myListID[2]);
+ myListID[2] = 0;
+ if (myListID[3] > 0)
+ pView->GetExListId().Add(myListID[3]);
+ myListID[3] = 0;
+ if (myListID[4] > 0)
+ pView->GetExListId().Add(myListID[4]);
+ myListID[4] = 0;
+ }
+
+#endif
+ myIsUpdated[0] = Standard_False;
+ myIsUpdated[1] = Standard_False;
+ myIsUpdated[2] = Standard_False;
+ myIsUpdated[3] = Standard_False;
+ myIsUpdated[4] = Standard_False;
}
//=======================================================================
void NIS_DrawList::BeginPrepare (const Standard_Integer theType)
{
+#ifdef ARRAY_LISTS
if (myListID == 0)
- myListID = glGenLists(4);
- glNewList (GetListID (theType), GL_COMPILE);
+ myListID = glGenLists(5);
+#else
+ if (GetListID(theType) == 0)
+ myListID[theType] = glGenLists(1);
+#endif
+ glNewList (GetListID(theType), GL_COMPILE);
}
//=======================================================================
void NIS_DrawList::EndPrepare (const Standard_Integer theType)
{
glEndList ();
- myIsUpdated[theType&0x3] = Standard_False;
+ myIsUpdated[theType] = Standard_False;
}
//=======================================================================
void NIS_DrawList::SetUpdated (const Standard_Integer theType,
const Standard_Boolean theFlag)
{
- if ( theFlag )
- SetUpdated( theType );
+ if (theFlag)
+ SetUpdated(theType);
else
- myIsUpdated [theType&0x3] = Standard_False;
+ myIsUpdated [theType] = Standard_False;
}
+//=======================================================================
+//function : SetUpdated
+//purpose :
+//=======================================================================
+
+void NIS_DrawList::SetUpdated (const Standard_Integer theType)
+{
+ myIsUpdated [theType] = Standard_True;
+ if (theType == NIS_Drawer::Draw_Hilighted)
+ myDynHilighted.Clear();
+}
#include <NCollection_List.hxx>
class NIS_InteractiveContext;
+/**
+ * This macro defines that OpenGL draw lists will be allocated as array of 5
+ * integers and any of them would not be deleted unless all interactive objects
+ * in the given drawer are removed.
+ * When the macro is undefined every draw list is created when needed and it is
+ * destroyed when there is no objects to show in this draw list.
+ */
+//#define ARRAY_LISTS
/**
- * Block of comments describing class NIS_DrawList
+ * Implementation of a set of OpenGL draw lists for a given NIS_Drawer and
+ * given NIS_View. Stored in NIS_Drawer instances.
*/
class NIS_DrawList
* @param theType
* Integer value coinciding with the enumerated NIS_Drawer:DrawType.
*/
- inline Standard_Integer GetListID (const Standard_Integer theType)
- { return myListID + (theType&0x3); }
+ inline Standard_Integer GetListID (const Standard_Integer theType) const
+#ifdef ARRAY_LISTS
+ { return myListID + theType; }
+#else
+ { return myListID[theType]; }
+#endif
+
+ /**
+ * Set myListID to 0.
+ * @return
+ * Previous value of myListID
+ */
+ Standard_EXPORT void ClearListID (const Standard_Integer theType);
+
+ /**
+ * Set myListID to 0.
+ * @return
+ * Previous value of myListID
+ */
+ Standard_EXPORT void ClearListID (const Handle_NIS_View& theView=NULL);
/**
* This method is called to start recording a new list. It must be eventually
* @param theType
* Integer value coinciding with the enumerated NIS_Drawer::DrawType.
*/
- inline Standard_Boolean IsUpdated (const Standard_Integer theType)
- { return myIsUpdated [theType&0x3]; }
+ inline Standard_Boolean IsUpdated (const Standard_Integer theType) const
+ { return myIsUpdated [theType]; }
/**
* Set the flag indicating that the List should be updated (rebuilt).
*/
- inline void SetUpdated (const Standard_Integer theType)
- { myIsUpdated [theType&0x3] = Standard_True; }
+ Standard_EXPORT void SetUpdated (const Standard_Integer theType);
/**
* Query if the given list should be processed by Dynamic Hilighting.
Standard_EXPORT void SetUpdated (const Standard_Integer,
const Standard_Boolean);
+#ifdef ARRAY_LISTS
inline void SetListID (const Standard_Integer theID)
{ myListID = theID; }
-
-
+#endif
private:
// ---------- PRIVATE METHODS (PROHIBITED) ----------
// ---------- PRIVATE FIELDS ----------
Handle_NIS_View myView;
+#ifdef ARRAY_LISTS
Standard_Integer myListID;
- Standard_Boolean myIsUpdated[4];
+#else
+ Standard_Integer myListID[5];
+#endif
+ Standard_Boolean myIsUpdated[5];
NCollection_List<Handle_NIS_InteractiveObject> myDynHilighted;
};
// Copyright: Open Cascade 2007
#include <NIS_Drawer.hxx>
+#include <NIS_View.hxx>
#include <NIS_InteractiveContext.hxx>
#include <NIS_InteractiveObject.hxx>
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
{
if (theOther->IsKind(DynamicType()) == Standard_False)
Standard_TypeMismatch::Raise ("NIS_Drawer::Assign");
+ myIniId = theOther->myIniId;
+ myObjPerDrawer = theOther->myObjPerDrawer;
+ myTransparency = theOther->myTransparency;
}
//=======================================================================
Standard_Integer NIS_Drawer::HashCode(const Standard_Integer theN) const
{
- return ::HashCode (DynamicType(), theN);
+ Standard_Integer aKey = ::HashCode (DynamicType(), theN);
+ aKey += (myIniId / myObjPerDrawer);
+ return ((aKey & 0x7fffffff) % theN) + 1;
}
//=======================================================================
Standard_Boolean aResult (Standard_False);
if (theOther.IsNull() == Standard_False)
if (DynamicType() == theOther->DynamicType())
- aResult = (myMapID.Extent() < 2048);
+ if (theOther->myIniId/theOther->myObjPerDrawer == myIniId/myObjPerDrawer)
+ aResult = Standard_True;
+
+ if (aResult)
+ if (fabs(myTransparency - theOther->myTransparency) > 0.01)
+ aResult = Standard_False;
+
return aResult;
}
{
}
+//=======================================================================
+//function : UpdateExListId
+//purpose :
+//=======================================================================
+
+void NIS_Drawer::UpdateExListId (const Handle_NIS_View& theView) const
+{
+ if (theView.IsNull()) {
+ if (myCtx) {
+ if (myCtx->myViews.IsEmpty() == Standard_False) {
+ const Handle(NIS_View)& aView = myCtx->myViews.First();
+ NCollection_List<NIS_DrawList *>::Iterator anIterL(myLists);
+ for (; anIterL.More(); anIterL.Next()) {
+ NIS_DrawList * const pList = anIterL.Value();
+ pList->ClearListID(aView);
+ }
+ }
+ }
+ } else {
+ NCollection_List<NIS_DrawList *>::Iterator anIterL(myLists);
+ for (; anIterL.More(); anIterL.Next()) {
+ NIS_DrawList * const pList = anIterL.Value();
+ if (pList->GetView() == theView) {
+ pList->ClearListID(theView);
+ break;
+ }
+ }
+ }
+}
+
//=======================================================================
//function : redraw
//purpose :
NCollection_List<NIS_DrawList*>::Iterator anIter (myLists);
for (; anIter.More(); anIter.Next()) {
NIS_DrawList& aDrawList = * anIter.ChangeValue();
- if (aDrawList.GetView() == theView) {
+ const Handle_NIS_View& aView = aDrawList.GetView();
+ if (aView == theView || aView.IsNull()) {
if (aDrawList.IsUpdated(theType)) {
+ // Get the IDs of objects concerned
+ TColStd_PackedMapOfInteger mapObj;
+ mapObj.Intersection (myCtx->myMapObjects[theType], myMapID);
+#ifndef ARRAY_LISTS
+ // Release the list that is no more in use
+ if (mapObj.IsEmpty() && theType != Draw_DynHilighted) {
+ aDrawList.ClearListID(theType);
+ break;
+ }
+#endif
aDrawList.BeginPrepare(theType);
- prepareList (theType, aDrawList);
+ prepareList (theType, aDrawList, mapObj);
aDrawList.EndPrepare(theType);
}
- aDrawList.Call(theType);
+ if (aDrawList.GetListID(theType) > 0)
+ aDrawList.Call(theType);
break;
}
}
const_cast<Bnd_B3f&>(myBox).Clear();
}
+//=======================================================================
+//function : SetUpdated
+//purpose :
+//=======================================================================
+
+
+void NIS_Drawer::SetUpdated (const DrawType theType1,
+ const DrawType theType2,
+ const DrawType theType3,
+ const DrawType theType4) const
+{
+ NCollection_List<NIS_DrawList*>::Iterator anIter (myLists);
+ for (; anIter.More(); anIter.Next()) {
+ NIS_DrawList& aDrawList = * anIter.ChangeValue();
+ aDrawList.SetUpdated (theType1);
+ aDrawList.SetUpdated (theType2);
+ aDrawList.SetUpdated (theType3);
+ aDrawList.SetUpdated (theType4);
+ }
+ const_cast<Bnd_B3f&>(myBox).Clear();
+}
+
//=======================================================================
//function : SetDynamicHilighted
//purpose :
} else
for (; anIter.More(); anIter.Next()) {
NIS_DrawList& aDrawList = * anIter.ChangeValue();
- if (aDrawList.GetView() == theView) {
+ const Handle(NIS_View)& aView = aDrawList.GetView();
+ if (aView == theView || aView.IsNull()) {
aDrawList.SetDynHilighted (isHilighted, theObj);
theObj->myIsDynHilighted = isHilighted;
aDrawList.SetUpdated (Draw_DynHilighted);
//=======================================================================
void NIS_Drawer::removeObject (const NIS_InteractiveObject * theObj,
- const Standard_Boolean isUpdateViews)
+ const Standard_Boolean isUpdateViews)
{
const Standard_Integer anID = theObj->ID();
myMapID.Remove (anID);
// Stop dynamic hilighting if it has been activated
if (theObj->IsDynHilighted())
SetDynamicHilighted (Standard_False, theObj);
+ if (myMapID.IsEmpty()) {
+ UpdateExListId(NULL);
+ }
// Set Updated for the draw type.
- if (theObj->IsHidden() == Standard_False && isUpdateViews)
+ else if (theObj->IsHidden() == Standard_False && isUpdateViews)
SetUpdated (theObj->DrawType());
}
//=======================================================================
void NIS_Drawer::addObject (const NIS_InteractiveObject * theObj,
+ const Standard_Boolean isShareList,
const Standard_Boolean isUpdateViews)
{
myMapID.Add (theObj->ID());
// Fill the drawer (if new) with DrawList instances for available Views.
if ( myLists.IsEmpty())
{
- NCollection_List<Handle_NIS_View>::Iterator anIter (GetContext()->myViews);
- for (; anIter.More(); anIter.Next())
- myLists.Append (createDefaultList(anIter.Value()));
+ if (isShareList)
+ myLists.Append (createDefaultList(NULL));
+ else {
+ NCollection_List<Handle_NIS_View>::Iterator anIter(GetContext()->myViews);
+ for (; anIter.More(); anIter.Next())
+ myLists.Append (createDefaultList(anIter.Value()));
+ }
}
if (theObj->IsHidden() == Standard_False && isUpdateViews)
NCollection_List<NIS_DrawList*>::Iterator anIterL (myLists);
for (; anIterL.More(); anIterL.Next()) {
NIS_DrawList& aDrawList = * anIterL.ChangeValue();
- if (aDrawList.GetView().operator->() == pView)
+ const Handle(NIS_View)& aView = aDrawList.GetView();
+ if (aView.IsNull() || aView.operator->() == pView)
break;
}
if (anIterL.More())
//function : prepareList
//purpose :
//=======================================================================
-void NIS_Drawer::prepareList( const NIS_Drawer::DrawType theType,
- const NIS_DrawList& theDrawList )
+void NIS_Drawer::prepareList(const NIS_Drawer::DrawType theType,
+ const NIS_DrawList& theDrawList,
+ const TColStd_PackedMapOfInteger& mapObj)
{
if (!myCtx)
return;
if (theType == NIS_Drawer::Draw_DynHilighted) {
NCollection_List<Handle_NIS_InteractiveObject>::Iterator
anIter (theDrawList.DynHilightedList());
- for (; anIter.More(); anIter.Next())
- {
+ if (anIter.More()) {
BeforeDraw (theType, theDrawList);
- Draw (anIter.Value(), NIS_Drawer::Draw_DynHilighted, theDrawList);
+ for (; anIter.More(); anIter.Next())
+ Draw (anIter.Value(), NIS_Drawer::Draw_DynHilighted, theDrawList);
AfterDraw (theType, theDrawList);
}
} else {
// The common part of two maps (objects for this draw type & objects in
// the current Drawer) is used for updating the presentation.
- TColStd_PackedMapOfInteger mapObj;
- mapObj.Intersection (myCtx->myMapObjects[theType&0x3], myMapID);
TColStd_MapIteratorOfPackedMapOfInteger anIter (mapObj);
if (anIter.More()) {
BeforeDraw (theType, theDrawList);
NIS_DrawList* NIS_Drawer::createDefaultList
(const Handle_NIS_View& theView) const
{
- return new NIS_DrawList( theView );
+ return new NIS_DrawList(theView);
}
template <class A> class NCollection_Vector;
/**
- * Abstract Drawer type
+ * Abstract Drawer type.
+ * Drawer provides the immediate OpenGL drawing for every NIS_InteractiveObject
+ * maneged by the given Drawer instance. Each Drawer instance has reciprocal
+ * link with a number of NIS_InteractiveObject instances of the same
+ * (corresponding to Drawer) type. The idea is to group the drawing for all
+ * referred interactive objects using the same pre- and post-treatment like
+ * color setting, matrix, polygon offset, line thickness and what not.
+ *
+ * @section nis_drawer_visualprop Visual properties of Drawer
+ * Normally visual properties of any NIS_InteractiveObject are stored in its
+ * Drawer instance, but not in an object. For example, if an interactive object
+ * has method SetColor() then the color is stored in the corresponding Drawer
+ * rather than in the interactive object itself. This scheme avoid useless
+ * duplication when a lot of objects have similar properties like color. Please
+ * see @see nis_interactiveobject_drawer to learn how this mechanism
+ * works from the side of NIS_InteractiveObject.
+ *
+ * @section nis_drawer_drawing Drawing
+ * There are 3 virtual methods to implement OpenGL drawing in this API. They
+ * define the drawing cycle that consists of filling the internal OpenGL draw
+ * list with commands. This drawing cycle is triggered when the corresponding
+ * internal instance of NIS_DrawList has 'IsUpdated' flag (you can set this
+ * flag by means of public methods NIS_Drawer::SetUpdated()).
+ * <ul>
+ * <li><b>BeforeDraw()</b> : contains all OpenGL commands that define the
+ * common set of visual properties for all managed interactive objects.
+ * This method is called once in the beginning of drawing cycle for the
+ * Drawer instance</li>
+ * <li><b>Draw()</b> : all OpenGL commands that are specific to a given
+ * interactive object, usually definition of vertices, triangles, lines,
+ * or their arrays.</li>
+ * <li><b>AfterDraw()</b> : commands that revert the status of OpenGL context
+ * to the state before execution of BeforeDraw(). This method is called
+ * once in the end of drawing cycle.</li>
+ * </ul>
+ * Each of these methods receives NIS_DrawList and DrawType, both identify the
+ * OpenGL draw list that should be filled with commands. Based on DrawType
+ * you will be able to define different presentation - the most important case
+ * is how hilighted (selected) interactive object is presented.
+ * <p>
+ * For advanced purposes you also can redefine the virtual method redraw(), it
+ * is dedicated to higher-level management of draw lists and ordering of
+ * their update when necessary.
+ *
+ * @section nis_drawer_distinction Distinction of Drawer instances
+ * Every Drawer should define which interactive objects it may manage and
+ * which - may not. The same idea could be shaped alternatively: every
+ * interactive object should understand to what Drawer it can attach itself.
+ * This question is answerd by special virtual method IsEqual() that compares
+ * two Drawers of the same type. <b>Two instances of Drawer are equal if they
+ * have the same set of visual properties that are implemented in BeforeDraw().
+ * </b> The method IsEqual() is the core of Drawer architecture and it must
+ * be implemented very carefully for any new type. Particularly, for any
+ * derived class the method IsEqual() should first call the same method of
+ * its superclass.
+ * <p>
+ * For the optimal efficiency of OpenGL drawing it is better to keep the size
+ * of draw list (i.e., the number of interactive objects in a Drawer instance)
+ * not too small and not too big. The latter limitation is entered by the
+ * protected field myObjPerDrawer. It is used in method IsEqual() of the base
+ * Drawer class: two Drawers are not equal if they are initialized on objects
+ * that have too different IDs -- even if all visual properties of these two
+ * Drawer instances coincide.
+ * <p>
+ * @section nis_drawer_cloning Cloning Drawer instances
+ * It is possible to clone a Drawer instance with the viryual method Assign().
+ * This method copies all visual properties and other important data from the
+ * Drawer provided as parameter. Method Clone() also should be very carefully
+ * implemented for any new Drawer type, to make sure that all necessary data
+ * fields and structures are properly copied.
*/
class NIS_Drawer : public Standard_Transient
{
public:
-#if (_MSC_VER < 1400)
- enum DrawType {
+#if defined(WNT) && (_MSC_VER >= 1400)
+ enum DrawType : unsigned int {
#else
- enum DrawType : unsigned int {
+ enum DrawType {
#endif
Draw_Normal = 0,
- Draw_Transparent = 1,
- Draw_Hilighted = 2,
- Draw_DynHilighted = 3
+ Draw_Top = 1,
+ Draw_Transparent = 2,
+ Draw_Hilighted = 3,
+ Draw_DynHilighted = 4
};
public:
/**
* Empty constructor.
*/
- inline NIS_Drawer () : myCtx (0L) {}
+ inline NIS_Drawer ()
+ : myTransparency (0.f),
+ myIniId (0),
+ myObjPerDrawer (1024),
+ myCtx (0L)
+ {}
/**
* Destructor.
const DrawType theType2,
const DrawType theType3) const;
+ Standard_EXPORT void SetUpdated (const DrawType theType1,
+ const DrawType theType2,
+ const DrawType theType3,
+ const DrawType theType4) const;
+
/**
* Switch on/off the dynamic hilight of the given object in the
* given view.
ObjectIterator () const
{ return TColStd_MapIteratorOfPackedMapOfInteger (myMapID); }
+ /**
+ * Query associated draw lists.
+ */
+ inline NCollection_List<NIS_DrawList *>
+ GetLists() const
+ { return myLists; }
+
protected:
+ /**
+ * Called to add draw list IDs to ex-list Ids of view. These draw lists are
+ * eventually released in the callback function, before anything is displayed
+ */
+ Standard_EXPORT void UpdateExListId (const Handle_NIS_View& theView) const;
+
// ---------- PROTECTED METHODS ----------
/**
const Handle_NIS_View& theView);
Standard_EXPORT void addObject (const NIS_InteractiveObject * theObj,
- const Standard_Boolean isUpVws);
+ const Standard_Boolean isShareList,
+ const Standard_Boolean isUpVws);
Standard_EXPORT void removeObject (const NIS_InteractiveObject * theObj,
const Standard_Boolean isUpVws);
Standard_EXPORT virtual NIS_DrawList*
createDefaultList (const Handle_NIS_View&) const;
+ protected:
+ //! Get the number of interactive objects in this drawer
+ inline Standard_Integer NObjects() const
+ { return myMapID.Extent(); }
+
private:
// ---------- PRIVATE (PROHIBITED) METHODS ----------
NIS_Drawer& operator = (const NIS_Drawer& theOther);
// ---------- PRIVATE METHODS ----------
- void prepareList (const NIS_Drawer::DrawType theType,
- const NIS_DrawList& theDrawLst);
+ void prepareList (const NIS_Drawer::DrawType theType,
+ const NIS_DrawList& theDrawLst,
+ const TColStd_PackedMapOfInteger& mapObj);
protected:
// ---------- PROTECTED FIELDS ----------
NCollection_List<NIS_DrawList*> myLists;
+ Standard_ShortReal myTransparency;
+ //! ID of the initializing InteractiveObject. It is never changed, can be
+ //! used to compute hash code of the Drawer instance.
+ Standard_Integer myIniId;
+ //! Maximal range of IDs of objects in one drawer. Limits the size of
+ //! draw lists. Can be initialized only in constructor (default 1024). It is
+ //! strictly prohibited to change this value outside the constructor.
+ Standard_Integer myObjPerDrawer;
private:
// ---------- PRIVATE FIELDS ----------
friend class NIS_InteractiveContext;
friend class NIS_InteractiveObject;
+ friend class NIS_View;
public:
// Declaration of CASCADE RTTI
#include <NIS_View.hxx>
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
#include <Standard_NoSuchObject.hxx>
+#include <Bnd_B2f.hxx>
IMPLEMENT_STANDARD_HANDLE (NIS_InteractiveContext, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT (NIS_InteractiveContext, Standard_Transient)
-static void deselectObj (const Handle(NIS_InteractiveObject)&,
- const Standard_Integer,
- TColStd_PackedMapOfInteger *);
-static void selectObj (const Handle(NIS_InteractiveObject)&,
- const Standard_Integer,
- TColStd_PackedMapOfInteger *);
+static void markAllDrawersUpdated (const NCollection_Map<Handle_NIS_Drawer>&);
//=======================================================================
//function : NIS_InteractiveContext()
//=======================================================================
NIS_InteractiveContext::NIS_InteractiveContext ()
- : mySelectionMode (Mode_NoSelection),
- myAllocator (new NCollection_IncAllocator)
+ : myAllocator (new NIS_Allocator(1024*100)),
+// myDrawers (101, myAllocator),
+ mySelectionMode (Mode_NoSelection),
+ myIsShareDrawList (Standard_True)
{
// ID == 0 is invalid so we reserve this item from subsequent allocation.
myObjects.Append (NULL);
//=======================================================================
void NIS_InteractiveContext::Display
- (const Handle_NIS_InteractiveObject& theObj,
- const Handle_NIS_Drawer& theDrawer,
- const Standard_Boolean isUpdateViews)
+ (Handle_NIS_InteractiveObject& theObj,
+ const Handle_NIS_Drawer& theDrawer,
+ const Standard_Boolean isUpdateViews)
{
if (theObj.IsNull())
return;
- Standard_Integer anID = theObj->ID();
- Handle(NIS_Drawer) aDrawer = theDrawer;
- if (aDrawer.IsNull() == Standard_False) {
- if (aDrawer->myCtx != this)
- Standard_NoSuchObject::Raise ("NIS_InteractiveContext::Display (0)");
- } else {
- aDrawer = theObj->GetDrawer();
- if (aDrawer.IsNull()) {
- aDrawer = theObj->DefaultDrawer();
- aDrawer->myCtx = this;
- }
- }
- if (anID == 0) {
- // Create a new ID for this object
- theObj->myID = myObjects.Length();
- myObjects.Append (theObj);
- myMapObjects[NIS_Drawer::Draw_Normal].Add(theObj->myID);
- }
- aDrawer = theObj->SetDrawer (aDrawer);
+ objectForDisplay(theObj, theObj->DrawType());
+ const Handle(NIS_Drawer)& aDrawer = drawerForDisplay(theObj, theDrawer);
+ // Display Object as Normal or Transparent if it has been hidden
+ if (theObj->IsHidden())
+ theObj->myIsHidden = Standard_False;
- // Display Object as Normal or Transparent if it has been hidden
+ // Set Update flag in the Drawer
+ if (isUpdateViews)
+ aDrawer->SetUpdated (theObj->DrawType());
+}
+
+//=======================================================================
+//function : DisplayOnTop
+//purpose :
+//=======================================================================
+
+void NIS_InteractiveContext::DisplayOnTop
+ (Handle_NIS_InteractiveObject& theObj,
+ const Handle_NIS_Drawer& theDrawer,
+ const Standard_Boolean isUpdateViews)
+{
+ if (theObj.IsNull())
+ return;
+
+ objectForDisplay(theObj, NIS_Drawer::Draw_Top);
+ const Handle(NIS_Drawer)& aDrawer = drawerForDisplay(theObj, theDrawer);
+
+ // Display Object as Normal or Transparent if it has been hidden
if (theObj->IsHidden())
theObj->myIsHidden = Standard_False;
-// if (theObj->IsTransparent()) {
-// myMapObjects[NIS_Drawer::Draw_Transparent].Add(anID);
-// theObj->myDrawType = NIS_Drawer::Draw_Transparent;
-// } else {
-// myMapObjects[NIS_Drawer::Draw_Normal].Add(anID);
-// theObj->myDrawType = NIS_Drawer::Draw_Normal;
-// }
// Set Update flag in the Drawer
if (isUpdateViews)
{
if (theObj.IsNull() == Standard_False) {
const Handle(NIS_Drawer)& aDrawer = theObj->GetDrawer();
+ if ( aDrawer.IsNull() )
+ return;
if (aDrawer->myCtx == this) {
// Remove the hilighting if the object has been hilighted
if (theObj->IsDynHilighted()) {
if (anIterV.Value().IsNull() == Standard_False)
anIterV.Value()->DynamicUnhilight (theObj);
}
- // Remove the obejct from the context
+ // Remove the object from the context
const Standard_Integer anID = theObj->ID();
const NIS_Drawer::DrawType aDrawType (theObj->DrawType());
- if (myMapObjects[Standard_Integer(aDrawType)&0x3].Remove(anID))
+ if (myMapObjects[Standard_Integer(aDrawType)].Remove(anID))
aDrawer->removeObject(theObj.operator->(), isUpdateViews);
theObj->myID = 0;
theObj->myDrawer.Nullify();
//purpose :
//=======================================================================
-void NIS_InteractiveContext::DisplayAll (const Standard_Boolean isUpdateViews)
+void NIS_InteractiveContext::DisplayAll ()
{
// UnHide all objects in the Context
NCollection_Vector <Handle_NIS_InteractiveObject>::Iterator anIter(myObjects);
}
// Update status of objects in Drawers (particularly cancel dyn. hilighting)
- if (isUpdateViews) {
- NCollection_Map<Handle_NIS_Drawer>::Iterator anIterD (myDrawers);
- for (; anIterD.More(); anIterD.Next()) {
- const Handle(NIS_Drawer)& aDrawer = anIterD.Value();
- if (aDrawer.IsNull() == Standard_False) {
- aDrawer->SetUpdated (NIS_Drawer::Draw_Normal,
- NIS_Drawer::Draw_Transparent,
- NIS_Drawer::Draw_Hilighted);
- }
+ NCollection_Map<Handle_NIS_Drawer>::Iterator anIterD (myDrawers);
+ for (; anIterD.More(); anIterD.Next()) {
+ const Handle(NIS_Drawer)& aDrawer = anIterD.Value();
+ if (aDrawer.IsNull() == Standard_False) {
+ aDrawer->SetUpdated (NIS_Drawer::Draw_Normal,
+ NIS_Drawer::Draw_Top,
+ NIS_Drawer::Draw_Transparent,
+ NIS_Drawer::Draw_Hilighted);
}
}
}
//purpose :
//=======================================================================
-void NIS_InteractiveContext::EraseAll (const Standard_Boolean isUpdateViews)
+void NIS_InteractiveContext::EraseAll ()
{
// Hide all objects in the Context
NCollection_Vector <Handle_NIS_InteractiveObject>::Iterator anIter(myObjects);
for (; anIterD.More(); anIterD.Next()) {
const Handle(NIS_Drawer)& aDrawer = anIterD.Value();
if (aDrawer.IsNull() == Standard_False) {
- if (isUpdateViews)
- aDrawer->SetUpdated (NIS_Drawer::Draw_Normal,
- NIS_Drawer::Draw_Transparent,
- NIS_Drawer::Draw_Hilighted);
+ aDrawer->SetUpdated (NIS_Drawer::Draw_Normal,
+ NIS_Drawer::Draw_Top,
+ NIS_Drawer::Draw_Transparent,
+ NIS_Drawer::Draw_Hilighted);
// if (aList.myDynHilighted.IsEmpty() == Standard_False) {
// aList.myIsUpdated[NIS_Drawer::Draw_DynHilighted]= Standard_True;
// aList.myDynHilighted.Clear();
// }
+
}
}
}
//purpose :
//=======================================================================
-void NIS_InteractiveContext::RemoveAll (const Standard_Boolean isUpdateViews)
+void NIS_InteractiveContext::RemoveAll ()
{
// Remove objects from the Context
NCollection_Vector <Handle_NIS_InteractiveObject>::Iterator anIter(myObjects);
}
}
- // Remove objects from Drawers (particularly cancel dynamic hilighting)
+ // Mark all draw lists to be removed in the view callback
NCollection_Map<Handle_NIS_Drawer>::Iterator anIterD (myDrawers);
for (; anIterD.More(); anIterD.Next()) {
const Handle(NIS_Drawer)& aDrawer = anIterD.Value();
if (aDrawer.IsNull() == Standard_False) {
aDrawer->myMapID.Clear();
- if (isUpdateViews)
- aDrawer->SetUpdated (NIS_Drawer::Draw_Normal,
- NIS_Drawer::Draw_Transparent,
- NIS_Drawer::Draw_Hilighted);
-// if (aList.myDynHilighted.IsEmpty() == Standard_False) {
-// aList.myIsUpdated[NIS_Drawer::Draw_DynHilighted]= Standard_True;
-// aList.myDynHilighted.Clear();
-// }
+ aDrawer->UpdateExListId(NULL);
+ aDrawer->myLists.Clear();
}
}
+ // Remove Drawers
+ myDrawers.Clear();
+
+ // Release memory
+ myAllocator->Reset();
+ myAllocator->ResetCounters();
+
+ myDrawers.Clear();
+
+ // Remove objects from maps
+ myMapObjects[0].Clear();
+ myMapObjects[1].Clear();
+ myMapObjects[2].Clear();
+ myMapObjects[3].Clear();
+ myMapNonSelectableObjects.Clear();
}
//=======================================================================
-//function : UpdateViews
+//function : RebuildViews
//purpose :
//=======================================================================
-void NIS_InteractiveContext::UpdateViews ()
+void NIS_InteractiveContext::RebuildViews ()
{
- NCollection_Map<Handle_NIS_Drawer>::Iterator anIterD (myDrawers);
- for (; anIterD.More(); anIterD.Next()) {
- const Handle(NIS_Drawer)& aDrawer = anIterD.Value();
- if (aDrawer.IsNull() == Standard_False) {
- aDrawer->SetUpdated (NIS_Drawer::Draw_Normal,
- NIS_Drawer::Draw_Transparent,
- NIS_Drawer::Draw_Hilighted);
-// aList.myIsUpdated[NIS_Drawer::Draw_DynHilighted] =
-// (aList.myDynHilighted.IsEmpty() == Standard_False);
- }
+ const Handle_NIS_Allocator aNewAlloc = compactObjects();
+
+ // Recalculate all DrawLists in all drawers
+ markAllDrawersUpdated(myDrawers);
+
+ // It is time to destroy the old allocator, not before this line. Because
+ // the old allocator is needed to tidy up draw lists in SetUpdated() calls.
+ if (aNewAlloc.IsNull() == Standard_False)
+ myAllocator = aNewAlloc;
+
+ NCollection_List<Handle_NIS_View>::Iterator anIterV(myViews);
+ for (; anIterV.More(); anIterV.Next()) {
+ const Handle(NIS_View)& aView = anIterV.Value();
+ if (aView.IsNull() == Standard_False)
+ aView->Redraw();
}
- NCollection_List<Handle_NIS_View>::Iterator anIterV (myViews);
+}
+
+//=======================================================================
+//function : UpdateViews
+//purpose : Only repaint the views refreshing their presentations only for
+// those drawers that have been marked as updated.
+//=======================================================================
+
+void NIS_InteractiveContext::UpdateViews ()
+{
+ const Handle_NIS_Allocator aNewAlloc = compactObjects();
+ if (aNewAlloc.IsNull() == Standard_False)
+ myAllocator = aNewAlloc;
+
+ NCollection_List<Handle_NIS_View>::Iterator anIterV(myViews);
for (; anIterV.More(); anIterV.Next()) {
const Handle(NIS_View)& aView = anIterV.Value();
if (aView.IsNull() == Standard_False)
const Standard_Integer anID = theObj->ID();
if (isSelected == Standard_False) {
if (myMapObjects[NIS_Drawer::Draw_Hilighted].Remove(anID)) {
- deselectObj (theObj, anID, &myMapObjects[0]);
+ deselectObj (theObj, anID);
aResult = Standard_True;
}
} else {
if (IsSelectable(anID) == Standard_True) {
if (myMapObjects[NIS_Drawer::Draw_Hilighted].Add(anID)) {
- selectObj (theObj, anID, &myMapObjects[0]);
+ selectObj (theObj, anID);
aResult = Standard_True;
}
}
Standard_Integer anID (0);
Standard_Boolean wasSelected (Standard_False);
if (theObj.IsNull() == Standard_False) {
- anID = theObj->ID();
- wasSelected = myMapObjects[NIS_Drawer::Draw_Hilighted].Contains (anID);
+ const Handle(NIS_Drawer)& aDrawer = theObj->GetDrawer();
+ if (aDrawer.IsNull() == Standard_False) {
+ if (aDrawer->GetContext() == this) {
+ anID = theObj->ID();
+ wasSelected = myMapObjects[NIS_Drawer::Draw_Hilighted].Contains (anID);
+ }
+ }
}
switch (mySelectionMode) {
aResult = Standard_True;
} else if (wasSelected && mySelectionMode == Mode_Normal) {
myMapObjects[NIS_Drawer::Draw_Hilighted].Remove( anID );
- deselectObj (theObj, anID, &myMapObjects[0]);
+ deselectObj (theObj, anID);
aResult = Standard_True;
break;
}
if (wasSelected == Standard_False && IsSelectable(anID) == Standard_True) {
myMapObjects[NIS_Drawer::Draw_Hilighted].Add( anID );
- selectObj (theObj, anID, &myMapObjects[0]);
+ selectObj (theObj, anID);
aResult = Standard_True;
}
break;
case Mode_Exclusive:
if (wasSelected) {
myMapObjects[NIS_Drawer::Draw_Hilighted].Remove( anID );
- deselectObj (theObj, anID, &myMapObjects[0]);
+ deselectObj (theObj, anID);
aResult = Standard_True;
}
break;
myMapObjects[NIS_Drawer::Draw_Hilighted] = aMap;
for (anIter.Initialize (aMap); anIter.More(); anIter.Next()) {
const Standard_Integer anID = anIter.Key();
- selectObj (myObjects(anID), anID, &myMapObjects[0]);
+ selectObj (myObjects(anID), anID);
}
} else {
TColStd_PackedMapOfInteger aMapSub;
myMapObjects[NIS_Drawer::Draw_Hilighted].Subtract (aMapSub);
for (anIter.Initialize (aMap); anIter.More(); anIter.Next()) {
const Standard_Integer anID = anIter.Key();
- selectObj (myObjects(anID), anID, &myMapObjects[0]);
+ selectObj (myObjects(anID), anID);
}
for (anIter.Initialize (aMapSub); anIter.More(); anIter.Next()) {
const Standard_Integer anID = anIter.Key();
- deselectObj (myObjects(anID), anID, &myMapObjects[0]);
+ deselectObj (myObjects(anID), anID);
}
}
break;
myMapObjects[NIS_Drawer::Draw_Hilighted].Unite (aMap);
for (anIter.Initialize (aMap); anIter.More(); anIter.Next()) {
const Standard_Integer anID = anIter.Key();
- selectObj (myObjects(anID), anID, &myMapObjects[0]);
+ selectObj (myObjects(anID), anID);
}
break;
case Mode_Exclusive:
myMapObjects[NIS_Drawer::Draw_Hilighted].Subtract (aMap);
for (anIter.Initialize (aMap); anIter.More(); anIter.Next()) {
const Standard_Integer anID = anIter.Key();
- deselectObj (myObjects(anID), anID, &myMapObjects[0]);
+ deselectObj (myObjects(anID), anID);
}
break;
default: ;
(myMapObjects[NIS_Drawer::Draw_Hilighted]);
for (; anIter.More(); anIter.Next()) {
const Standard_Integer anID = anIter.Key();
- deselectObj (myObjects(anID), anID, &myMapObjects[0]);
+ deselectObj (myObjects(anID), anID);
}
myMapObjects[NIS_Drawer::Draw_Hilighted].Clear();
}
aMapSub.Subtraction (myMapObjects[NIS_Drawer::Draw_Hilighted], aMap);
for (anIter.Initialize(aMapSub); anIter.More(); anIter.Next()) {
const Standard_Integer anID = anIter.Key();
- deselectObj (myObjects(anID), anID, &myMapObjects[0]);
+ deselectObj (myObjects(anID), anID);
}
myMapObjects[NIS_Drawer::Draw_Hilighted].Subtract(aMapSub);
}
// Select objects
for (anIter.Initialize (aMap); anIter.More(); anIter.Next()) {
const Standard_Integer anID = anIter.Key();
- selectObj (myObjects(anID), anID, &myMapObjects[0]);
+ selectObj (myObjects(anID), anID);
}
}
}
//=======================================================================
Standard_Real NIS_InteractiveContext::selectObject
- (Handle_NIS_InteractiveObject& theSel,
- const gp_Ax1& theAxis,
- const Standard_Real theOver,
- const Standard_Boolean isOnlySel) const
+ (Handle_NIS_InteractiveObject& theSel,
+ NCollection_List<DetectedEnt>& theDetected,
+ const gp_Ax1& theAxis,
+ const Standard_Real theOver,
+ const Standard_Boolean isOnlySel) const
{
- Standard_Real aResult (0.5 * RealLast());
+ static const Standard_Real anInfiniteDist = 0.5 * RealLast();
+ Standard_Real aMinDist(anInfiniteDist);
if (mySelectionMode != Mode_NoSelection || isOnlySel == Standard_False)
{
+ DetectedEnt anEnt;
NCollection_Vector <Handle_NIS_InteractiveObject>::Iterator
anIter(myObjects);
for (; anIter.More(); anIter.Next()) {
const Bnd_B3f& aBox = anObj->GetBox();
if (aBox.IsOut (theAxis, Standard_False, theOver) == Standard_False)
{
- const Standard_Real aDist = anObj->Intersect (theAxis, theOver);
- if (aDist < aResult) {
- aResult = aDist;
- theSel = anObj;
+ anEnt.Dist = anObj->Intersect (theAxis, theOver);
+ if (anEnt.Dist < anInfiniteDist) {
+ anEnt.PObj = anObj.operator->();
+ // Insert the detected entity in the sorted list
+ NCollection_List<DetectedEnt>::Iterator anIterD(theDetected);
+ for (; anIterD.More(); anIterD.Next()) {
+ if (anEnt.Dist < anIterD.Value().Dist) {
+ theDetected.InsertBefore(anEnt, anIterD);
+ break;
+ }
+ }
+ if (anIterD.More() == Standard_False)
+ theDetected.Append(anEnt);
+ if (anEnt.Dist < aMinDist) {
+ aMinDist = anEnt.Dist;
+ theSel = anObj;
+ }
}
}
}
}
}
- return aResult;
+ return aMinDist;
}
//=======================================================================
anID = anIter.Key();
if ( myMapObjects[NIS_Drawer::Draw_Hilighted].Contains(anID)) {
myMapObjects[NIS_Drawer::Draw_Hilighted].Remove(anID);
- deselectObj (myObjects(anID), anID, &myMapObjects[0]);
+ deselectObj (myObjects(anID), anID);
}
}
myMapNonSelectableObjects.Unite(objIDs);
return aResult;
}
+//=======================================================================
+//function : selectObjects
+//purpose :
+//=======================================================================
+
+Standard_Boolean NIS_InteractiveContext::selectObjects
+ (TColStd_PackedMapOfInteger &mapObj,
+ const NCollection_List<gp_XY> &thePolygon,
+ const Bnd_B2f &thePolygonBox,
+ const gp_Trsf &theTrfInv,
+ const Standard_Boolean isFullyIn) const
+{
+ Standard_Boolean aResult (Standard_False);
+
+ if (mySelectionMode != Mode_NoSelection) {
+ NCollection_Vector <Handle_NIS_InteractiveObject>::Iterator
+ anIter(myObjects);
+
+ for (; anIter.More(); anIter.Next()) {
+ const Handle(NIS_InteractiveObject)& anObj = anIter.Value();
+
+ if (anObj.IsNull() == Standard_False)
+ if (anObj->IsDisplayed()) {
+ // Pass the object through the SelectFilter if available
+ if (mySelectFilter.IsNull() == Standard_False)
+ if (mySelectFilter->IsOk (anObj.operator->()) == Standard_False)
+ continue;
+
+ // Comvert 3d box to 2d one
+ const Bnd_B3f &aBox = anObj->GetBox();
+ Bnd_B2f aB2d;
+ Standard_Real aX[2];
+ Standard_Real aY[2];
+ Standard_Real aZ[2];
+ gp_XYZ aBoxVtx;
+ Standard_Integer i;
+
+ aBox.CornerMin().Coord(aX[0], aY[0], aZ[0]);
+ aBox.CornerMax().Coord(aX[1], aY[1], aZ[1]);
+
+ for (i = 0; i < 8; i++) {
+ aBoxVtx.SetX(aX[(i & 1) ? 1 : 0]);
+ aBoxVtx.SetY(aY[(i & 2) ? 1 : 0]);
+ aBoxVtx.SetZ(aZ[(i & 4) ? 1 : 0]);
+ theTrfInv.Transforms(aBoxVtx);
+ aB2d.Add(gp_XY(aBoxVtx.X(), aBoxVtx.Y()));
+ }
+
+ // Check the intersection with the box
+ if (thePolygonBox.IsOut(aB2d) == Standard_False) {
+ if (anObj->Intersect(thePolygon, theTrfInv, isFullyIn)) {
+ mapObj.Add (anObj->ID());
+ aResult = Standard_True;
+ }
+ }
+ }
+ }
+ }
+ return aResult;
+}
+
//=======================================================================
//function : deselectObj
//purpose :
//=======================================================================
-void deselectObj (const Handle(NIS_InteractiveObject)& theObj,
- const Standard_Integer theID,
- TColStd_PackedMapOfInteger * mapObjects)
+void NIS_InteractiveContext::deselectObj
+ (const Handle(NIS_InteractiveObject)& theObj,
+ const Standard_Integer theID)
{
if (theObj.IsNull() == Standard_False) {
const Handle(NIS_Drawer)& aDrawer = theObj->GetDrawer();
if (theObj->IsTransparent()) {
- mapObjects[NIS_Drawer::Draw_Transparent].Add(theID);
+ myMapObjects[NIS_Drawer::Draw_Transparent].Add(theID);
aDrawer->SetUpdated(NIS_Drawer::Draw_Transparent);
+ } else if (theObj->myBaseType == NIS_Drawer::Draw_Top) {
+ myMapObjects[NIS_Drawer::Draw_Top].Add(theID);
+ aDrawer->SetUpdated(NIS_Drawer::Draw_Top);
} else {
- mapObjects[NIS_Drawer::Draw_Normal].Add(theID);
+ myMapObjects[NIS_Drawer::Draw_Normal].Add(theID);
aDrawer->SetUpdated(NIS_Drawer::Draw_Normal);
}
aDrawer->SetUpdated(NIS_Drawer::Draw_Hilighted);
+ theObj->myDrawType = theObj->myBaseType;
}
}
//purpose :
//=======================================================================
-void selectObj (const Handle(NIS_InteractiveObject)& theObj,
- const Standard_Integer theID,
- TColStd_PackedMapOfInteger * mapObjects)
+void NIS_InteractiveContext::selectObj
+ (const Handle(NIS_InteractiveObject)& theObj,
+ const Standard_Integer theID)
{
if (theObj.IsNull() == Standard_False) {
const Handle(NIS_Drawer)& aDrawer = theObj->GetDrawer();
if (theObj->IsTransparent()) {
- mapObjects[NIS_Drawer::Draw_Transparent].Remove(theID);
+ myMapObjects[NIS_Drawer::Draw_Transparent].Remove(theID);
aDrawer->SetUpdated(NIS_Drawer::Draw_Transparent);
+ } else if (theObj->myDrawType == NIS_Drawer::Draw_Top) {
+ myMapObjects[NIS_Drawer::Draw_Top].Remove(theID);
+ aDrawer->SetUpdated(NIS_Drawer::Draw_Top);
} else {
- mapObjects[NIS_Drawer::Draw_Normal].Remove(theID);
+ myMapObjects[NIS_Drawer::Draw_Normal].Remove(theID);
aDrawer->SetUpdated(NIS_Drawer::Draw_Normal);
}
aDrawer->SetUpdated(NIS_Drawer::Draw_Hilighted);
+ theObj->myDrawType = NIS_Drawer::Draw_Hilighted;
+ }
+}
+
+//=======================================================================
+//function : drawerForDisplay
+//purpose :
+//=======================================================================
+
+const Handle_NIS_Drawer& NIS_InteractiveContext::drawerForDisplay
+ (const Handle_NIS_InteractiveObject& theObj,
+ const Handle_NIS_Drawer& theDrawer)
+{
+ Handle(NIS_Drawer) aDrawer;
+ if (theDrawer.IsNull() == Standard_False) {
+ if (theDrawer->myCtx != this)
+ Standard_NoSuchObject::Raise ("NIS_InteractiveContext::Display (0)");
+ aDrawer = theDrawer;
+ } else {
+ const Handle(NIS_Drawer)& anObjDrawer = theObj->GetDrawer();
+ if (anObjDrawer.IsNull() == Standard_False)
+ return anObjDrawer;
+ aDrawer = theObj->DefaultDrawer(0L);
+ aDrawer->myCtx = this;
+ }
+ return theObj->SetDrawer (aDrawer, Standard_False);
+}
+
+//=======================================================================
+//function : objectIdForDisplay
+//purpose :
+//=======================================================================
+
+void NIS_InteractiveContext::objectForDisplay
+ (Handle_NIS_InteractiveObject& theObj,
+ const NIS_Drawer::DrawType theDrawType)
+{
+ if (theObj->ID() == 0) {
+ // Create a new ID for this object
+ Handle(NIS_InteractiveObject) anObj;
+ theObj->Clone(myAllocator, anObj);
+ theObj = anObj;
+ anObj->myID = myObjects.Length();
+ myObjects.Append (anObj);
+ myMapObjects[theDrawType].Add(anObj->myID);
+ anObj->myDrawType = theDrawType;
+ }
+}
+
+//=======================================================================
+//function : compactObjects
+//purpose :
+//=======================================================================
+
+Handle_NIS_Allocator NIS_InteractiveContext::compactObjects()
+{
+ Handle(NIS_Allocator) aNewAlloc;
+
+ NCollection_List<Handle_NIS_View>::Iterator anIterV;
+ // Check if the memory used by objects has to be compacted.
+ const Standard_Size nAllocated = myAllocator->NAllocated();
+
+ if (nAllocated > 1024*1024) {
+ const Standard_Size nFreed = myAllocator->NFreed();
+ if ((nFreed * 5) / 3 > nAllocated || nFreed > 20*1024*1024)
+ {
+ for (anIterV.Init(myViews); anIterV.More(); anIterV.Next()) {
+ const Handle(NIS_View)& aView = anIterV.Value();
+ if (aView.IsNull() == Standard_False) {
+ aView->myDynHilighted.Nullify();
+ aView->GetDetected().Clear();
+ }
+ }
+ // Compact the memory: clone all objects to a new allocator, release
+ // the old allocator instance.
+ aNewAlloc = new NIS_Allocator;
+ NCollection_Vector<Handle_NIS_InteractiveObject>::Iterator
+ anIter(myObjects);
+ for (; anIter.More(); anIter.Next()) {
+ if (anIter.Value().IsNull() == Standard_False) {
+ Handle(NIS_InteractiveObject)& aNewObj = anIter.ChangeValue();
+ const Handle(NIS_InteractiveObject) anObj = aNewObj;
+ aNewObj.Nullify();
+ anObj->CloneWithID(aNewAlloc, aNewObj);
+ }
+ }
+ }
}
+ return aNewAlloc;
}
+//=======================================================================
+//function : markAllDrawersUpdated
+//purpose :
+//=======================================================================
+
+void markAllDrawersUpdated (const NCollection_Map<Handle_NIS_Drawer>& lstDrv)
+{
+ NCollection_Map<Handle_NIS_Drawer>::Iterator anIterD (lstDrv);
+ for (; anIterD.More(); anIterD.Next()) {
+ const Handle(NIS_Drawer)& aDrawer = anIterD.Value();
+ if (aDrawer.IsNull() == Standard_False) {
+ aDrawer->SetUpdated (NIS_Drawer::Draw_Normal,
+ NIS_Drawer::Draw_Top,
+ NIS_Drawer::Draw_Transparent,
+ NIS_Drawer::Draw_Hilighted);
+ }
+ }
+}
#include <Handle_NIS_InteractiveObject.hxx>
#include <Handle_NIS_View.hxx>
-#include <NCollection_IncAllocator.hxx>
#include <NCollection_Map.hxx>
#include <NCollection_Vector.hxx>
+#include <NIS_Allocator.hxx>
#include <NIS_Drawer.hxx>
#include <NIS_SelectFilter.hxx>
class NIS_View;
class Bnd_B3f;
+class Bnd_B2f;
/**
* InteractiveContext is the central NIS structure that stores and manages
- * all InteractiveObject instances as well as the Drawers for their
+ * all NIS_InteractiveObject instances as well as the Drawers for their
* visualisation.
* There may be one or more Views referred by an InteractiveContext instance.
* Also there may be one or more InteractiveContext instances referring the same
* View. However the latter case is not typical (see NIS_View description).<br>
* To add or remove a View in a Context, use methods AttachView() and
* DetachView().
- * <p>The main purpose of class NIS_InteractiveContext is allocation and
+ *
+ * @section nis_interactivecontext_mgtobjects Management of objects
+ * The main purpose of class NIS_InteractiveContext is allocation and
* management of NIS_InteractiveObject instances.
* <p>An InteractiveObject should be added to the Context by a call to method
- * Display(). After that (not before) it becomes possible to:
+ * Display() or DisplayOnTop(). After that (not before) it becomes possible to:
* <ul>
* <li>change the presentation of the InteractiveObject (e.g., modify the color)
* </li>
- * <li>make the InteractiveObject visible or invisible;</li>
+ * <li>make the InteractiveObject visible or invisible, selectable or
+ * unselectable;</li>
* <li>set Transparency;</li>
* <li>select InteractiveObject interactively, including the hilighting and
* the dynamic hilighting.</li>
* </ul>
- * All methods managing InteractiveObject instances have the optional parameter
- * 'isUpdateViews'. When it is set to True (default), the modification of the
- * object brings about the immediate update of the presentation (the
- * corresponding Drawer is flagged to recompute presentations). However, for
- * block operations when many InteractiveObject instances are affected it is
- * usually better to delay this recalculation till a definite moment in the end
- * of updates. Then you can set the optional parameter to False and in the end -
- * call the method UpdateViews of the NIS_InteractiveContext.
+ * Methods that add/remove/display/hide NIS_InteractiveObject instances have
+ * the optional parameter 'isUpdateViews'. When it is set to True (default),
+ * the modification of the object brings about an immediate update of its
+ * presentation (the corresponding Drawer flagged to recompute presentations).
+ * Normally you do not have to worry about this parameter leaving it assigned to
+ * the default value; use the alternative value 'Standard_False' only for
+ * very special purposes, like animation -- when many updates should be
+ * synchronized in time. For other methods like changing the transparency or
+ * color definition there is no parameter 'isUpdateViews', all changes mark
+ * the corresponding drawers immediately.
* <p>Typical scheme of usage:
* @code
* const Handle(NIS_InteractiveContext) aContext = new NIS_InteractiveContext;
* aContext->AttachView (aView);
* ....
* for (; ;) {
- * const Handle(NIS_InteractiveObject) anObject = new ...
- * aContext->Display (anObject, NULL, Standard_False);
+ * const Handle(MyIOClass) anObject = new MyIOClass();
+ * aContext->Display (anObject);
+ * anObject->SetColor(...); // method of class MyIOClass
* ...
* }
- * aContext->UpdateViews();
* @endcode
- * Additional services provided by InteractiveContext:
+ * @section nis_interactivecontext_display Method Display()
+ * This method performs three important tasks, when called the first time for
+ * an object:
* <ul>
- * <li>Every instance of this class maintains a distinct
- * NCollection_IncAllocator that can be used by contained
- * NIS_InteractiveObject and NIS_Drawer instances. For example, each Object
- * may be assigned a name using the method SetAttribute, like:
- * @code
- * Standard_Size aLen = strlen(theName)+1;
- * char * aName = (char *) myContext->Allocator()->Allocate(aLen);
- * memcpy (aName, theName, aLen);
- * myObject->SetAttribute(aName);
- * @endcode
- * </li>
+ * <li>Copy its argument to the memory pool that is managed by the internal
+ * Allocator of NIS_InteractiveContext. Then <b>the new instance of
+ * object</b> is returned back in the same argument (in-out parameter);</li>
+ * <li>Store the copied instance in the internal vector of objects, so that
+ * the displayed object receives its ID (sequential address in the vector);
+ * </li>
+ * <li>Create a Drawer instance if necessary; attach the displayed interactive
+ * object to this instance (or to a relevant and already existing Drawer)
+ * </li>
* </ul>
+ * Thus any methods dealing with Drawer-related properties like color, line
+ * width, polygon offset, etc. can only be called following the necessary call
+ * of method Display().
+ * <p>
+ * Subsequent calls to Display() just revert previous calls of Erase() without
+ * any re-initialization of interactive object or its drawer.
+ *
+ * @section nis_interactivecontext_memory Using the memory
+ * As described in the sections above, all interactive objects should completely
+ * reside in the special memory pool managed by the InteractiveContext instance.
+ * This is a fast memory (NCollection_IncAllocator is used) but it has the
+ * drawback: when you destroy an object using method Remove() it is detached
+ * from NIS_InteractiveContext and its presentation is removed from all Views.
+ * But the memory allocated for that removed object is not released and it
+ * cannot be reused by new interactive objects. In time there may appear too
+ * many "dead" objects to hinder or even crash the application.
+ * <p>
+ * This problem is resolved by automatic keeping the record of the total size
+ * of both used and unused memory, in the instance of NIS_Allocator. When the
+ * amount of unused memory becomes too big then the method compactObjects()
+ * creates a new NIS_Allocator instance and copies there all interactive
+ * objects that are 'alive' then releasing the previous memory pool. All
+ * object IDs and their drawers remain intact, so nothing is changed except
+ * the greater amount of available memory in the system.
+ * <p>
+ * This mechanism works when either UpdateViews() or RebuildViews() is called
+ * from time to time, only these two methods can call compactObjects().
*/
class NIS_InteractiveContext : public Standard_Transient
NbObjects ()
// { return myObjects.Length()-1; }
{ return (myMapObjects[0].Extent() + myMapObjects[1].Extent() +
- myMapObjects[2].Extent()); }
+ myMapObjects[2].Extent()) + myMapObjects[3].Extent(); }
/**
* Query the total number of Drawers instances.
{ return myDrawers.Size(); }
/**
- * Query the memory allocator associated with InteractiveContext instance.
- */
- inline const Handle_NCollection_IncAllocator&
- Allocator () const
- { return myAllocator; }
+ * Access to Drawers, can be used for specific operations where it is not
+ * desirale to iterate InteractiveObjects.
+ */
+ inline NCollection_Map<Handle_NIS_Drawer>::Iterator
+ GetDrawers () const
+ { return NCollection_Map<Handle_NIS_Drawer>::Iterator(myDrawers); }
// ================ BEGIN Mangement of Objects ================
///@name Management of Objects
* this method should follow the creation of an InteractiveObject instance
* before it can be displayed.
* @param theObj
- * Interactive object instance.
+ * <tt>[in/out]</tt>Interactive object instance. If the object is displayed
+ * for the first time then the output value will be a new (cloned) object.
* @param theDrawer
* If this parameter is NULL, the default drawer is used for theObj, defined
* by the object type. Otherwise the given Drawer (must be present in this
* to False if you have to make a number of similar calls, then you would
* call UpdateViews() in the end.
*/
- Standard_EXPORT void Display (const Handle_NIS_InteractiveObject& theObj,
+ Standard_EXPORT void Display (Handle_NIS_InteractiveObject& theObj,
const Handle_NIS_Drawer& theDrawer = NULL,
const Standard_Boolean isUpdateViews
= Standard_True);
+ /**
+ * Make the given interactive object visible on top of other objects in
+ * the current context.
+ * If the object is not yet added to this context, it is added. Therefore
+ * this method should follow the creation of an InteractiveObject instance
+ * before it can be displayed.
+ * @param theObj
+ * Interactive object instance.
+ * @param theDrawer
+ * If this parameter is NULL, the default drawer is used for theObj, defined
+ * by the object type. Otherwise the given Drawer (must be present in this
+ * context) is used for theObj. Use the parameter to change the presentation
+ * of theObj.
+ * @param isUpdateViews
+ * If True, the drawer receives isUpdate flag, then it will recompute
+ * the presentations when Redraw event happens. You can leave the parameter
+ * to False if you have to make a number of similar calls, then you would
+ * call UpdateViews() in the end.
+ */
+ Standard_EXPORT void DisplayOnTop (Handle_NIS_InteractiveObject& theObj,
+ const Handle_NIS_Drawer& theDrawer = NULL,
+ const Standard_Boolean isUpdateViews
+ = Standard_True);
+
/**
* Make the given object invisible in the current InteractiveContext.
* @param theObj
/**
* Make all stored InteractiveObject instances visible, equivalent to
* calling method Display() for all contained objects.
- * @param isUpdateViews
- * If True, the drawer receives isUpdate flag, then it will recompute
- * the presentations when Redraw event happens. You can leave the parameter
- * to False if you have to make a number of similar calls, then you would
- * call UpdateViews() in the end.
*/
- Standard_EXPORT void DisplayAll (const Standard_Boolean isUpdateViews
- = Standard_True);
+ Standard_EXPORT void DisplayAll ();
/**
* Make all stored InteractiveObject instances invisible, equivalent to
* calling method Erase() for all contained objects.
- * @param isUpdateViews
- * If True, the drawer receives isUpdate flag, then it will recompute
- * the presentations when Redraw event happens. You can leave the parameter
- * to False if you have to make a number of similar calls, then you would
- * call UpdateViews() in the end.
*/
- Standard_EXPORT void EraseAll (const Standard_Boolean isUpdateViews
- = Standard_True);
+ Standard_EXPORT void EraseAll ();
/**
- * Clean the context of its contained objects. Drawers are not destroyed
- * however all presentations should become empty.
- * @param isUpdateViews
- * If True, the drawer receives isUpdate flag, then it will recompute
- * the presentations when Redraw event happens. You can leave the parameter
- * to False if you have to make a number of similar calls, then you would
- * call UpdateViews() in the end.
+ * Clean the context of its contained objects. Drawers are destroyed
+ * and all presentations become empty.
*/
- Standard_EXPORT void RemoveAll (const Standard_Boolean isUpdateViews
- = Standard_True);
+ Standard_EXPORT void RemoveAll ();
/**
- * This method signal that the presenation should be refreshed in all
- * Drawers and in all Views.
+ * This method signals that the presenation should be refreshed in all updated
+ * Drawers and in all Views. Calls Redraw() of each view from inside.
*/
Standard_EXPORT void UpdateViews ();
+ /**
+ * Similar to UpdateViews but forces all presentations to be rebuilt whether
+ * the drawers are marked as updated or not.
+ */
+ Standard_EXPORT void RebuildViews();
+
/**
* Find the bounding box of all Objects displayed (visible) in the given View.
* @param theBox
inline Standard_Boolean IsSelectable (const Standard_Integer objID) const
{ return (myMapNonSelectableObjects.Contains( objID ) == Standard_False); }
+ /**
+ * Set or reset the flag that tells to NIS_Drawer to create shared DrawList.
+ * The default mode (in Constructor) is True.
+ */
+ inline void SetShareDrawList (Standard_Boolean isShare)
+ { myIsShareDrawList = isShare; }
//@}
// ====== END Selection API ================
protected:
+ //! Structure referencing one detected (picked) interactive entity.
+ struct DetectedEnt
+ {
+ Standard_Real Dist; //!< Distance on the view direction
+ NIS_InteractiveObject* PObj; //!< Pointer to interactive object
+ };
+
// ---------- PROTECTED METHODS ----------
Standard_EXPORT void redraw (const Handle_NIS_View& theView,
const NIS_Drawer::DrawType theType);
- /*Standard_EXPORT void prepareList (const NIS_Drawer::DrawType theType,
- const NIS_DrawList& theView,
- NIS_Drawer * theDrawer);
- */
/**
* Detect the object selected by the given ray.
* @param theSel
* <tt>[out]</tt> The selected object that has the lowest ray distance.
+ * @param theDet
+ * <tt>[out]</tt> Sorted list of all detected objects with ray distances
* @param theAxis
* Selection ray
* @param theOver
*/
Standard_EXPORT Standard_Real
selectObject (Handle_NIS_InteractiveObject& theSel,
+ NCollection_List<DetectedEnt>& theDet,
const gp_Ax1& theAxis,
const Standard_Real theOver,
const Standard_Boolean isOnlySelectable
const gp_Trsf& theTrfInv,
const Standard_Boolean isFullyIn)const;
+ /**
+ * Build a list of objects that are inside or touched by a polygon.
+ * @param mapObj
+ * <tt>[out]</tt> Container of object IDs, updated by detected objects.
+ * @param thePolygon
+ * the list of vertices of a free-form closed polygon without
+ * self-intersections. The last point should not coincide with the first
+ * point of the list. Any two neighbor points should not be confused.
+ * @param thePolygonBox
+ * 2D box of selection polygon
+ * @param theTrfInv
+ * Inverted Position/Orientation of the plane where thePolygon is defined
+ * (for polygon-object intersections)
+ * @param isFullyIn
+ * True if only those objects are processed that are fully inside the
+ * selection polygon. False if objects fully or partially included in
+ * the polygon are processed.
+ * @return
+ * True if at least one object was selected.
+ */
+ Standard_EXPORT Standard_Boolean
+ selectObjects (TColStd_PackedMapOfInteger &mapObj,
+ const NCollection_List<gp_XY> &thePolygon,
+ const Bnd_B2f &thePolygonBox,
+ const gp_Trsf &theTrfInv,
+ const Standard_Boolean isFullyIn) const;
+
+private:
+ void deselectObj (const Handle_NIS_InteractiveObject&,
+ const Standard_Integer);
+
+ void selectObj (const Handle_NIS_InteractiveObject&,
+ const Standard_Integer);
+
+ const Handle_NIS_Drawer&
+ drawerForDisplay (const Handle_NIS_InteractiveObject&,
+ const Handle_NIS_Drawer&);
+
+ void objectForDisplay (Handle_NIS_InteractiveObject&,
+ const NIS_Drawer::DrawType);
+
+ Handle_NIS_Allocator
+ compactObjects ();
+
private:
// ---------- PRIVATE FIELDS ----------
+ /**
+ * Allocator for all data associated with objects.
+ */
+ Handle_NIS_Allocator myAllocator;
+
/**
* Container of InteractiveObject instances.
*/
/**
* Three maps indicating the state of contained objects:
* - #0 - normally presented objects
- * - #1 - hilighted objects (i.e., selected)
- * - #2 - transparent objects
+ * - #1 - top objects
+ * - #2 - hilighted objects (i.e., selected)
+ * - #3 - transparent objects
* <br>Each object can have only one entry in these maps.
*/
- TColStd_PackedMapOfInteger myMapObjects[3];
+ TColStd_PackedMapOfInteger myMapObjects[4];
/**
* Objects contained in this map are ignored by SetSelected methods,
*/
Handle_NIS_SelectFilter mySelectFilter;
- /**
- * Current selection.
- */
- // TColStd_PackedMapOfInteger mySelection;
-
/**
* Current mode of selection.
*/
SelectionMode mySelectionMode;
/**
- * Allocator for arbitrary data associated with objects and drawers.
+ * Flag that allows to use single draw list for all views.
*/
- Handle_NCollection_IncAllocator myAllocator;
+ Standard_Boolean myIsShareDrawList;
friend class NIS_View;
friend class NIS_Drawer;
//=======================================================================
const Handle_NIS_Drawer& NIS_InteractiveObject::SetDrawer
- (const Handle(NIS_Drawer)& theDrawer)
+ (const Handle(NIS_Drawer)& theDrawer,
+ const Standard_Boolean setUpdated)
{
NIS_InteractiveContext * aCtx = theDrawer->GetContext();
if (myDrawer.IsNull() == Standard_False)
Standard_NullValue_Raise_if
(aCtx == 0L, "NIS_InteractiveObject::SetDrawer: NULL drawer context");
// Add (if necessary) the new drawer to the Context
+ if (theDrawer->myIniId == 0)
+ theDrawer->myIniId = myID;
const Handle(NIS_Drawer)& aDrawer = aCtx->myDrawers.Added (theDrawer);
if (myDrawer != aDrawer)
{
myDrawer->removeObject(this, Standard_True);
myDrawer = aDrawer;
- myDrawer->addObject(this, Standard_True);
+ myDrawer->addObject(this, aCtx->myIsShareDrawList, Standard_True);
}
+ if (setUpdated)
+ myDrawer->SetUpdated (NIS_Drawer::Draw_Normal,
+ NIS_Drawer::Draw_Top,
+ NIS_Drawer::Draw_Transparent,
+ NIS_Drawer::Draw_Hilighted);
return aDrawer;
}
void NIS_InteractiveObject::SetTransparency (const Standard_Real theValue)
{
- if (fabs(theValue - myTransparency) > 0.001) {
- if (theValue > 0.001)
- myTransparency = static_cast<const Standard_ShortReal> (theValue);
+ Standard_Integer aValue =
+ static_cast<Standard_Integer> (theValue * MaxTransparency);
+ if (aValue != static_cast<Standard_Integer>(myTransparency))
+ {
+ if (aValue <= 0)
+ myTransparency = 0;
+ else if (aValue >= 1000)
+ myTransparency = 1000u;
else
- myTransparency = 0.f;
+ myTransparency = static_cast<unsigned int> (aValue);
if (myDrawer.IsNull() == Standard_False && myID != 0) {
+ const Handle(NIS_Drawer) aDrawer = DefaultDrawer(0L);
+ aDrawer->Assign (GetDrawer());
+ aDrawer->myTransparency = Transparency();
+ SetDrawer (aDrawer, Standard_False);
+
NIS_InteractiveContext * aCtx = myDrawer->GetContext();
Standard_NullValue_Raise_if
(aCtx == 0L, "NIS_InteractiveObject::SetTransparency: "
return myBox;
}
+//=======================================================================
+//function : Clone
+//purpose :
+//=======================================================================
+
+void NIS_InteractiveObject::Clone (const Handle_NCollection_BaseAllocator&,
+ Handle_NIS_InteractiveObject& theDest) const
+{
+ if (theDest.IsNull() == Standard_False)
+ {
+ theDest->myID = 0;
+ theDest->myDrawer = myDrawer;
+ theDest->myDrawType = myDrawType;
+ theDest->myBaseType = myBaseType;
+ theDest->myIsHidden = myIsHidden;
+ theDest->myIsDynHilighted = myIsDynHilighted;
+ theDest->myIsUpdateBox = myIsUpdateBox;
+ theDest->myTransparency = myTransparency;
+ if (myIsUpdateBox == Standard_False)
+ theDest->myBox = myBox;
+ theDest->myAttributePtr = myAttributePtr;
+ }
+}
+
+//=======================================================================
+//function : CloneWithID
+//purpose :
+//=======================================================================
+
+void NIS_InteractiveObject::CloneWithID
+ (const Handle_NCollection_BaseAllocator& theAlloc,
+ Handle_NIS_InteractiveObject& theDest)
+{
+ Clone(theAlloc, theDest);
+ theDest->myID = myID;
+ myDrawer.Nullify();
+}
+
//=======================================================================
//function : Intersect
//purpose :
return Standard_True;
}
+//=======================================================================
+//function : Intersect
+//purpose :
+//=======================================================================
+
+Standard_Boolean NIS_InteractiveObject::Intersect
+ (const NCollection_List<gp_XY> &thePolygon,
+ const gp_Trsf &theTrf,
+ const Standard_Boolean isFull) const
+{
+ return Standard_True;
+}
+
//=======================================================================
//function : IsSelectable
//purpose : Query if the Object is selectable.
aCtx->myMapNonSelectableObjects.Remove (myID);
else {
aCtx->myMapNonSelectableObjects.Add (myID);
- if (aCtx->myMapObjects[NIS_Drawer::Draw_Hilighted].Remove(myID))
+ if (myDrawType == NIS_Drawer::Draw_Hilighted)
{
- if (IsTransparent()) {
- aCtx->myMapObjects[NIS_Drawer::Draw_Transparent].Add(myID);
- myDrawer->SetUpdated(NIS_Drawer::Draw_Transparent);
- } else {
- aCtx->myMapObjects[NIS_Drawer::Draw_Normal].Add(myID);
- myDrawer->SetUpdated(NIS_Drawer::Draw_Normal);
- }
- myDrawer->SetUpdated(NIS_Drawer::Draw_Hilighted);
+ aCtx->myMapObjects[NIS_Drawer::Draw_Hilighted].Remove(myID);
+ aCtx->deselectObj (this, myID);
}
}
}
* An InteractiveObject has the attributes:
* <ul>
* <li>Integer ID that is unique within the Interactive Context that hosts
- * this Object. Thsi ID is 0 if the Object is not yet attached to an
+ * this Object. This ID is 0 if the Object is not yet attached to an
* InteractiveContext</li>
* <li>3D Bounding box</li>
- * <li>Presenatble state of the Object: Normal, Hilighted or Transparent.</li>
+ * <li>Presentable state of the Object: Normal, Hilighted or Transparent.</li>
* <li>Visibility state (shown/hidden)</li>
- * <li>Transparency level (0 to 1) - for transparent state</li>
+ * <li>Selectability (selectable/non-selectable)</li>
+ * <li>Transparency level (0 to 1 in 1/1000 steps) - for transparent state</li>
* </ul>
* Because the class is abstract, it does not define any color, material and
* other visual aspect - all relevant aspects should be defined in derived
- * classes.<br>
+ * classes and their Drawers.
+ *
+ * @section nis_interactiveobject_drawer Drawers for NIS_InteractiveObject
* Every InteractiveObject type should have an associated NIS_Drawer type; a
- * new instance of this associated drawer is returned by the virtual method
+ * new instance of this associated drawer must be returned by the virtual method
* DefaultDrawer(). The drawer is responsible for the correct calculation of
* the presentation in every possible state (normal, hilighted, etc.); usually
- * the associated drawer instance contains all relevant visual aspects.<p>
- * Association with a Drawer instance is performed by method SetDrawer. This
+ * the associated drawer instance contains all relevant visual aspects.
+ * <p>
+ * Association with a Drawer instance is performed by method SetDrawer(). This
* method should not be called by any custom code, it is used internally by
* NIS algorithms (in NIS_InteractiveContext::Display() for instance). If you
* develop your own InteractiveObject type, you will need to call SetDrawer
* @code
* void MyIOClass::SetColor (const Quantity_Color& theColor);
* {
- * Handle(MyIOClassDrawer) aDrawer = new MyIOClassDrawer;
+ * const Handle(MyIOClassDrawer) aDrawer =
+ * static_cast<MyIOClassDrawer*>(DefaultDrawer(0L));
* // copy the current visual aspects and other attributes to the new Drawer
* aDrawer->Assign (GetDrawer());
* // replace the Drawer
* aDrawer->myColor = theColor;
* SetDrawer (aDrawer);
- * // optional: redraws the changed InteractiveObject in the views
- * GetDrawer()->GetContext()->UpdateViews();
* }
* @endcode
- * <p>
+ * Please keep in mind that with this scheme you should not store the color in
+ * MyIOClass type, because it is already stored in its Drawer.
+ *
+ * @section nis_interactiveobject_selection Interactive selection
+ * Interactive selection is made in class NIS_InteractiveContext, methods
+ * selectObjects(). These methods call the virtual API of interactive object,
+ * that consists of 3 methods:
+ * <ul>
+ * <li>Intersect (theAxis, theOver) : find the intersection point with a 3D ray,
+ * the method returns the coordinate of intersection point on the ray.
+ * Parameter theOver provides the tolerance for intersection of thin
+ * geometries (lines, vertices)</li>
+ * <li>Intersect (theBox, theTrsf, isFullIn) : check if the interactive object
+ * intersects with a 3D box. Transformation 'theTrf' is the <b>inverse</b>
+ * box transformation, so it is applied to the interactive object rather
+ * than to the 3D box (3D box stays axis-aligned during intersection
+ * test). Parameter IsFullIn defines the condition for the result: if
+ * True then the whole interactive object must be contained inside the box,
+ * otherwise it is sufficient if only a portion (e.g., a point) is inside.
+ * This method is used for interactive rectangle selection.</li>
+ * <li>Intersect (thePolygon, theTrsf, isFullIn) : similar to the previous
+ * method, but using a polygonal prism instead of box, for selection by
+ * closed curve or polygon.</li>
+ * </ul>
+ *
+ * @section nis_interactiveobject_memory Memory management
+ * All data used in the scope of NIS_InteractiveObject subtype should be either
+ * its explicit fields or pointers to memory managed by a special NIS_Allocator
+ * instance that belongs to NIS_InteractiveContext. This is strictly required
+ * because NIS_InteractiveContext should completely manage all its objects,
+ * meaning that it destroys/reallocates them automatically. To support that,
+ * the virtual method Clone() should be correctly defined for every interactive
+ * object subtype. Supposing that MyIOClass inherits MyBaseIOBase :
+ * @code
+ * void MyIOCalss::Clone (const Handle_NCollection_BaseAllocator& theAlloc,
+ * Handle_NIS_InteractiveObject& theDest) const
+ * {
+ * Handle(MyIOClass) aNewObj;
+ * if (theDest.IsNull()) {
+ * aNewObj = new MyIOClass();
+ * theDest = aNewObj;
+ * } else {
+ * aNewObj = reinterpret_cast<MyIOClass*> (theDest.operator->());
+ * aNewObj->myAlloc = theAlloc;
+ * }
+ * MyIOBase::Clone(theAlloc, theDest);
+ * aNewObj->myDataField = myDataField;
+ * memcpy(myNewObj->myDataArray, myDataArray, nBytes);
+ * ...
+ * }
+ * @endcode
+ *
+ * @section nis_interactiveobject_attribute Attribute
* An instance of this class can have an associated value (Attribute) that is
* stored as a pointer. It can accommodate an integer/float/boolean value or
* a pointer to some structure. This attribute is NOT automatically destroyed
inline NIS_InteractiveObject ()
: myID (0),
myDrawType (NIS_Drawer::Draw_Normal),
+ myBaseType (NIS_Drawer::Draw_Normal),
myIsHidden (Standard_True),
myIsDynHilighted (Standard_False),
myIsUpdateBox (Standard_True),
- myTransparency (0.f),
+ myTransparency (0),
myAttributePtr (0L)
{}
* the Context.
*/
Standard_EXPORT const Handle_NIS_Drawer&
- SetDrawer (const Handle_NIS_Drawer& theDrawer);
+ SetDrawer (const Handle_NIS_Drawer& theDrawer,
+ const Standard_Boolean setUpdated
+ = Standard_True);
/**
* Query the current drawer.
{ return myDrawer; }
/**
- * Create a default drawer instance.
+ * Create a default drawer instance. In the upper-level call (in subclass)
+ * it is always called with NULL parameter. Then it should call the same
+ * method of the superclass (except for NIS_InteractiveObject superclass type)
+ * with the created Drawer instance as parameter.
+ * @see NIS_Triangulated as example.
*/
- Standard_EXPORT virtual Handle_NIS_Drawer
- DefaultDrawer () const = 0;
+ Standard_EXPORT virtual NIS_Drawer *
+ DefaultDrawer (NIS_Drawer * theDrv) const = 0;
/**
* Query a 3D bounding box of the object.
* Query the Transparent state.
*/
inline Standard_Boolean IsTransparent () const
- { return myTransparency > 0.001; }
+ { return myTransparency > 0; }
/**
* Query the Hidden state
/**
* Query if the Object is selectable.
*/
- Standard_EXPORT Standard_Boolean
+ Standard_EXPORT virtual Standard_Boolean
IsSelectable () const;
/**
* True (default) - the Object will be selectable, False - it will be
* ignored by selection/hilighting algorithms.
*/
- Standard_EXPORT void SetSelectable (const Standard_Boolean isSel
+ Standard_EXPORT virtual void
+ SetSelectable (const Standard_Boolean isSel
= Standard_True) const;
/**
* Query the Transparency factor.
*/
- inline Standard_Real Transparency () const
- { return myTransparency; }
+ inline Standard_ShortReal Transparency () const
+ { return static_cast<Standard_ShortReal>(myTransparency) / MaxTransparency; }
/**
* Set the Transparency factor.
inline void UnsetTransparency ()
{ SetTransparency (0.); }
+ /**
+ * Create a copy of theObject except its ID.
+ * @param theAll
+ * Allocator where the Dest should store its private data.
+ * @param theDest
+ * <tt>[in-out]</tt> The target object where the data are copied.
+ */
+ Standard_EXPORT virtual void
+ Clone (const Handle_NCollection_BaseAllocator& theAll,
+ Handle_NIS_InteractiveObject& theDest) const;
+
+ /**
+ * The same as Clone() but also copies the ID.
+ */
+ Standard_EXPORT void CloneWithID (const Handle_NCollection_BaseAllocator&,
+ Handle_NIS_InteractiveObject&);
+
/**
* Intersect the InteractiveObject geometry with a line/ray.
* @param theAxis
const gp_Trsf& theTrf,
const Standard_Boolean isFull) const;
+ /**
+ * Intersect the InteractiveObject geometry with a selection polygon.
+ * The default implementation (in this abstract class) always returns True,
+ * signalling that every object pre-selected by its bounding box is
+ * automatically selected. The specializations should define a more correct
+ * behaviour.<br>
+ * The algorithm should transform the InteractiveObject geometry using the
+ * parameter theTrf and then reject it with polygon.
+ * @param thePolygon
+ * the list of vertices of a free-form closed polygon without
+ * self-intersections. The last point should not coincide with the first
+ * point of the list. Any two neighbor points should not be confused.
+ * @param theTrf
+ * Position/Orientation of the polygon. It coincides with theTrfInv that is
+ * passed to NIS_InteractiveContext::selectObjects().
+ * @param isFull
+ * True if full inclusion is required (full inside the tested box) for
+ * the positive result, False - if only partial inclusion give a result.
+ * @return
+ * True if the InteractiveObject geometry intersects the polygon or is inside it
+ */
+ Standard_EXPORT virtual Standard_Boolean
+ Intersect (const NCollection_List<gp_XY> &thePolygon,
+ const gp_Trsf &theTrf,
+ const Standard_Boolean isFull) const;
+
/**
* Set the pointer to custom (arbitrary) data associated with the Object.
*/
// ---------- PRIVATE FIELDS ----------
Handle_NIS_Drawer myDrawer;
- Standard_Size myID : 26;
- NIS_Drawer::DrawType myDrawType : 2;
+ Standard_Size myID;
+ NIS_Drawer::DrawType myDrawType : 3;
+ NIS_Drawer::DrawType myBaseType : 3;
Standard_Boolean myIsHidden : 1;
Standard_Boolean myIsDynHilighted: 1;
Standard_Boolean myIsUpdateBox : 1;
- Standard_ShortReal myTransparency;
+ unsigned int myTransparency : 10;
+ static const unsigned int MaxTransparency = 1000;
protected:
Bnd_B3f myBox;
void * myAttributePtr;
+
friend class NIS_InteractiveContext;
friend class NIS_Drawer;
if (myIter.Value().IsNull() == Standard_False)
break;
}
+
+//=======================================================================
+//function : Value
+//purpose :
+//=======================================================================
+
+const Handle(NIS_InteractiveObject)& NIS_ObjectsIterator::Value() const
+{
+ if (More())
+ return myIter.Value();
+ static const Handle(NIS_InteractiveObject) aNullObj;
+ return aNullObj;
+}
* Returns the current object at the iteration pointer. If the iteration is
* over (More() == False) this method returns NULL Handle.
*/
- inline Handle(NIS_InteractiveObject)
- Value () const
- { if (More()) return myIter.Value(); return NULL; }
+ Standard_EXPORT const Handle_NIS_InteractiveObject&
+ Value () const;
/**
* Step forward to the next valid InteractiveObject instance.
#include <NIS_Surface.hxx>
#include <NIS_SurfaceDrawer.hxx>
#include <NIS_Triangulated.hxx>
+#include <BRepMesh_IncrementalMesh.hxx>
+#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
+#include <BRep_PolygonOnTriangulation.hxx>
+#include <BRep_TEdge.hxx>
#include <BRep_Tool.hxx>
#include <Geom_Surface.hxx>
+#include <NCollection_Map.hxx>
+#include <Poly_PolygonOnTriangulation.hxx>
#include <Poly_Triangulation.hxx>
#include <Precision.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
+#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
+#include <TopTools_MapOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TShort_Array1OfShortReal.hxx>
#include <gp_Ax1.hxx>
IMPLEMENT_STANDARD_HANDLE (NIS_Surface, NIS_InteractiveObject)
IMPLEMENT_STANDARD_RTTIEXT(NIS_Surface, NIS_InteractiveObject)
//=======================================================================
-//function : defaultDrawer
-//purpose : internal method (static)
+//function : IsEqual
+//purpose : Compare two triangulations, for NCollection_Map interface.
//=======================================================================
-inline Handle(NIS_SurfaceDrawer) defaultDrawer()
+inline Standard_Boolean IsEqual(const Handle_Poly_Triangulation& theT0,
+ const Handle_Poly_Triangulation& theT1)
{
- const Handle(NIS_SurfaceDrawer) aDrawer =
- new NIS_SurfaceDrawer(Quantity_NOC_SLATEBLUE4);
- aDrawer->SetBackColor (Quantity_NOC_DARKGREEN);
- return aDrawer;
+ return (theT0 == theT1);
+}
+
+//=======================================================================
+//function : NIS_Surface
+//purpose :
+//=======================================================================
+
+NIS_Surface::NIS_Surface(const Handle_NCollection_BaseAllocator& theAlloc)
+ : myAlloc (theAlloc),
+ mypNodes (NULL),
+ mypNormals (NULL),
+ mypTriangles (NULL),
+ mypEdges (NULL),
+ myNNodes (0),
+ myNTriangles (0),
+ myNEdges (0),
+ myIsWireframe(0)
+{
+ if (myAlloc.IsNull())
+ myAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
}
//=======================================================================
//purpose :
//=======================================================================
-NIS_Surface::NIS_Surface
- (const Handle(Poly_Triangulation)& theTri,
- const Handle_NCollection_BaseAllocator& theAlloc)
-: mypNodes (NULL),
- mypNormals (NULL),
- myNNodes (0),
- myNTriangles (0),
- myAlloc (theAlloc)
+NIS_Surface::NIS_Surface (const Handle(Poly_Triangulation)& theTri,
+ const Handle_NCollection_BaseAllocator& theAlloc)
+ : myAlloc (theAlloc),
+ mypNodes (NULL),
+ mypNormals (NULL),
+ mypEdges (NULL),
+ myNNodes (0),
+ myNTriangles (0),
+ myNEdges (0),
+ myIsWireframe(0)
{
if (myAlloc.IsNull())
myAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
//purpose : Constructor
//=======================================================================
-NIS_Surface::NIS_Surface
- (const TopoDS_Shape& theShape,
-// const Standard_Real theDeflection,
- const Handle_NCollection_BaseAllocator& theAlloc)
- : mypNodes (NULL),
+NIS_Surface::NIS_Surface (const TopoDS_Shape& theShape,
+ const Standard_Real theDeflection,
+ const Handle_NCollection_BaseAllocator& theAlloc)
+ : myAlloc (theAlloc),
+ mypNodes (NULL),
mypNormals (NULL),
mypTriangles (NULL),
+ mypEdges (NULL),
myNNodes (0),
myNTriangles (0),
- myAlloc (theAlloc)
+ myNEdges (0),
+ myIsWireframe (0)
{
if (myAlloc.IsNull())
myAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
+ Init (theShape, theDeflection);
+}
+
+//=======================================================================
+//function : Init
+//purpose : Initialize the instance with a TopoDS_Shape.
+//=======================================================================
+
+void NIS_Surface::Init (const TopoDS_Shape& theShape,
+ const Standard_Real theDeflection)
+{
TopLoc_Location aLoc, aLocSurf;
// Count the nodes and triangles in faces
+ NCollection_Map<Handle_Poly_Triangulation> mapTri;
TopExp_Explorer fexp (theShape, TopAbs_FACE);
- for ( ; fexp.More(); fexp.Next() )
+ for (; fexp.More(); fexp.Next())
{
- TopoDS_Face aFace = TopoDS::Face(fexp.Current());
+ const TopoDS_Face& aFace = TopoDS::Face(fexp.Current());
const Handle(Poly_Triangulation)& aTriangulation
= BRep_Tool::Triangulation (aFace, aLoc);
- const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aLoc);
+
+ if (aTriangulation.IsNull())
+ BRepMesh_IncrementalMesh aMeshTool(aFace, theDeflection);
- if (aTriangulation.IsNull() == Standard_False &&
- aSurf.IsNull() == Standard_False)
+ if (aTriangulation.IsNull() == Standard_False)
{
myNNodes += aTriangulation->NbNodes();
myNTriangles += aTriangulation->NbTriangles();
+ mapTri.Add(aTriangulation);
}
}
- // Alocate arrays of entities
+ // Create map of edges, to build wireframe for all edges.
+ TopTools_MapOfShape mapEdges;
+ TopExp_Explorer eexp (theShape, TopAbs_EDGE);
+ for (; eexp.More(); eexp.Next())
+ {
+ const TopoDS_Shape& anEdge = eexp.Current();
+ mapEdges.Add(anEdge);
+ }
+
+ // Allocate arrays of entities
if (myNNodes && myNTriangles) {
- mypNodes = static_cast<Standard_ShortReal*>
+ mypNodes = static_cast<Standard_ShortReal *>
(myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes));
mypNormals = static_cast<Standard_ShortReal *>
(myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes));
- mypTriangles = static_cast<Standard_Integer*>
+ mypTriangles = static_cast<Standard_Integer *>
(myAlloc->Allocate(sizeof(Standard_Integer) * 3 * myNTriangles));
+ mypEdges = static_cast<Standard_Integer **>
+ (myAlloc->Allocate(sizeof(Standard_Integer *) * mapEdges.Extent()));
+ myNEdges = 0;
// The second loop: copy all nodes and triangles face-by-face
const Standard_Real eps2 = Precision::Confusion()*Precision::Confusion();
const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aLocSurf);
const Handle(Poly_Triangulation)& aTriangulation =
BRep_Tool::Triangulation(aFace, aLoc);
- if (aTriangulation.IsNull() == Standard_False &&
- aSurf.IsNull() == Standard_False)
+ if (aTriangulation.IsNull() == Standard_False)
{
// Prepare transformation
Standard_Integer i, aNodeInd(nNodes)/*, aNTriangles = 0*/;
gp_Vec aD1U, aD1V;
gp_Pnt aP;
+ gp_XYZ aNorm(0., 0., 0.);
+
+ if (aTriangulation->HasNormals()) {
+ // Retrieve the normal direction from the triangulation
+ aNorm.SetCoord(aTriangulation->Normals().Value(3*i-2),
+ aTriangulation->Normals().Value(3*i-1),
+ aTriangulation->Normals().Value(3*i-0));
+ } else if (aSurf.IsNull() == Standard_False)
+ {
+ // Compute the surface normal at the Node.
+ aSurf->D1(tabUV(i).X(), tabUV(i).Y(), aP, aD1U, aD1V);
+ aNorm = (aD1U.Crossed(aD1V)).XYZ();
+ }
- // Compute the surface normal at the Node.
- aSurf->D1(tabUV(i).X(), tabUV(i).Y(), aP, aD1U, aD1V);
- gp_XYZ aNorm = (aD1U.Crossed(aD1V)).XYZ();
if (isReverse)
aNorm.Reverse();
const Standard_Real aMod = aNorm.SquareModulus();
aNodeInd++;
}
+ const Standard_Integer nNodes1 = nNodes - 1;
// Store all triangles of the current face in the data model
const Poly_Array1OfTriangle& tabTri = aTriangulation->Triangles();
for (i = tabTri.Lower(); i <= tabTri.Upper(); i++)
{
Standard_Integer aN[3];
tabTri(i).Get (aN[0], aN[1], aN[2]);
- if (((tabNode(aN[2]).XYZ() -
- tabNode(aN[0]).XYZ()) ^
- (tabNode(aN[1]).XYZ() -
- tabNode(aN[0]).XYZ())).SquareModulus() > eps2)
- {
- aN[0] += (nNodes - 1);
- aN[1] += (nNodes - 1);
- aN[2] += (nNodes - 1);
- mypTriangles[nTriangles*3 + 0] = aN[0];
- if (isReverse) {
- mypTriangles[nTriangles*3 + 1] = aN[2];
- mypTriangles[nTriangles*3 + 2] = aN[1];
- } else {
- mypTriangles[nTriangles*3 + 1] = aN[1];
- mypTriangles[nTriangles*3 + 2] = aN[2];
- }
+ Standard_Integer * pTriangle = &mypTriangles[nTriangles*3];
+ pTriangle[0] = aN[0] + nNodes1;
+ if (isReverse) {
+ pTriangle[1] = aN[2] + nNodes1;
+ pTriangle[2] = aN[1] + nNodes1;
+ } else {
+ pTriangle[1] = aN[1] + nNodes1;
+ pTriangle[2] = aN[2] + nNodes1;
+ }
+ const Standard_ShortReal aVec0[3] = {
+ mypNodes[3*pTriangle[1]+0] - mypNodes[3*pTriangle[0]+0],
+ mypNodes[3*pTriangle[1]+1] - mypNodes[3*pTriangle[0]+1],
+ mypNodes[3*pTriangle[1]+2] - mypNodes[3*pTriangle[0]+2]
+ };
+ const Standard_ShortReal aVec1[3] = {
+ mypNodes[3*pTriangle[2]+0] - mypNodes[3*pTriangle[0]+0],
+ mypNodes[3*pTriangle[2]+1] - mypNodes[3*pTriangle[0]+1],
+ mypNodes[3*pTriangle[2]+2] - mypNodes[3*pTriangle[0]+2]
+ };
+ const Standard_ShortReal aVecP[3] = {
+ aVec0[1] * aVec1[2] - aVec0[2] * aVec1[1],
+ aVec0[2] * aVec1[0] - aVec0[0] * aVec1[2],
+ aVec0[0] * aVec1[1] - aVec0[1] * aVec1[0]
+ };
+ if (aVecP[0]*aVecP[0] + aVecP[1]*aVecP[1] + aVecP[2]*aVecP[2] > eps2)
nTriangles++;
+ }
+ // Store all edge polygons on the current face.
+ for (eexp.Init(aFace, TopAbs_EDGE); eexp.More(); eexp.Next())
+ {
+ const TopoDS_Edge& anEdge = TopoDS::Edge(eexp.Current());
+ if (mapEdges.Remove(anEdge)) {
+ const Handle(Poly_PolygonOnTriangulation)& aPolygon =
+ BRep_Tool::PolygonOnTriangulation(anEdge, aTriangulation, aLoc);
+ if (aPolygon.IsNull() == Standard_False) {
+ const TColStd_Array1OfInteger& arrNode = aPolygon->Nodes();
+ // Allocate memory to store the current polygon indices.
+ Standard_Integer aLen = arrNode.Length();
+ Standard_Integer * pEdge = static_cast<Standard_Integer *>
+ (myAlloc->Allocate(sizeof(Standard_Integer) * (aLen + 1)));
+ const gp_Pnt* pLast = &tabNode(arrNode(arrNode.Lower()));
+ pEdge[1] = arrNode(arrNode.Lower()) + nNodes1;
+ Standard_Integer iPNode(arrNode.Lower() + 1), iENode(1);
+ for (; iPNode <= arrNode.Upper(); iPNode++)
+ {
+ const Standard_Integer aN(arrNode(iPNode));
+ if (pLast->SquareDistance(tabNode(aN)) < eps2)
+ {
+ aLen--;
+ } else {
+ pLast = &tabNode(aN);
+ pEdge[++iENode] = aN + nNodes1;
+ }
+ }
+ // Do not save very short polygons
+ if (aLen > 1) {
+ pEdge[0] = aLen;
+ mypEdges[myNEdges++] = pEdge;
+ }
+ }
}
}
nNodes += tabNode.Length();
}
myNTriangles = nTriangles;
}
+ if (GetDrawer().IsNull() == Standard_False)
+ {
+ setDrawerUpdate();
+ }
+ setIsUpdateBox(Standard_True);
}
//=======================================================================
//=======================================================================
NIS_Surface::~NIS_Surface ()
+{
+ Clear();
+}
+
+//=======================================================================
+//function : Clear
+//purpose :
+//=======================================================================
+
+void NIS_Surface::Clear ()
{
if (myNNodes) {
myNNodes = 0;
myNTriangles = 0;
myAlloc->Free(mypTriangles);
}
+ if (mypEdges) {
+ for (Standard_Integer i = 0; i < myNEdges; i++) {
+ myAlloc->Free(mypEdges[i]);
+ }
+ myNEdges = 0;
+ myAlloc->Free(mypEdges);
+ }
+ if (GetDrawer().IsNull() == Standard_False) {
+ GetDrawer()->SetUpdated(NIS_Drawer::Draw_Normal,
+ NIS_Drawer::Draw_Top,
+ NIS_Drawer::Draw_Transparent,
+ NIS_Drawer::Draw_Hilighted);
+ }
+ myBox.Clear();
}
//=======================================================================
//purpose :
//=======================================================================
-Handle(NIS_Drawer) NIS_Surface::DefaultDrawer () const
+NIS_Drawer * NIS_Surface::DefaultDrawer (NIS_Drawer * theDrawer) const
{
- return defaultDrawer();
+ NIS_SurfaceDrawer * aDrawer =
+ theDrawer ? static_cast<NIS_SurfaceDrawer *>(theDrawer)
+ : new NIS_SurfaceDrawer (Quantity_NOC_SLATEBLUE4);
+ aDrawer->SetBackColor (Quantity_NOC_DARKGREEN);
+ aDrawer->myIsWireframe = myIsWireframe;
+ return aDrawer;
}
//=======================================================================
void NIS_Surface::SetColor (const Quantity_Color& theColor)
{
- Handle(NIS_SurfaceDrawer) aDrawer = defaultDrawer();
+ const Handle(NIS_SurfaceDrawer) aDrawer =
+ static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L));
aDrawer->Assign (GetDrawer());
aDrawer->myColor[NIS_Drawer::Draw_Normal] = theColor;
+ aDrawer->myColor[NIS_Drawer::Draw_Top] = theColor;
aDrawer->myColor[NIS_Drawer::Draw_Transparent] = theColor;
SetDrawer (aDrawer);
}
void NIS_Surface::SetBackColor (const Quantity_Color& theColor)
{
- Handle(NIS_SurfaceDrawer) aDrawer = defaultDrawer();
+ const Handle(NIS_SurfaceDrawer) aDrawer =
+ static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L));
aDrawer->Assign (GetDrawer());
aDrawer->myBackColor = theColor;
SetDrawer (aDrawer);
void NIS_Surface::SetPolygonOffset (const Standard_Real theValue)
{
- Handle(NIS_SurfaceDrawer) aDrawer = defaultDrawer();
+ const Handle(NIS_SurfaceDrawer) aDrawer =
+ static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L));
aDrawer->Assign (GetDrawer());
- aDrawer->myPolygonOffset = theValue;
+ aDrawer->myPolygonOffset = static_cast<Standard_ShortReal>(theValue);
SetDrawer (aDrawer);
}
//=======================================================================
-//function : SetTransparency
+//function : SetDisplayMode
+//purpose : Set the display mode: Shading or Wireframe.
+//=======================================================================
+
+void NIS_Surface::SetDisplayMode (const NIS_Surface::DisplayMode theMode)
+{
+ Standard_Boolean isUpdate(Standard_False);
+ if (myIsWireframe) {
+ if (theMode != Wireframe) {
+ myIsWireframe = Standard_False;
+ isUpdate = Standard_True;
+ }
+ } else {
+ if (theMode == Wireframe) {
+ myIsWireframe = Standard_True;
+ isUpdate = Standard_True;
+ }
+ }
+ if (isUpdate && GetDrawer()) {
+ const Handle(NIS_SurfaceDrawer) aDrawer =
+ static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L));
+ aDrawer->Assign (GetDrawer());
+ aDrawer->myIsWireframe = myIsWireframe;
+ SetDrawer(aDrawer);
+ }
+}
+
+//=======================================================================
+//function : GetDisplayMode
+//purpose : Query the current display mode: Shading or Wireframe.
+//=======================================================================
+
+NIS_Surface::DisplayMode NIS_Surface::GetDisplayMode () const
+{
+ return myIsWireframe ? Wireframe : Shading;
+}
+
+//=======================================================================
+//function : Clone
//purpose :
//=======================================================================
-void NIS_Surface::SetTransparency (const Standard_Real theValue)
+void NIS_Surface::Clone (const Handle_NCollection_BaseAllocator& theAlloc,
+ Handle_NIS_InteractiveObject& theDest) const
{
- Handle(NIS_SurfaceDrawer) aDrawer = defaultDrawer();
- aDrawer->Assign (GetDrawer());
- aDrawer->myTransparency = theValue;
- SetDrawer (aDrawer);
+ Handle(NIS_Surface) aNewObj;
+ if (theDest.IsNull()) {
+ aNewObj = new NIS_Surface(theAlloc);
+ theDest = aNewObj;
+ } else {
+ aNewObj = reinterpret_cast<NIS_Surface*> (theDest.operator->());
+ aNewObj->myAlloc = theAlloc;
+ }
+ NIS_InteractiveObject::Clone(theAlloc, theDest);
+ aNewObj->myNNodes = myNNodes;
+ if (myNNodes > 0) {
+ // copy nodes and normals
+ const Standard_Size nBytes = myNNodes*3*sizeof(Standard_ShortReal);
+ aNewObj->mypNodes = (Standard_ShortReal *)theAlloc->Allocate(nBytes);
+ aNewObj->mypNormals = (Standard_ShortReal *)theAlloc->Allocate(nBytes);
+ memcpy(aNewObj->mypNodes, mypNodes, nBytes);
+ memcpy(aNewObj->mypNormals, mypNormals, nBytes);
+ }
+ aNewObj->myNTriangles = myNTriangles;
+ if (myNTriangles > 0) {
+ const Standard_Size nBytes = sizeof(Standard_Integer) * 3 * myNTriangles;
+ aNewObj->mypTriangles = (Standard_Integer *)theAlloc->Allocate(nBytes);
+ memcpy(aNewObj->mypTriangles, mypTriangles, nBytes);
+ }
+ aNewObj->myNEdges = myNEdges;
+ if (myNEdges > 0) {
+ aNewObj->mypEdges = static_cast<Standard_Integer **>
+ (theAlloc->Allocate(sizeof(Standard_Integer *) * myNEdges));
+ for (Standard_Integer i = 0; i < myNEdges; i++) {
+ const Standard_Integer * pEdge = mypEdges[i];
+ const Standard_Size nBytes = sizeof(Standard_Integer) * (pEdge[0] + 1);
+ aNewObj->mypEdges[i] =
+ static_cast<Standard_Integer *> (theAlloc->Allocate(nBytes));
+ memcpy(aNewObj->mypEdges[i], pEdge, nBytes);
+ }
+ }
+ aNewObj->myIsWireframe = myIsWireframe;
}
//=======================================================================
//=======================================================================
Standard_Real NIS_Surface::Intersect (const gp_Ax1& theAxis,
- const Standard_Real /*over*/) const
+ const Standard_Real theOver) const
{
Standard_Real aResult (RealLast());
Standard_Real start[3], dir[3];
theAxis.Direction().Coord(dir[0], dir[1], dir[2]);
double anInter;
- for (Standard_Integer i = 0; i < myNTriangles; i++) {
- const Standard_Integer * pTri = &mypTriangles[3*i];
- if (NIS_Triangulated::tri_line_intersect (start, dir,
- &mypNodes[3*pTri[0]],
- &mypNodes[3*pTri[1]],
- &mypNodes[3*pTri[2]],
- &anInter))
- if (anInter < aResult)
- aResult = anInter;
+ if (myIsWireframe == Standard_False)
+ for (Standard_Integer i = 0; i < myNTriangles; i++) {
+ const Standard_Integer * pTri = &mypTriangles[3*i];
+ if (NIS_Triangulated::tri_line_intersect (start, dir,
+ &mypNodes[3*pTri[0]],
+ &mypNodes[3*pTri[1]],
+ &mypNodes[3*pTri[2]],
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ }
+ else {
+ const Standard_Real anOver2 = theOver*theOver;
+ for (Standard_Integer iEdge = 0; iEdge < myNEdges; iEdge++) {
+ const Standard_Integer * anEdge = mypEdges[iEdge];
+ const Standard_Integer nNodes = anEdge[0];
+ for (Standard_Integer i = 1; i < nNodes; i++) {
+ // Node index is incremented for the head of polygon indice array
+ if (NIS_Triangulated::seg_line_intersect (theAxis.Location().XYZ(),
+ theAxis.Direction().XYZ(),
+ anOver2,
+ &mypNodes[3*anEdge[i+0]],
+ &mypNodes[3*anEdge[i+1]],
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ }
+ }
}
return aResult;
//purpose :
//=======================================================================
-Standard_Boolean NIS_Surface::Intersect
- (const Bnd_B3f& theBox,
+Standard_Boolean NIS_Surface::Intersect (const Bnd_B3f& theBox,
const gp_Trsf& theTrf,
const Standard_Boolean isFullIn) const
{
Standard_Boolean aResult (isFullIn);
- if (myNTriangles > 0) {
- for (Standard_Integer iNode = 0; iNode < myNNodes*3; iNode+=3) {
- gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]),
- static_cast<Standard_Real>(mypNodes[iNode+1]),
- static_cast<Standard_Real>(mypNodes[iNode+2]));
- theTrf.Transforms(aPnt);
- if (theBox.IsOut (aPnt) == isFullIn) {
- aResult = !isFullIn;
- break;
+ if (myIsWireframe == Standard_False) {
+ if (myNTriangles > 0) {
+ for (Standard_Integer iNode = 0; iNode < myNNodes*3; iNode+=3) {
+ gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]),
+ static_cast<Standard_Real>(mypNodes[iNode+1]),
+ static_cast<Standard_Real>(mypNodes[iNode+2]));
+ theTrf.Transforms(aPnt);
+ if (theBox.IsOut (aPnt) == isFullIn) {
+ aResult = !isFullIn;
+ break;
+ }
+ }
+ }
+ } else {
+ for (Standard_Integer iEdge = 0; iEdge < myNEdges; iEdge++) {
+ const Standard_Integer * anEdge = mypEdges[iEdge];
+ const Standard_Integer nNodes = anEdge[0];
+ for (Standard_Integer i = 1; i < nNodes; i++) {
+ // index is incremented by 1 for the head number in the array
+ gp_Pnt aPnt[2] = {
+ gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+0]),
+ static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+1]),
+ static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+2])),
+ gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+0]),
+ static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+1]),
+ static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+2]))
+ };
+ aPnt[0].Transform(theTrf);
+ aPnt[1].Transform(theTrf);
+ if (isFullIn) {
+ if (NIS_Triangulated::seg_box_included (theBox, aPnt) == 0) {
+ aResult = Standard_False;
+ break;
+ }
+ } else {
+ if (NIS_Triangulated::seg_box_intersect (theBox, aPnt)) {
+ aResult = Standard_True;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return aResult;
+}
+
+//=======================================================================
+//function : Intersect
+//purpose : Selection by polygon
+//=======================================================================
+
+Standard_Boolean NIS_Surface::Intersect
+ (const NCollection_List<gp_XY> &thePolygon,
+ const gp_Trsf &theTrf,
+ const Standard_Boolean isFullIn) const
+{
+ Standard_Boolean aResult (isFullIn);
+
+ if (myIsWireframe == Standard_False) {
+ if (myNTriangles > 0) {
+ for (Standard_Integer iNode = 0; iNode < myNNodes*3; iNode+=3) {
+ gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]),
+ static_cast<Standard_Real>(mypNodes[iNode+1]),
+ static_cast<Standard_Real>(mypNodes[iNode+2]));
+ theTrf.Transforms(aPnt);
+ gp_XY aP2d(aPnt.X(), aPnt.Y());
+
+ if (!NIS_Triangulated::IsIn(thePolygon, aP2d)) {
+ if (isFullIn) {
+ aResult = Standard_False;
+ break;
+ }
+ } else {
+ if (isFullIn == Standard_False) {
+ aResult = Standard_True;
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ for (Standard_Integer iEdge = 0; iEdge < myNEdges; iEdge++) {
+ const Standard_Integer * anEdge = mypEdges[iEdge];
+ const Standard_Integer nNodes = anEdge[0];
+ for (Standard_Integer i = 1; i < nNodes; i++) {
+ // index is incremented by 1 for the head number in the array
+ gp_Pnt aPnt[2] = {
+ gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+0]),
+ static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+1]),
+ static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+2])),
+ gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+0]),
+ static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+1]),
+ static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+2]))
+ };
+ aPnt[0].Transform(theTrf);
+ aPnt[1].Transform(theTrf);
+ const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
+ gp_XY(aPnt[1].X(), aPnt[1].Y()) };
+ if (isFullIn) {
+ if (NIS_Triangulated::seg_polygon_included (thePolygon, aP2d) == 0) {
+ aResult = Standard_False;
+ break;
+ }
+ } else {
+ if (NIS_Triangulated::seg_polygon_intersect (thePolygon, aP2d)) {
+ aResult = Standard_True;
+ break;
+ }
+ }
}
}
}
void NIS_Surface::computeBox ()
{
- NIS_Triangulated::ComputeBox(myBox, myNNodes, mypNodes);
+ NIS_Triangulated::ComputeBox(myBox, myNNodes, mypNodes, 3);
const Handle(NIS_SurfaceDrawer)& aDrawer =
static_cast<const Handle(NIS_SurfaceDrawer)&> (GetDrawer());
class TopoDS_Shape;
/**
- * This class describes a presentation of a meshed surface.
+ * Presentation of a meshed surface.
+ * Consists of 4 arrays: Nodes, Triangles, Normals and Edges. Normals are
+ * defined in nodes, so the number of stored normals is strictly the number of
+ * nodes. Edges is an array of pointers: each pointer starts an array of
+ * node indices that define a single edge (i.e., a polygon that can be closed or
+ * open, no matter). The first number in the edge is the number of nodes in it.
+ * <p>
+ * Instances of this class can be initialized either atomically (setting every
+ * node and triangle and edge) or from a TopoDS_Shape object. In side the
+ * TopoDS_Shape only triangulations in faces are used; edges are taken from
+ * PolygonOnTriangulation also belonging to faces.
+ * <p>
+ * This class is conceived as replacement of AIS_Shape; both wireframe and
+ * shading modes are available for dynamic switching.
*/
class NIS_Surface : public NIS_InteractiveObject
{
public:
+ enum DisplayMode {
+ Shading,
+ Wireframe
+ };
+
/**
* Constructor
*/
Standard_EXPORT NIS_Surface(const Handle_Poly_Triangulation& theTri,
- const Handle_NCollection_BaseAllocator&
+ const Handle_NCollection_BaseAllocator&
theAlloc =0L);
/**
* Constructor. Creates the presentation of all faces in 'theShape' object.
- * @aparm theShape
+ * @param theShape
* Source geometry. It should contain triangulations inside.
- * @param theAlloc
+ * @param theDeflection
+ * Absolute deflection for meshing 'theShape' if such meshing is needed.
+ * @param theAl
* Allocator used for nodes and triangles in this presentation.
*/
Standard_EXPORT NIS_Surface(const TopoDS_Shape& theShape,
-// const Standard_Real theDeflection,
- const Handle_NCollection_BaseAllocator&
- theAlloc = 0L);
+ const Standard_Real theDeflection,
+ const Handle_NCollection_BaseAllocator& theAl=0L);
/**
* Destructor
*/
Standard_EXPORT virtual ~NIS_Surface ();
+ /**
+ * Initialize the instance with a TopoDS_Shape. Used in constructor but can
+ * be called any time to redefine the geometry.
+ */
+ Standard_EXPORT void Init (const TopoDS_Shape& theShape,
+ const Standard_Real theDefl);
+
+ /**
+ * Deallocate all internal data structures.
+ */
+ Standard_EXPORT void Clear ();
+
/**
* Query the number of nodes.
*/
*/
inline Standard_Integer NTriangles () const { return myNTriangles;}
+ /**
+ * Query the number of edges for wireframe display.
+ */
+ inline Standard_Integer NEdges () const { return myNEdges; }
+
/**
* Query the node by its index.
* @return
return &mypTriangles[theIndex * 3];
}
+ /**
+ * Access to array of integers that represents an Edge.
+ * @return
+ * Pointer to array where the 0th element is the number of nodes in the edge
+ * and the elements starting from the 1st are node indices.
+ */
+ inline const Standard_Integer*
+ Edge (const Standard_Integer theIndex) const
+ {
+ return mypEdges[theIndex];
+ }
+
/**
* Query the normal vector at the given triangulation node (by index)
* @return
/**
* Create a default drawer instance.
*/
- Standard_EXPORT virtual Handle_NIS_Drawer
- DefaultDrawer () const;
+ Standard_EXPORT virtual NIS_Drawer *
+ DefaultDrawer (NIS_Drawer *) const;
/**
* Set the normal color for presentation.
Standard_EXPORT void SetPolygonOffset (const Standard_Real theValue);
/**
- * Set the transparency factor.
- * @param theValue
- * 1.0 means full transparency, 0.0 means opaque. Valid quantities are in
- * this interval.
+ * Set the display mode: Shading or Wireframe.
+ * The default mode is Shading.
*/
- Standard_EXPORT void SetTransparency (const Standard_Real theValue);
+ Standard_EXPORT void SetDisplayMode (const DisplayMode theMode);
/**
- * Intersect the InteractiveObject geometry with a line/ray.
+ * Query the current display mode: Shading or Wireframe.
+ */
+ Standard_EXPORT DisplayMode
+ GetDisplayMode () const;
+
+ /**
+ * Create a copy of theObject except its ID.
+ * @param theAll
+ * Allocator where the Dest should store its private data.
+ * @param theDest
+ * <tt>[in-out]</tt> The target object where the data are copied. If
+ * passed NULL then the target should be created.
+ */
+ Standard_EXPORT virtual void
+ Clone (const Handle_NCollection_BaseAllocator& theAll,
+ Handle_NIS_InteractiveObject& theDest) const;
+
+ /**
+ * Intersect the surface shading/wireframe geometry with a line/ray.
* @param theAxis
* The line or ray in 3D space.
* @param theOver
* on the ray. May be negative.
*/
Standard_EXPORT virtual Standard_Real
- Intersect (const gp_Ax1& theAxis,
+ Intersect (const gp_Ax1& theAxis,
const Standard_Real theOver) const;
/**
- * Intersect the InteractiveObject geometry with an oriented box.
+ * Intersect the surface shading/wireframe geometry with an oriented box.
* @param theBox
* 3D box of selection
* @param theTrf
const gp_Trsf& theTrf,
const Standard_Boolean isFull)const;
+ /**
+ * Intersect the surface shading/wireframe geometry with a selection polygon.
+ * @param thePolygon
+ * the list of vertices of a free-form closed polygon without
+ * self-intersections. The last point should not coincide with the first
+ * point of the list. Any two neighbor points should not be confused.
+ * @param theTrf
+ * Position/Orientation of the polygon.
+ * @param isFullIn
+ * True if full inclusion is required, False - if partial.
+ * @return
+ * True if the InteractiveObject geometry intersects the polygon or is
+ * inside it
+ */
+ Standard_EXPORT virtual Standard_Boolean Intersect
+ (const NCollection_List<gp_XY> &thePolygon,
+ const gp_Trsf &theTrf,
+ const Standard_Boolean isFullIn) const;
+
protected:
+ /**
+ * Allocator for method Clone().
+ */
+ Standard_EXPORT NIS_Surface (const Handle_NCollection_BaseAllocator& theAl);
+
/**
* Create a 3D bounding box of the object.
*/
gp_XYZ& theNormal) const;
private:
+ Handle_NCollection_BaseAllocator myAlloc;
//! Array of nodes in triangles
Standard_ShortReal * mypNodes;
//! Array of normals (TriNodes)
Standard_ShortReal * mypNormals;
+ //! Array of triangles (node indices)
Standard_Integer * mypTriangles;
+ //! Array of edges, each edge is an array of indices prefixed by N nodes
+ Standard_Integer ** mypEdges;
//! Number of nodes in triangles
Standard_Integer myNNodes;
Standard_Integer myNTriangles;
- Handle_NCollection_BaseAllocator myAlloc;
+ Standard_Integer myNEdges;
+ Standard_Boolean myIsWireframe;
public:
// Declaration of CASCADE RTTI
#endif
#include <GL/gl.h>
+static void setColor(GLenum theFace,
+ Quantity_Parameter * theAmbient,
+ const Standard_Real theSpecularity,
+ GLint theShininess);
+
IMPLEMENT_STANDARD_HANDLE (NIS_SurfaceDrawer, NIS_Drawer)
IMPLEMENT_STANDARD_RTTIEXT (NIS_SurfaceDrawer, NIS_Drawer)
const Quantity_Color &theHilight,
const Quantity_Color &theDynHilight)
: myBackColor (theNormal),
- myTransparency (0.0),
- myPolygonOffset (0.f)
+ myPolygonOffset (0.f),
+ myIsWireframe (Standard_False)
{
myColor[Draw_Normal] = theNormal;
+ myColor[Draw_Top] = theNormal;
myColor[Draw_Transparent] = theNormal;
myColor[Draw_Hilighted] = theHilight;
myColor[Draw_DynHilighted] = theDynHilight;
//purpose :
//=======================================================================
-void NIS_SurfaceDrawer::SetColor(const Quantity_Color &theColor,
- const Standard_Real theTransparency)
+void NIS_SurfaceDrawer::SetColor(const Quantity_Color &theColor)
{
myColor[Draw_Normal] = theColor;
+ myColor[Draw_Top] = theColor;
myColor[Draw_Transparent] = theColor;
- myTransparency = theTransparency;
}
//=======================================================================
const Handle(NIS_SurfaceDrawer)& anOther =
static_cast <const Handle(NIS_SurfaceDrawer)&> (theOther);
myColor[Draw_Normal] = anOther->myColor[Draw_Normal];
+ myColor[Draw_Top] = anOther->myColor[Draw_Top];
myColor[Draw_Transparent] = anOther->myColor[Draw_Transparent];
myColor[Draw_Hilighted] = anOther->myColor[Draw_Hilighted];
myColor[Draw_DynHilighted] = anOther->myColor[Draw_DynHilighted];
myBackColor = anOther->myBackColor;
+ myPolygonOffset = anOther->myPolygonOffset;
+ myIsWireframe = anOther->myIsWireframe;
}
}
.SquareDistance (myColor[Draw_DynHilighted]) < anEpsilon2 &&
anOther->myBackColor.SquareDistance(myBackColor) < anEpsilon2 &&
fabs(anOther->myPolygonOffset - myPolygonOffset) < 0.999 &&
- (anOther->myTransparency - myTransparency) *
- (anOther->myTransparency - myTransparency) < 0.01);
+ myIsWireframe == anOther->myIsWireframe);
if (aResult) {
// Arbitrary point for test
gp_XYZ aPnt[2] = {
//=======================================================================
void NIS_SurfaceDrawer::redraw (const DrawType theType,
- const Handle_NIS_View& theView)
+ const Handle_NIS_View& theView)
{
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
//=======================================================================
void NIS_SurfaceDrawer::BeforeDraw (const DrawType theType,
- const NIS_DrawList&)
+ const NIS_DrawList&)
{
glEnable(GL_LIGHTING);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
- glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ // glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
glEnableClientState (GL_VERTEX_ARRAY);
- glEnable(GL_COLOR_MATERIAL);
+ if (myIsWireframe == Standard_False) {
+ glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glShadeModel(GL_SMOOTH);
+ }
- Quantity_Parameter aValueCol[3];
+ Quantity_Parameter aValueCol[4] = {0., 0., 0., 1.};
Quantity_TypeOfColor bidTC (Quantity_TOC_RGB);
GLfloat aLineWidth (1.f);
GLfloat anOffset = myPolygonOffset;
+ static const GLfloat gColorN[4] = {0.f, 0.f, 0.f, 1.f};
+
switch (theType) {
case Draw_DynHilighted:
aLineWidth = 3.f;
myColor[theType].Values (aValueCol[0], aValueCol[1], aValueCol[2], bidTC);
- glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
- glColor3d (aValueCol[0], aValueCol[1], aValueCol[2]);
+ setColor(GL_FRONT_AND_BACK, &aValueCol[0], 0.1, 5);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &gColorN[0]);
glLineWidth (aLineWidth);
-// glEnable(GL_POLYGON_OFFSET_LINE);
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(1.f, -(anOffset + 11.f));
+ if (myIsWireframe == Standard_False)
+ glPolygonOffset(1.f, -(anOffset + 11.f));
return;
case Draw_Hilighted:
anOffset += 10.f;
case Draw_Normal:
+ case Draw_Top:
case Draw_Transparent:
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(1.f, -anOffset);
- glEnableClientState (GL_NORMAL_ARRAY);
+ if (myIsWireframe == Standard_False) {
+ glPolygonOffset(1.f, -anOffset);
+ glEnableClientState (GL_NORMAL_ARRAY);
+ }
myColor[theType].Values (aValueCol[0], aValueCol[1], aValueCol[2], bidTC);
aValueCol[3] = 1. - myTransparency;
+ if (theType == Draw_Transparent) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ // don't write triangles into depth test
+ glDepthMask(GL_FALSE);
+ }
break;
default:
return;
}
-// glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
- static const GLfloat gColorN[4] = {0.f, 0.f, 0.f, 1.f};
- GLfloat gColorS[4] = {
- 0.5f * static_cast<GLfloat> (1. + aValueCol[0]),
- 0.5f * static_cast<GLfloat> (1. + aValueCol[1]),
- 0.5f * static_cast<GLfloat> (1. + aValueCol[2]),
- 1.f
- };
+ // glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
if (theType == Draw_Hilighted ||
myBackColor.SquareDistance(myColor[Draw_Normal]) < 1.e-7)
{
- glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4d (aValueCol[0], aValueCol[1], aValueCol[2], aValueCol[3]);
-// glColor3d (aValueCol[0], aValueCol[1], aValueCol[2]);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &gColorS[0]);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 10);
+ setColor(GL_FRONT_AND_BACK, &aValueCol[0], 0.5, 10);
} else {
- glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4d (aValueCol[0], aValueCol[1], aValueCol[2], aValueCol[3]);
-// glColor3d (aValueCol[0], aValueCol[1], aValueCol[2]);
- glMaterialfv(GL_FRONT, GL_SPECULAR, &gColorS[0]);
+ setColor(GL_FRONT, &aValueCol[0], 0.4, 10);
myBackColor.Values (aValueCol[0], aValueCol[1], aValueCol[2], bidTC);
- glColorMaterial(GL_BACK, GL_AMBIENT_AND_DIFFUSE);
- glColor3d (aValueCol[0], aValueCol[1], aValueCol[2]);
- glMateriali(GL_FRONT, GL_SHININESS, 10);
- gColorS[0] = 0.9f * static_cast<GLfloat> (aValueCol[0]) + 0.1f;
- gColorS[1] = 0.9f * static_cast<GLfloat> (aValueCol[1]) + 0.1f;
- gColorS[2] = 0.9f * static_cast<GLfloat> (aValueCol[2]) + 0.1f;
- glMaterialfv(GL_BACK, GL_SPECULAR, &gColorS[0]);
- glMateriali(GL_BACK, GL_SHININESS, 5);
+ setColor(GL_BACK, &aValueCol[0], 0.8, 5);
}
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &gColorN[0]);
-
- if (theType == Draw_Hilighted)
- glColor3d(0.9, 0.9, 0.9); // for the polygon presentation
-
glLineWidth (aLineWidth);
- glShadeModel(GL_SMOOTH);
}
//=======================================================================
//=======================================================================
void NIS_SurfaceDrawer::AfterDraw (const DrawType theType,
- const NIS_DrawList&)
+ const NIS_DrawList&)
{
- // Reset transformation matrix.
-// glPopMatrix();
-
- glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHTING);
glDisableClientState(GL_VERTEX_ARRAY);
switch (theType) {
- case Draw_DynHilighted:
-// glDisable(GL_POLYGON_OFFSET_LINE);
- break;
+ case Draw_Transparent:
+ glDisable(GL_BLEND);
+ glDepthMask(GL_TRUE);
case Draw_Hilighted:
case Draw_Normal:
- case Draw_Transparent:
- glDisable(GL_POLYGON_OFFSET_FILL);
- glDisableClientState(GL_NORMAL_ARRAY);
+ case Draw_Top:
+ if (myIsWireframe == Standard_False)
+ glDisableClientState(GL_NORMAL_ARRAY);
default:;
}
+ if (myIsWireframe == Standard_False)
+ glDisable(GL_POLYGON_OFFSET_FILL);
}
//=======================================================================
//=======================================================================
void NIS_SurfaceDrawer::Draw (const Handle_NIS_InteractiveObject& theObj,
- const DrawType theType,
- const NIS_DrawList&)
+ const DrawType theType,
+ const NIS_DrawList&)
{
// Assertion for the type of the drawn object
#ifdef _DEBUG
static const Handle(Standard_Type) ThisType = STANDARD_TYPE(NIS_Surface);
Standard_ProgramError_Raise_if (theObj->IsKind(ThisType) == Standard_False,
- "NIS_Surface::Draw: "
- "irrelevant object type");
+ "NIS_Surface::Draw: irrelevant object type");
#endif
const NIS_Surface * pObject =
static_cast <const NIS_Surface *> (theObj.operator->());
- if (pObject->NTriangles())
+ glVertexPointer (3, GL_FLOAT, 0, pObject->Node(0));
+
+ // In Highlited mode the shape must be shown as wireframe
+ Standard_Boolean isWireframe(myIsWireframe);
+ if (isWireframe == Standard_False && theType == Draw_DynHilighted)
+ if (pObject->NEdges() > 0)
+ isWireframe = Standard_True;
+
+ if (isWireframe)
{
- glVertexPointer (3, GL_FLOAT, 0, pObject->Node(0));
- glNormalPointer (GL_FLOAT, 0, pObject->Normal(0));
- glDrawElements (GL_TRIANGLES, pObject->NTriangles()*3,
- GL_UNSIGNED_INT, pObject->Triangle(0));
+ for (Standard_Integer i = 0; i < pObject->NEdges(); i++) {
+ const GLint * pEdge = static_cast<const GLint *> (pObject->Edge(i));
+ glDrawElements (GL_LINE_STRIP, pEdge[0], GL_UNSIGNED_INT, &pEdge[1]);
+ }
+ } else {
+ if (pObject->NTriangles()) {
+ if (theType != Draw_DynHilighted)
+ glNormalPointer (GL_FLOAT, 0, pObject->Normal(0));
+ glDrawElements (GL_TRIANGLES, pObject->NTriangles()*3,
+ GL_UNSIGNED_INT, pObject->Triangle(0));
+ }
}
}
+
+//=======================================================================
+//function : setColor
+//purpose :
+//=======================================================================
+
+void setColor(GLenum theFace,
+ Quantity_Parameter * theAmbient,
+ const Standard_Real theSpecularity,
+ GLint theShininess)
+{
+ GLfloat aSpec = static_cast<GLfloat>(theSpecularity);
+ GLfloat aValueCol[4] = {
+ GLfloat(theAmbient[0]),
+ GLfloat(theAmbient[1]),
+ GLfloat(theAmbient[2]),
+ GLfloat(theAmbient[3])
+ };
+ glMaterialfv(theFace, GL_AMBIENT_AND_DIFFUSE, &aValueCol[0]);
+ aValueCol[0] = aSpec * (aValueCol[0] - 1.f) + 1.f;
+ aValueCol[1] = aSpec * (aValueCol[1] - 1.f) + 1.f;
+ aValueCol[2] = aSpec * (aValueCol[2] - 1.f) + 1.f;
+ aValueCol[3] = 1.f;
+ glMaterialfv(theFace, GL_SPECULAR, &aValueCol[0]);
+ glMateriali(theFace, GL_SHININESS, theShininess);
+}
+
*/
Standard_EXPORT NIS_SurfaceDrawer(const Quantity_Color &theNormal,
const Quantity_Color &theHilight
- = Quantity_NOC_GRAY80,
+ = Quantity_NOC_GRAY65,
const Quantity_Color &theDynHilight
= Quantity_NOC_CYAN1);
/**
- * Sets the color and transparency of the drawer.
+ * Sets the color of the drawer.
*/
- Standard_EXPORT void SetColor (const Quantity_Color &theColor,
- const Standard_Real theTransparency);
+ Standard_EXPORT void SetColor (const Quantity_Color &theColor);
/**
* Define the color used for the back side of rendered triangles.
*/
inline void SetPolygonOffset (const Standard_Real theOffset)
{
- myPolygonOffset = static_cast<const Standard_ShortReal>(theOffset);
+ myPolygonOffset = static_cast<Standard_ShortReal>(theOffset);
}
/**
*/
inline Standard_Real GetPolygonOffset () const
{
- return static_cast<const Standard_Real>(myPolygonOffset);
+ return static_cast<Standard_Real>(myPolygonOffset);
}
-
/**
* Copy the relevant information from another instance of Drawer.
* raises exception if theOther has incompatible type (test IsKind).
private:
- Quantity_Color myColor[4];
+ Quantity_Color myColor[5];
Quantity_Color myBackColor;
gp_Trsf myTrsf;
- Standard_Real myTransparency;
Standard_ShortReal myPolygonOffset;
+ Standard_Boolean myIsWireframe;
friend class NIS_Surface;
IMPLEMENT_STANDARD_HANDLE (NIS_Triangulated, NIS_InteractiveObject)
IMPLEMENT_STANDARD_RTTIEXT (NIS_Triangulated, NIS_InteractiveObject)
-inline Handle(NIS_TriangulatedDrawer) defaultDrawer ()
+static Standard_Real aTolConf = Precision::Confusion() * 0.0001;
+
+/**
+ * Checking the given value if it is considerably greater than zero.
+ */
+static inline Standard_Boolean IsPositive (const Standard_Real theVal)
{
- return new NIS_TriangulatedDrawer (Quantity_NOC_RED);
+ return (theVal > aTolConf);
+}
+
+/**
+ * Compute the size in bytes of an index array.
+ */
+static inline Standard_Size NBytesInd (const Standard_Integer nInd,
+ const unsigned int theIndType)
+{
+ Standard_Size nBytes = static_cast<Standard_Size>(nInd);
+ if (theIndType) {
+ nBytes *= 2;
+ if (theIndType > 1u)
+ nBytes *= 2;
+ }
+ return nBytes;
}
//=======================================================================
NIS_Triangulated::NIS_Triangulated
(const Standard_Integer nNodes,
+ const Standard_Boolean is2D,
const Handle(NCollection_BaseAllocator)& theAlloc)
- : myType (Type_None),
+ : myAlloc (0L),
+ myType (Type_None),
mypNodes (0L),
mypTriangles (0L),
mypLines (0L),
mypPolygons (0L),
myNNodes (0),
myNTriangles (0),
- myNPolygons (0),
myNLineNodes (0),
- myAlloc (0L),
- myIsDrawPolygons (Standard_False)
+ myNPolygons (0u),
+ myIsDrawPolygons (Standard_False),
+ myIsCloned (Standard_False),
+ myIndexType (2u),
+ myNodeCoord (is2D ? 2 : 3),
+ myPolygonType (static_cast<unsigned int>(Polygon_Default))
{
if (theAlloc.IsNull())
mypLines = 0L;
}
if (myNPolygons) {
- for (Standard_Integer i = 0; i < myNPolygons; i++)
+ for (unsigned int i = 0; i < myNPolygons; i++)
myAlloc->Free(mypPolygons[i]);
myAlloc->Free(mypPolygons);
- myNPolygons = 0;
+ myNPolygons = 0u;
mypPolygons = 0L;
}
myType = Type_None;
myIsDrawPolygons = Standard_False;
+ myPolygonType = static_cast<unsigned int>(Polygon_Default);
+ if (GetDrawer().IsNull() == Standard_False) {
+ GetDrawer()->SetUpdated(NIS_Drawer::Draw_Normal,
+ NIS_Drawer::Draw_Top,
+ NIS_Drawer::Draw_Transparent,
+ NIS_Drawer::Draw_Hilighted);
+ }
}
//=======================================================================
else {
myType |= Type_Polygons;
if (myNPolygons) {
- for (Standard_Integer i = 0; i < myNPolygons; i++)
+ for (unsigned int i = 0; i < myNPolygons; i++)
myAlloc->Free(mypPolygons[i]);
myAlloc->Free(mypPolygons);
}
- myNPolygons = nPolygons;
+ myNPolygons = static_cast<unsigned int>(nPolygons);
mypPolygons = static_cast<Standard_Integer **>
(myAlloc->Allocate(sizeof(Standard_Integer *)*nPolygons));
allocateNodes (nNodes);
myType |= Type_Triangulation;
if (myNTriangles)
myAlloc->Free(mypTriangles);
- myNTriangles = nTri;
- mypTriangles = static_cast<Standard_Integer *>
- (myAlloc->Allocate(sizeof(Standard_Integer)*3*nTri));
allocateNodes (nNodes);
+
+ myNTriangles = nTri;
+ const Standard_Size nBytes = NBytesInd(3 * nTri, myIndexType);
+ mypTriangles = static_cast<Standard_Integer *> (myAlloc->Allocate(nBytes));
}
}
if (myNLineNodes)
myAlloc->Free(mypLines);
myType &= ~Type_Segments;
- myNLineNodes = nPoints;
- mypLines = static_cast<Standard_Integer *>
- (myAlloc->Allocate(sizeof(Standard_Integer)*nPoints));
allocateNodes (nNodes);
+
+ myNLineNodes = nPoints;
+ const Standard_Size nBytes = NBytesInd(nPoints, myIndexType);
+ mypLines = static_cast<Standard_Integer *> (myAlloc->Allocate(nBytes));
}
}
if (myNLineNodes)
myAlloc->Free(mypLines);
myType &= ~(Type_Line | Type_Loop);
- myNLineNodes = nSegments*2;
- mypLines = static_cast<Standard_Integer *>
- (myAlloc->Allocate(sizeof(Standard_Integer)*myNLineNodes));
allocateNodes (nNodes);
+
+ myNLineNodes = nSegments*2;
+ const Standard_Size nBytes = NBytesInd(myNLineNodes, myIndexType);
+ mypLines = static_cast<Standard_Integer *> (myAlloc->Allocate(nBytes));
}
}
//purpose :
//=======================================================================
-Handle(NIS_Drawer) NIS_Triangulated::DefaultDrawer () const
+NIS_Drawer * NIS_Triangulated::DefaultDrawer (NIS_Drawer * theDrawer) const
{
- return defaultDrawer();
+ NIS_TriangulatedDrawer * aDrawer =
+ theDrawer ? static_cast<NIS_TriangulatedDrawer *>(theDrawer)
+ : new NIS_TriangulatedDrawer (Quantity_NOC_RED);
+ aDrawer->myIsDrawPolygons = myIsDrawPolygons;
+ aDrawer->myPolygonType = myPolygonType;
+ return aDrawer;
}
//=======================================================================
void NIS_Triangulated::ComputeBox (Bnd_B3f& theBox,
const Standard_Integer nNodes,
- const Standard_ShortReal* pNodes)
+ const Standard_ShortReal* pNodes,
+ const Standard_Integer nCoord)
{
theBox.Clear();
if (nNodes > 0) {
Standard_ShortReal aBox[6] = {
- pNodes[0], pNodes[1], pNodes[2],
- pNodes[0], pNodes[1], pNodes[2]
+ pNodes[0], pNodes[1], 0.,
+ pNodes[0], pNodes[1], 0.
};
+ if (nCoord > 2) {
+ aBox[2] = pNodes[2];
+ aBox[5] = pNodes[2];
+ }
for (Standard_Integer i = 1; i < nNodes; i++) {
- const Standard_ShortReal * pNode = &pNodes[i*3];
+ const Standard_ShortReal * pNode = &pNodes[i * nCoord];
if (aBox[0] > pNode[0])
aBox[0] = pNode[0];
else if (aBox[3] < pNode[0])
aBox[1] = pNode[1];
else if (aBox[4] < pNode[1])
aBox[4] = pNode[1];
- if (aBox[2] > pNode[2])
- aBox[2] = pNode[2];
- else if (aBox[5] < pNode[2])
- aBox[5] = pNode[2];
+ if (nCoord > 2) {
+ if (aBox[2] > pNode[2])
+ aBox[2] = pNode[2];
+ else if (aBox[5] < pNode[2])
+ aBox[5] = pNode[2];
+ }
}
theBox.Add (gp_XYZ (Standard_Real(aBox[0]),
Standard_Real(aBox[1]),
void NIS_Triangulated::computeBox ()
{
- ComputeBox (myBox, myNNodes, mypNodes);
+ ComputeBox (myBox, myNNodes, mypNodes, myNodeCoord);
}
//=======================================================================
{
if (ind >= myNNodes)
Standard_OutOfRange::Raise ("NIS_Triangulated::SetNode");
- Standard_ShortReal * pNode = &mypNodes[3*ind];
+ Standard_ShortReal * pNode = &mypNodes[myNodeCoord * ind];
pNode[0] = Standard_ShortReal(thePnt.X());
pNode[1] = Standard_ShortReal(thePnt.Y());
- pNode[2] = Standard_ShortReal(thePnt.Z());
+ if (myNodeCoord > 2)
+ pNode[2] = Standard_ShortReal(thePnt.Z());
+ setIsUpdateBox(Standard_True);
}
//=======================================================================
{
if (ind >= myNNodes)
Standard_OutOfRange::Raise ("NIS_Triangulated::SetNode");
- Standard_ShortReal * pNode = &mypNodes[3*ind];
+ Standard_ShortReal * pNode = &mypNodes[myNodeCoord * ind];
pNode[0] = Standard_ShortReal(thePnt.X());
pNode[1] = Standard_ShortReal(thePnt.Y());
- pNode[2] = 0.f;
+ if (myNodeCoord > 2)
+ pNode[2] = 0.f;
+ setIsUpdateBox(Standard_True);
}
//=======================================================================
{
if (ind >= myNTriangles)
Standard_OutOfRange::Raise ("NIS_Triangulated::SetTriangle");
- Standard_Integer * pTri = &mypTriangles[3*ind];
- pTri[0] = iNode0;
- pTri[1] = iNode1;
- pTri[2] = iNode2;
+ switch (myIndexType) {
+ case 0: // 8bit
+ {
+ unsigned char * pTri =
+ reinterpret_cast<unsigned char *>(mypTriangles) + (3 * ind);
+ pTri[0] = static_cast<unsigned char>(iNode0);
+ pTri[1] = static_cast<unsigned char>(iNode1);
+ pTri[2] = static_cast<unsigned char>(iNode2);
+ }
+ break;
+ case 1: // 16bit
+ {
+ unsigned short * pTri =
+ reinterpret_cast<unsigned short *>(mypTriangles) + (3 * ind);
+ pTri[0] = static_cast<unsigned short>(iNode0);
+ pTri[1] = static_cast<unsigned short>(iNode1);
+ pTri[2] = static_cast<unsigned short>(iNode2);
+ }
+ break;
+ default: // 32bit
+ {
+ Standard_Integer * pTri = &mypTriangles[3*ind];
+ pTri[0] = iNode0;
+ pTri[1] = iNode1;
+ pTri[2] = iNode2;
+ }
+ }
}
//=======================================================================
{
if (ind >= myNLineNodes)
Standard_OutOfRange::Raise ("NIS_Triangulated::SetTriangle");
- mypLines[ind] = iNode;
+ switch (myIndexType) {
+ case 0: // 8bit
+ {
+ unsigned char * pInd =
+ reinterpret_cast<unsigned char *>(mypLines) + ind;
+ pInd[0] = static_cast<unsigned char>(iNode);
+ }
+ break;
+ case 1: // 16bit
+ {
+ unsigned short * pInd =
+ reinterpret_cast<unsigned short *>(mypLines) + ind;
+ pInd[0] = static_cast<unsigned short>(iNode);
+ }
+ break;
+ default: // 32bit
+ mypLines[ind] = iNode;
+ }
+}
+
+//=======================================================================
+//function : SetPolygonNode
+//purpose :
+//=======================================================================
+
+void NIS_Triangulated::SetPolygonNode (const Standard_Integer indPoly,
+ const Standard_Integer ind,
+ const Standard_Integer iNode)
+{
+ if (indPoly >= static_cast<Standard_Integer>(myNPolygons))
+ Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
+
+ Standard_Integer * aPoly = mypPolygons[indPoly];
+ switch (myIndexType) {
+ case 0: // 8bit
+ {
+ unsigned char aNNode = * (reinterpret_cast<unsigned char *>(aPoly));
+ if (static_cast<unsigned char>(ind) >= aNNode)
+ Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
+
+ unsigned char * pInd =
+ reinterpret_cast<unsigned char *>(aPoly) + ind + 1;
+ pInd[0] = static_cast<unsigned char>(iNode);
+ }
+ break;
+ case 1: // 16bit
+ {
+ unsigned short aNNode = * (reinterpret_cast<unsigned short *>(aPoly));
+ if (static_cast<unsigned short>(ind) >= aNNode)
+ Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
+
+ unsigned short * pInd =
+ reinterpret_cast<unsigned short *>(aPoly) + ind + 1;
+ pInd[0] = static_cast<unsigned short>(iNode);
+ }
+ break;
+ default: // 32bit
+ if (ind >= aPoly[0])
+ Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
+ aPoly[ind + 1] = iNode;
+ }
+}
+
+//=======================================================================
+//function : NPolygonNodes
+//purpose :
+//=======================================================================
+Standard_Integer NIS_Triangulated::NPolygonNodes
+ (const Standard_Integer indPoly)const
+{
+ Standard_Integer aResult(0);
+ if (indPoly >= static_cast<Standard_Integer>(myNPolygons))
+ Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
+ Standard_Integer * aPoly = mypPolygons[indPoly];
+ switch (myIndexType) {
+ case 0: // 8bit
+ {
+ unsigned char aNNode = * (reinterpret_cast<unsigned char *>(aPoly));
+ aResult = static_cast<Standard_Integer>(aNNode);
+ }
+ break;
+ case 1: // 16bit
+ {
+ unsigned short aNNode = * (reinterpret_cast<unsigned short *>(aPoly));
+ aResult = static_cast<Standard_Integer>(aNNode);
+ }
+ break;
+ default: // 32bit
+ {
+ aResult = aPoly[0];
+ }
+ }
+ return aResult;
+}
+
+//=======================================================================
+//function : PolygonNode
+//purpose :
+//=======================================================================
+
+Standard_Integer NIS_Triangulated::PolygonNode
+ (const Standard_Integer indPoly,
+ const Standard_Integer ind)const
+{
+ Standard_Integer aResult(-1);
+ if (indPoly >= static_cast<Standard_Integer>(myNPolygons))
+ Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
+ const Standard_Integer * aPoly = mypPolygons[indPoly];
+ switch (myIndexType) {
+ case 0: // 8bit
+ {
+ const unsigned char * pInd =
+ reinterpret_cast<const unsigned char *>(aPoly);
+ if (static_cast<unsigned char>(ind) >= pInd[0])
+ Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
+
+ aResult = static_cast<Standard_Integer>(pInd[ind + 1]);
+ }
+ break;
+ case 1: // 16bit
+ {
+ const unsigned short * pInd =
+ reinterpret_cast<const unsigned short *>(aPoly);
+ if (static_cast<unsigned short>(ind) >= pInd[0])
+ Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
+
+ aResult = static_cast<Standard_Integer>(pInd[ind + 1]);
+ }
+ break;
+ default: // 32bit
+ {
+ if (ind >= aPoly[0])
+ Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
+ aResult = aPoly[ind + 1];
+ }
+ }
+ return aResult;
}
//=======================================================================
//purpose :
//=======================================================================
-Standard_Integer* NIS_Triangulated::SetPolygon (const Standard_Integer ind,
- const Standard_Integer theSz)
+void NIS_Triangulated::SetPolygon (const Standard_Integer ind,
+ const Standard_Integer theSz)
{
- if (ind >= myNPolygons)
+ if (ind >= static_cast<Standard_Integer>(myNPolygons))
Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygon");
- Standard_Integer * anArray = static_cast <Standard_Integer *>
- (myAlloc->Allocate (sizeof(Standard_Integer) * (theSz+1)));
- mypPolygons[ind] = anArray;
- anArray[0] = theSz;
- return &anArray[1];
+ switch (myIndexType) {
+ case 0: // 8bit
+ {
+ unsigned char * anArray = static_cast <unsigned char *>
+ (myAlloc->Allocate (sizeof(unsigned char) * (theSz+1)));
+ mypPolygons[ind] = reinterpret_cast<Standard_Integer *> (anArray);
+ anArray[0] = static_cast<unsigned char>(theSz);
+ }
+ break;
+ case 1: // 16bit
+ {
+ unsigned short * anArray = static_cast <unsigned short *>
+ (myAlloc->Allocate (sizeof(unsigned short) * (theSz+1)));
+ mypPolygons[ind] = reinterpret_cast<Standard_Integer *> (anArray);
+ anArray[0] = static_cast<unsigned short>(theSz);
+ }
+ break;
+ default: // 32bit
+ {
+ Standard_Integer * anArray = static_cast <Standard_Integer *>
+ (myAlloc->Allocate (sizeof(Standard_Integer) * (theSz+1)));
+ mypPolygons[ind] = anArray;
+ anArray[0] = theSz;
+ }
+ }
}
//=======================================================================
//purpose :
//=======================================================================
-void NIS_Triangulated::SetDrawPolygons (const Standard_Boolean isDrawPolygons,
- const Standard_Boolean isUpdateViews)
+void NIS_Triangulated::SetDrawPolygons (const Standard_Boolean isDrawPolygons)
{
- if (myIsDrawPolygons != isDrawPolygons) {
- Handle(NIS_TriangulatedDrawer) aDrawer = defaultDrawer();
- aDrawer->Assign (GetDrawer());
- aDrawer->myIsDrawPolygons = isDrawPolygons;
- SetDrawer (aDrawer);
+ if (GetDrawer().IsNull())
myIsDrawPolygons = isDrawPolygons;
+ else {
+ if (myIsDrawPolygons != isDrawPolygons) {
+ const Handle(NIS_TriangulatedDrawer) aDrawer =
+ static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
+ aDrawer->Assign (GetDrawer());
+ aDrawer->myIsDrawPolygons = isDrawPolygons;
+ SetDrawer (aDrawer);
+ myIsDrawPolygons = isDrawPolygons;
+ }
+ }
+}
+
+//=======================================================================
+//function : SetPolygonType
+//purpose : Set the type of polygon rendering
+//=======================================================================
+
+void NIS_Triangulated::SetPolygonType
+ (const NIS_Triangulated::PolygonType theType)
+{
+ if (GetDrawer().IsNull())
+ myPolygonType = static_cast<unsigned int>(theType);
+ else {
+ if (myPolygonType != static_cast<unsigned int>(theType)) {
+ const Handle(NIS_TriangulatedDrawer) aDrawer =
+ static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
+ aDrawer->Assign (GetDrawer());
+ aDrawer->myPolygonType = theType;
+ SetDrawer (aDrawer);
+ myPolygonType = static_cast<unsigned int>(theType);
+ }
}
- if (isUpdateViews)
- GetDrawer()->GetContext()->UpdateViews();
}
//=======================================================================
//purpose : Set the normal color for presentation.
//=======================================================================
-void NIS_Triangulated::SetColor (const Quantity_Color& theColor,
- const Standard_Boolean isUpdateViews)
+void NIS_Triangulated::SetColor (const Quantity_Color& theColor)
{
- Handle(NIS_TriangulatedDrawer) aDrawer = defaultDrawer();
+ const Handle(NIS_TriangulatedDrawer) aDrawer =
+ static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
aDrawer->Assign (GetDrawer());
aDrawer->myColor[NIS_Drawer::Draw_Normal] = theColor;
+ aDrawer->myColor[NIS_Drawer::Draw_Top] = theColor;
aDrawer->myColor[NIS_Drawer::Draw_Transparent] = theColor;
SetDrawer (aDrawer);
- if (isUpdateViews)
- GetDrawer()->GetContext()->UpdateViews();
}
//=======================================================================
//purpose : Get Normal, Transparent or Hilighted color of the presentation.
//=======================================================================
-Quantity_Color NIS_Triangulated::GetColor (const NIS_Drawer::DrawType theDrawType) const
+Quantity_Color NIS_Triangulated::GetColor
+ (const NIS_Drawer::DrawType theDrawType) const
{
- Handle(NIS_TriangulatedDrawer) aDrawer =
- Handle(NIS_TriangulatedDrawer)::DownCast( GetDrawer() );
- if (aDrawer.IsNull() == Standard_False)
- {
- return aDrawer->myColor[theDrawType];
- }
- return Quantity_Color(); // return null color object
+ Handle(NIS_TriangulatedDrawer) aDrawer =
+ Handle(NIS_TriangulatedDrawer)::DownCast( GetDrawer() );
+ if (aDrawer.IsNull() == Standard_False)
+ {
+ return aDrawer->myColor[theDrawType];
+ }
+ return Quantity_Color(); // return null color object
}
//=======================================================================
//purpose : Set the color for hilighted presentation.
//=======================================================================
-void NIS_Triangulated::SetHilightColor (const Quantity_Color& theColor,
- const Standard_Boolean isUpdateViews)
+void NIS_Triangulated::SetHilightColor (const Quantity_Color& theColor)
{
- Handle(NIS_TriangulatedDrawer) aDrawer = defaultDrawer();
+ const Handle(NIS_TriangulatedDrawer) aDrawer =
+ static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
aDrawer->Assign (GetDrawer());
aDrawer->myColor[NIS_Drawer::Draw_Hilighted] = theColor;
SetDrawer (aDrawer);
- if (isUpdateViews)
- GetDrawer()->GetContext()->UpdateViews();
}
//=======================================================================
//purpose : Set the color for dynamic hilight presentation.
//=======================================================================
-void NIS_Triangulated::SetDynHilightColor(const Quantity_Color& theColor,
- const Standard_Boolean isUpdateViews)
+void NIS_Triangulated::SetDynHilightColor(const Quantity_Color& theColor)
{
- Handle(NIS_TriangulatedDrawer) aDrawer = defaultDrawer();
+ const Handle(NIS_TriangulatedDrawer) aDrawer =
+ static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
aDrawer->Assign (GetDrawer());
aDrawer->myColor[NIS_Drawer::Draw_DynHilighted] = theColor;
SetDrawer (aDrawer);
- if (isUpdateViews)
- GetDrawer()->GetContext()->UpdateViews();
}
//=======================================================================
//purpose : Set the width of line presentations in pixels.
//=======================================================================
-void NIS_Triangulated::SetLineWidth (const Standard_Real theWidth,
- const Standard_Boolean isUpdateViews)
+void NIS_Triangulated::SetLineWidth (const Standard_Real theWidth)
{
- Handle(NIS_TriangulatedDrawer) aDrawer = defaultDrawer();
+ const Handle(NIS_TriangulatedDrawer) aDrawer =
+ static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
aDrawer->Assign (GetDrawer());
aDrawer->myLineWidth = (Standard_ShortReal) theWidth;
SetDrawer (aDrawer);
- if (isUpdateViews)
- GetDrawer()->GetContext()->UpdateViews();
+}
+
+//=======================================================================
+//function : Clone
+//purpose :
+//=======================================================================
+
+void NIS_Triangulated::Clone (const Handle_NCollection_BaseAllocator& theAlloc,
+ Handle_NIS_InteractiveObject& theDest) const
+{
+ Handle(NIS_Triangulated) aNewObj;
+ if (theDest.IsNull()) {
+ aNewObj = new (theAlloc) NIS_Triangulated(myNNodes, myNodeCoord == 2,
+ theAlloc);
+ aNewObj->myIsCloned = Standard_True;
+ theDest = aNewObj;
+ } else {
+ aNewObj = reinterpret_cast<NIS_Triangulated*> (theDest.operator->());
+ aNewObj->myAlloc = theAlloc.operator->();
+ aNewObj->myNNodes = 0;
+ aNewObj->allocateNodes(myNNodes);
+ }
+ NIS_InteractiveObject::Clone(theAlloc, theDest);
+ if (myNNodes > 0)
+ {
+ // copy nodes
+ memcpy(aNewObj->mypNodes, mypNodes,
+ myNNodes * myNodeCoord * sizeof(Standard_ShortReal));
+ // copy triangles
+ aNewObj->myNTriangles = myNTriangles;
+ if (myNTriangles) {
+ const Standard_Size nBytes = NBytesInd(3 * myNTriangles, myIndexType);
+ aNewObj->mypTriangles = static_cast<Standard_Integer *>
+ (theAlloc->Allocate(nBytes));
+ memcpy(aNewObj->mypTriangles, mypTriangles, nBytes);
+ }
+ // copy lines/segments
+ aNewObj->myNLineNodes = myNLineNodes;
+ if (myNLineNodes) {
+ const Standard_Size nBytes = NBytesInd(myNLineNodes, myIndexType);
+ aNewObj->mypLines = static_cast<Standard_Integer *>
+ (theAlloc->Allocate(nBytes));
+ memcpy(aNewObj->mypLines, mypLines, nBytes);
+ }
+ // copy polygons
+ aNewObj->myNPolygons = myNPolygons;
+ if (myNPolygons) {
+ const Standard_Size nBytes = sizeof(Standard_Integer *)*myNPolygons;
+ aNewObj->mypPolygons = static_cast<Standard_Integer **>
+ (theAlloc->Allocate(nBytes));
+ for (unsigned int i = 0; i < myNPolygons; i++) {
+ const Standard_Integer nNodes = NPolygonNodes(i);
+ const Standard_Size nBytes = NBytesInd(nNodes+1, myIndexType);
+ aNewObj->mypPolygons[i] = static_cast <Standard_Integer *>
+ (theAlloc->Allocate (nBytes));
+ memcpy(aNewObj->mypPolygons[i], mypPolygons[i], nBytes);
+ }
+ }
+ }
+ aNewObj->myType = myType;
+ aNewObj->myIsDrawPolygons = myIsDrawPolygons;
+ aNewObj->myIndexType = myIndexType;
+ aNewObj->myPolygonType = myPolygonType;
+}
+
+//=======================================================================
+//function : Delete
+//purpose :
+//=======================================================================
+
+void NIS_Triangulated::Delete () const
+{
+ if (myIsCloned == Standard_False)
+ Standard_Transient::Delete();
+ else {
+ // Call the destructor and then release the memory occupied by the instance.
+ // This is required when the NIS_Triangulated instance is allocated in
+ // the same allocator as its internal arrays.
+ NIS_Triangulated* pThis = const_cast<NIS_Triangulated*>(this);
+ pThis->~NIS_Triangulated();
+ myAlloc->Free(pThis);
+ }
}
//=======================================================================
{
Standard_Boolean aResult (isFullIn);
- if ((myType & Type_Triangulation) && myIsDrawPolygons == Standard_False)
- for (Standard_Integer iNode = 0; iNode < myNNodes*3; iNode+=3) {
- gp_XYZ aPnt ((Standard_Real)mypNodes[iNode+0],
- (Standard_Real)mypNodes[iNode+1],
- (Standard_Real)mypNodes[iNode+2]);
- theTrf.Transforms(aPnt);
+ if ((myType & Type_Triangulation) && myIsDrawPolygons == Standard_False) {
+ unsigned int iNode = 0;
+ for (; iNode < myNNodes * myNodeCoord; iNode += myNodeCoord)
+ {
+ gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]),
+ static_cast<Standard_Real>(mypNodes[iNode+1]), 0.);
+ if (myNodeCoord > 2)
+ aPnt.SetZ (static_cast<Standard_Real>(mypNodes[iNode+2]));
+ theTrf.Transforms (aPnt);
if (theBox.IsOut (aPnt)) {
if (isFullIn) {
aResult = Standard_False;
}
}
}
+ }
if (aResult == isFullIn) {
if (myType & Type_Segments) {
for (Standard_Integer i = 0; i < myNLineNodes; i+=2) {
const gp_Pnt aPnt[2] = {
- gp_Pnt (mypNodes[3*mypLines[i+0]+0],
- mypNodes[3*mypLines[i+0]+1],
- mypNodes[3*mypLines[i+0]+2]).Transformed(theTrf),
- gp_Pnt (mypNodes[3*mypLines[i+1]+0],
- mypNodes[3*mypLines[i+1]+1],
- mypNodes[3*mypLines[i+1]+2]).Transformed(theTrf)
+ nodeAtInd(mypLines, i+0).Transformed(theTrf),
+ nodeAtInd(mypLines, i+1).Transformed(theTrf)
};
if (isFullIn) {
if (seg_box_included (theBox, aPnt) == 0) {
} else if (myType & Type_Line) {
for (Standard_Integer i = 1; i < myNLineNodes; i++) {
const gp_Pnt aPnt[2] = {
- gp_Pnt (mypNodes[3*mypLines[i-1]+0],
- mypNodes[3*mypLines[i-1]+1],
- mypNodes[3*mypLines[i-1]+2]).Transformed(theTrf),
- gp_Pnt (mypNodes[3*mypLines[i+0]+0],
- mypNodes[3*mypLines[i+0]+1],
- mypNodes[3*mypLines[i+0]+2]).Transformed(theTrf)
+ nodeAtInd(mypLines, i-1).Transformed(theTrf),
+ nodeAtInd(mypLines, i+0).Transformed(theTrf)
};
if (isFullIn) {
if (seg_box_included (theBox, aPnt) == 0) {
}
if (aResult == isFullIn && (myType & Type_Loop)) {
const gp_Pnt aPntLast[2] = {
- gp_Pnt (mypNodes[3*mypLines[myNLineNodes-1]+0],
- mypNodes[3*mypLines[myNLineNodes-1]+1],
- mypNodes[3*mypLines[myNLineNodes-1]+2]).Transformed(theTrf),
- gp_Pnt (mypNodes[3*mypLines[0]+0],
- mypNodes[3*mypLines[0]+1],
- mypNodes[3*mypLines[0]+2]).Transformed(theTrf)
+ nodeAtInd(mypLines, myNLineNodes-1).Transformed(theTrf),
+ nodeAtInd(mypLines, 0).Transformed(theTrf)
};
if (isFullIn) {
if (seg_box_included (theBox, aPntLast) == 0)
}
}
} else if ((myType & Type_Polygons) && myIsDrawPolygons) {
- for (Standard_Integer iPoly = 0; iPoly < myNPolygons; iPoly++) {
- const Standard_Integer nNodes = * mypPolygons[iPoly];
- const Standard_Integer * arrNodes = mypPolygons[iPoly] + 1;
+ for (unsigned int iPoly = 0; iPoly < myNPolygons; iPoly++) {
+ const Standard_Integer * aPoly = mypPolygons[iPoly];
+ const Standard_Integer nNodes = NPolygonNodes(iPoly);
for (Standard_Integer i = 1; i < nNodes; i++) {
+ // index is incremented by 1 for the head number in the array
const gp_Pnt aPnt[2] = {
- gp_Pnt (mypNodes[3*arrNodes[i-1]+0],
- mypNodes[3*arrNodes[i-1]+1],
- mypNodes[3*arrNodes[i-1]+2]).Transformed(theTrf),
- gp_Pnt (mypNodes[3*arrNodes[i+0]+0],
- mypNodes[3*arrNodes[i+0]+1],
- mypNodes[3*arrNodes[i+0]+2]).Transformed(theTrf)
+ nodeAtInd(aPoly, i+0).Transformed(theTrf),
+ nodeAtInd(aPoly, i+1).Transformed(theTrf)
};
if (isFullIn) {
if (seg_box_included (theBox, aPnt) == 0) {
}
if (aResult == isFullIn) {
const gp_Pnt aPntLast[2] = {
- gp_Pnt (mypNodes[3*arrNodes[nNodes-1]+0],
- mypNodes[3*arrNodes[nNodes-1]+1],
- mypNodes[3*arrNodes[nNodes-1]+2]).Transformed(theTrf),
- gp_Pnt (mypNodes[3*arrNodes[0]+0],
- mypNodes[3*arrNodes[0]+1],
- mypNodes[3*arrNodes[0]+2]).Transformed(theTrf)
+ nodeAtInd(aPoly, nNodes).Transformed(theTrf),
+ nodeAtInd(aPoly, 1).Transformed(theTrf)
};
if (isFullIn) {
if (seg_box_included (theBox, aPntLast) == 0)
if ((myType & Type_Triangulation) && (myIsDrawPolygons == Standard_False))
for (Standard_Integer i = 0; i < myNTriangles; i++) {
- const Standard_Integer * pTri = &mypTriangles[3*i];
- if (tri_line_intersect (start, dir,
- &mypNodes[3*pTri[0]],
- &mypNodes[3*pTri[1]],
- &mypNodes[3*pTri[2]],
- &anInter))
- if (anInter < aResult)
- aResult = anInter;
+ Standard_Boolean isIntersect(Standard_False);
+ if (myIndexType == 0) {
+ const unsigned char * pTri =
+ reinterpret_cast<unsigned char *>(mypTriangles) + (3 * i);
+ if (myNodeCoord > 2)
+ isIntersect = tri_line_intersect (start, dir,
+ &mypNodes[myNodeCoord * pTri[0]],
+ &mypNodes[myNodeCoord * pTri[1]],
+ &mypNodes[myNodeCoord * pTri[2]],
+ &anInter);
+ else
+ isIntersect = tri2d_line_intersect (start, dir,
+ &mypNodes[myNodeCoord * pTri[0]],
+ &mypNodes[myNodeCoord * pTri[1]],
+ &mypNodes[myNodeCoord * pTri[2]],
+ &anInter);
+ } else if (myIndexType == 1) {
+ const unsigned short * pTri =
+ reinterpret_cast<unsigned short *>(mypTriangles) + (3 * i);
+ if (myNodeCoord > 2)
+ isIntersect = tri_line_intersect (start, dir,
+ &mypNodes[myNodeCoord * pTri[0]],
+ &mypNodes[myNodeCoord * pTri[1]],
+ &mypNodes[myNodeCoord * pTri[2]],
+ &anInter);
+ else
+ isIntersect = tri2d_line_intersect (start, dir,
+ &mypNodes[myNodeCoord * pTri[0]],
+ &mypNodes[myNodeCoord * pTri[1]],
+ &mypNodes[myNodeCoord * pTri[2]],
+ &anInter);
+ } else {
+ const Standard_Integer * pTri = &mypTriangles[3 * i];
+ if (myNodeCoord > 2)
+ isIntersect = tri_line_intersect (start, dir,
+ &mypNodes[myNodeCoord * pTri[0]],
+ &mypNodes[myNodeCoord * pTri[1]],
+ &mypNodes[myNodeCoord * pTri[2]],
+ &anInter);
+ else
+ isIntersect = tri2d_line_intersect (start, dir,
+ &mypNodes[myNodeCoord * pTri[0]],
+ &mypNodes[myNodeCoord * pTri[1]],
+ &mypNodes[myNodeCoord * pTri[2]],
+ &anInter);
+ }
+ if (isIntersect && anInter < aResult)
+ aResult = anInter;
}
const Standard_Real anOver2 = theOver*theOver;
if (myType & Type_Segments) {
- for (Standard_Integer i = 0; i < myNLineNodes; i+=2) {
- if (seg_line_intersect (theAxis.Location().XYZ(),
- theAxis.Direction().XYZ(), anOver2,
- &mypNodes[3*mypLines[i+0]],
- &mypNodes[3*mypLines[i+1]],
- &anInter))
- if (anInter < aResult)
- aResult = anInter;
- }
+ Standard_Integer i = 0;
+ if (myNodeCoord > 2)
+ for (; i < myNLineNodes; i+=2) {
+ if (seg_line_intersect (theAxis.Location().XYZ(),
+ theAxis.Direction().XYZ(), anOver2,
+ nodeArrAtInd(mypLines, i+0),
+ nodeArrAtInd(mypLines, i+1),
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ }
+ else
+ for (; i < myNLineNodes; i+=2) {
+ if (seg2d_line_intersect (theAxis.Location().XYZ(),
+ theAxis.Direction().XYZ(), anOver2,
+ nodeArrAtInd(mypLines, i+0),
+ nodeArrAtInd(mypLines, i+1),
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ }
} else if (myType & Type_Line) {
- for (Standard_Integer i = 1; i < myNLineNodes; i++) {
- if (seg_line_intersect (theAxis.Location().XYZ(),
- theAxis.Direction().XYZ(), anOver2,
- &mypNodes[3*mypLines[i-1]],
- &mypNodes[3*mypLines[i-0]],
- &anInter))
- if (anInter < aResult)
- aResult = anInter;
- }
- if (myType & Type_Loop)
- if (seg_line_intersect (theAxis.Location().XYZ(),
- theAxis.Direction().XYZ(), anOver2,
- &mypNodes[3*mypLines[myNLineNodes-1]],
- &mypNodes[3*mypLines[0]],
- &anInter))
- if (anInter < aResult)
- aResult = anInter;
+ Standard_Integer i = 1;
+ if (myNodeCoord > 2) {
+ for (; i < myNLineNodes; i++) {
+ if (seg_line_intersect (theAxis.Location().XYZ(),
+ theAxis.Direction().XYZ(), anOver2,
+ nodeArrAtInd(mypLines, i-1),
+ nodeArrAtInd(mypLines, i-0),
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ }
+ if (myType & Type_Loop)
+ if (seg_line_intersect (theAxis.Location().XYZ(),
+ theAxis.Direction().XYZ(), anOver2,
+ nodeArrAtInd(mypLines, myNLineNodes-1),
+ nodeArrAtInd(mypLines, 0),
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ } else {
+ for (; i < myNLineNodes; i++) {
+ if (seg2d_line_intersect (theAxis.Location().XYZ(),
+ theAxis.Direction().XYZ(), anOver2,
+ nodeArrAtInd(mypLines, i-1),
+ nodeArrAtInd(mypLines, i-0),
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ }
+ if (myType & Type_Loop)
+ if (seg2d_line_intersect (theAxis.Location().XYZ(),
+ theAxis.Direction().XYZ(), anOver2,
+ nodeArrAtInd(mypLines, myNLineNodes-1),
+ nodeArrAtInd(mypLines, 0),
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ }
}
if ((myType & Type_Polygons) && myIsDrawPolygons) {
- for (Standard_Integer iPoly = 0; iPoly < myNPolygons; iPoly++) {
- const Standard_Integer nNodes = * mypPolygons[iPoly];
- const Standard_Integer * arrNodes = mypPolygons[iPoly] + 1;
- for (Standard_Integer i = 1; i < nNodes; i++) {
+ for (unsigned int iPoly = 0; iPoly < myNPolygons; iPoly++) {
+ const Standard_Integer * aPoly = mypPolygons[iPoly];
+ const Standard_Integer nNodes = NPolygonNodes(iPoly);
+ Standard_Integer i = 1;
+ if (myNodeCoord > 2) {
+ for (; i < nNodes; i++) {
+ // Node index is incremented for the head of polygon indice array
+ if (seg_line_intersect (theAxis.Location().XYZ(),
+ theAxis.Direction().XYZ(), anOver2,
+ nodeArrAtInd(aPoly, i+0),
+ nodeArrAtInd(aPoly, i+1),
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ }
if (seg_line_intersect (theAxis.Location().XYZ(),
theAxis.Direction().XYZ(), anOver2,
- &mypNodes[3*arrNodes[i-1]],
- &mypNodes[3*arrNodes[i-0]],
+ nodeArrAtInd(aPoly, nNodes),
+ nodeArrAtInd(aPoly, 1),
&anInter))
if (anInter < aResult)
aResult = anInter;
+ } else {
+ for (; i < nNodes; i++) {
+ // Node index is incremented for the head of polygon indice array
+ if (seg2d_line_intersect (theAxis.Location().XYZ(),
+ theAxis.Direction().XYZ(), anOver2,
+ nodeArrAtInd(aPoly, i+0),
+ nodeArrAtInd(aPoly, i+1),
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ }
+ if (seg2d_line_intersect (theAxis.Location().XYZ(),
+ theAxis.Direction().XYZ(), anOver2,
+ nodeArrAtInd(aPoly, nNodes),
+ nodeArrAtInd(aPoly, 1),
+ &anInter))
+ if (anInter < aResult)
+ aResult = anInter;
+ }
+ }
+ }
+ return aResult;
+}
+
+//=======================================================================
+//function : Intersect
+//purpose :
+//=======================================================================
+Standard_Boolean NIS_Triangulated::Intersect
+ (const NCollection_List<gp_XY> &thePolygon,
+ const gp_Trsf &theTrf,
+ const Standard_Boolean isFullIn) const
+{
+ Standard_Boolean aResult (isFullIn);
+
+ if ((myType & Type_Triangulation) && myIsDrawPolygons == Standard_False) {
+ unsigned int iNode = 0;
+ for (; iNode < myNNodes * myNodeCoord; iNode += myNodeCoord)
+ {
+ gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]),
+ static_cast<Standard_Real>(mypNodes[iNode+1]), 0.);
+ if (myNodeCoord > 2)
+ aPnt.SetZ (static_cast<Standard_Real>(mypNodes[iNode+2]));
+ theTrf.Transforms (aPnt);
+
+ gp_XY aP2d(aPnt.X(), aPnt.Y());
+
+ if (!NIS_Triangulated::IsIn(thePolygon, aP2d)) {
+ if (isFullIn) {
+ aResult = Standard_False;
+ break;
+ }
+ } else {
+ if (isFullIn == Standard_False) {
+ aResult = Standard_True;
+ break;
+ }
+ }
+ }
+ }
+ if (aResult == isFullIn) {
+ if (myType & Type_Segments) {
+ for (Standard_Integer i = 0; i < myNLineNodes; i+=2) {
+ const gp_Pnt aPnt[2] = {
+ nodeAtInd(mypLines, i+0).Transformed(theTrf),
+ nodeAtInd(mypLines, i+1).Transformed(theTrf)
+ };
+ const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
+ gp_XY(aPnt[1].X(), aPnt[1].Y()) };
+
+ if (isFullIn) {
+ if (seg_polygon_included (thePolygon, aP2d) == 0) {
+ aResult = Standard_False;
+ break;
+ }
+ } else {
+ if (seg_polygon_intersect (thePolygon, aP2d)) {
+ aResult = Standard_True;
+ break;
+ }
+ }
+ }
+ } else if (myType & Type_Line) {
+ for (Standard_Integer i = 1; i < myNLineNodes; i++) {
+ const gp_Pnt aPnt[2] = {
+ nodeAtInd(mypLines, i-1).Transformed(theTrf),
+ nodeAtInd(mypLines, i+0).Transformed(theTrf)
+ };
+ const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
+ gp_XY(aPnt[1].X(), aPnt[1].Y()) };
+ if (isFullIn) {
+ if (seg_polygon_included (thePolygon, aP2d) == 0) {
+ aResult = Standard_False;
+ break;
+ }
+ } else {
+ if (seg_polygon_intersect (thePolygon, aP2d)) {
+ aResult = Standard_True;
+ break;
+ }
+ }
+ }
+ if (aResult == isFullIn && (myType & Type_Loop)) {
+ const gp_Pnt aPntLast[2] = {
+ nodeAtInd(mypLines, myNLineNodes-1).Transformed(theTrf),
+ nodeAtInd(mypLines, 0).Transformed(theTrf)
+ };
+ const gp_XY aP2dLast[2] = { gp_XY(aPntLast[0].X(), aPntLast[0].Y()),
+ gp_XY(aPntLast[1].X(), aPntLast[1].Y()) };
+
+ if (isFullIn) {
+ if (seg_polygon_included (thePolygon, aP2dLast) == 0)
+ aResult = Standard_False;
+ } else {
+ if (seg_polygon_intersect (thePolygon, aP2dLast))
+ aResult = Standard_True;
+ }
+ }
+ } else if ((myType & Type_Polygons) && myIsDrawPolygons) {
+ for (unsigned int iPoly = 0; iPoly < myNPolygons; iPoly++) {
+ const Standard_Integer * aPoly = mypPolygons[iPoly];
+ const Standard_Integer nNodes = NPolygonNodes(iPoly);
+ for (Standard_Integer i = 1; i < nNodes; i++) {
+ const gp_Pnt aPnt[2] = {
+ nodeAtInd(aPoly, i+0).Transformed(theTrf),
+ nodeAtInd(aPoly, i+1).Transformed(theTrf)
+ };
+ const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
+ gp_XY(aPnt[1].X(), aPnt[1].Y()) };
+ if (isFullIn) {
+ if (seg_polygon_included (thePolygon, aP2d) == 0) {
+ aResult = Standard_False;
+ break;
+ }
+ } else {
+ if (seg_polygon_intersect (thePolygon, aP2d)) {
+ aResult = Standard_True;
+ break;
+ }
+ }
+ }
+ if (aResult == isFullIn) {
+ const gp_Pnt aPntLast[2] = {
+ nodeAtInd(aPoly, nNodes).Transformed(theTrf),
+ nodeAtInd(aPoly, 1).Transformed(theTrf)
+ };
+ const gp_XY aP2dLast[2] = { gp_XY(aPntLast[0].X(), aPntLast[0].Y()),
+ gp_XY(aPntLast[1].X(), aPntLast[1].Y()) };
+ if (isFullIn) {
+ if (seg_polygon_included (thePolygon, aP2dLast) == 0)
+ aResult = Standard_False;
+ } else {
+ if (seg_polygon_intersect (thePolygon, aP2dLast))
+ aResult = Standard_True;
+ }
+ }
}
- if (seg_line_intersect (theAxis.Location().XYZ(),
- theAxis.Direction().XYZ(), anOver2,
- &mypNodes[3*arrNodes[nNodes-1]],
- &mypNodes[3*arrNodes[0]],
- &anInter))
- if (anInter < aResult)
- aResult = anInter;
}
}
return aResult;
-};
+}
/* =====================================================================
Function : determinant
return res;
}
+/* =====================================================================
+Function : tri2d_line_intersect
+Purpose : Intersect a 2D triangle with a 3D line. Z coordinate of triangle
+ : is zero
+Parameters : start - coordinates of the origin of the line
+ dir - coordinates of the direction of the line (normalized)
+ V0 - first vertex of the triangle
+ V1 - second vertex of the triangle
+ V2 - third vertex of the triangle
+ tInter - output value, contains the parameter of the intersection
+ point on the line (if found). May be NULL pointer
+Returns : int = 1 if intersection found, 0 otherwise
+======================================================================== */
+
+int NIS_Triangulated::tri2d_line_intersect (const double start[3],
+ const double dir[3],
+ const float V0[2],
+ const float V1[2],
+ const float V2[2],
+ double * tInter)
+{
+ int res = 0;
+ const double conf = 1E-15;
+
+ // Parallel case is excluded
+ if (dir[2] * dir[2] > conf)
+ {
+ // Find the 2d intersection of (start, dir) with the plane Z = 0.
+ const double p2d[2] = {
+ start[0] - dir[0] * start[2] / dir[2],
+ start[1] - dir[1] * start[2] / dir[2]
+ };
+
+ // Classify the 2d intersection using barycentric coordinates
+ // (http://www.blackpawn.com/texts/pointinpoly/)
+ const double v[][2] = {
+ { static_cast<double>(V1[0]-V0[0]), static_cast<double>(V1[1]-V0[1]) },
+ { static_cast<double>(V2[0]-V0[0]), static_cast<double>(V2[1]-V0[1]) },
+ { static_cast<double>(p2d[0]-V0[0]), static_cast<double>(p2d[1]-V0[1]) }
+ };
+ const double dot00 = v[0][0]*v[0][0] + v[0][1]*v[0][1];
+ const double dot01 = v[0][0]*v[1][0] + v[0][1]*v[1][1];
+ const double dot02 = v[0][0]*v[2][0] + v[0][1]*v[2][1];
+ const double dot11 = v[1][0]*v[1][0] + v[1][1]*v[1][1];
+ const double dot12 = v[1][0]*v[2][0] + v[1][1]*v[2][1];
+ const double denom = (dot00 * dot11 - dot01 * dot01);
+ if (denom * denom < conf) {
+ // Point on the 1st side of the triangle
+ res = (dot01 > -conf && dot00 < dot11 + conf);
+ } else {
+ // Barycentric coordinates of the point
+ const double u = (dot11 * dot02 - dot01 * dot12) / denom;
+ const double v = (dot00 * dot12 - dot01 * dot02) / denom;
+ res = (u > -conf) && (v > -conf) && (u + v < 1. + conf);
+ }
+ }
+ if (res && tInter)
+ *tInter = -start[2] / dir[2];
+
+ return res;
+}
+
/* =====================================================================
Function : seg_line_intersect
Purpose : Intersect a segment with a line
dir - coordinates of the direction of the line (normalized)
over2 - maximal square distance between the line and the segment
for intersection state
- V0 - first vertex of the triangle
- V1 - second vertex of the triangle
+ V0 - first vertex of the segment
+ V1 - second vertex of the segment
tInter - output value, contains the parameter of the intersection
point on the line (if found). May be NULL pointer
Returns : int = 1 if intersection found, 0 otherwise
return res;
}
+/* =====================================================================
+Function : seg2d_line_intersect
+Purpose : Intersect a 2D segment with a 3D line
+Parameters : start - coordinates of the origin of the line
+ dir - coordinates of the direction of the line (normalized)
+ over2 - maximal square distance between the line and the segment
+ for intersection state
+ V0 - first vertex of the segment
+ V1 - second vertex of the segment
+ tInter - output value, contains the parameter of the intersection
+ point on the line (if found). May be NULL pointer
+Returns : int = 1 if intersection found, 0 otherwise
+======================================================================== */
+
+int NIS_Triangulated::seg2d_line_intersect (const gp_XYZ& aStart,
+ const gp_XYZ& aDir,
+ const double over2,
+ const float V0[2],
+ const float V1[2],
+ double * tInter)
+{
+ int res = 0;
+ const gp_XYZ aDirSeg (V1[0]-V0[0], V1[1]-V0[1], 0.);
+ gp_XYZ aDirN = aDirSeg ^ aDir;
+ Standard_Real aMod2 = aDirN.SquareModulus();
+ if (aMod2 < Precision::Confusion() * 0.001) {
+ const gp_XYZ aDelta0 (V0[0]-aStart.X(), V0[1]-aStart.Y(), -aStart.Z());
+ if ((aDelta0 ^ aDir).SquareModulus() < over2) {
+ res = 1;
+ const gp_XYZ aDelta1 (V1[0]-aStart.X(), V1[1]-aStart.Y(), -aStart.Z());
+ if (tInter)
+ * tInter = Min (aDelta0 * aDir, aDelta1 * aDir);
+ }
+ } else {
+ // distance between two unlimited lines
+ const gp_XYZ aPnt0 (V0[0], V0[1], 0.);
+ const Standard_Real aDistL = (aDirN * aPnt0) - aDirN * aStart;
+ if (aDistL*aDistL < over2 * aMod2) {
+ const gp_XYZ aPnt1 (V1[0], V1[1], 0.);
+ Standard_Real aDist[3] = {
+ ((aPnt0 - aStart) ^ aDir).Modulus(),
+ ((aPnt1 - aStart) ^ aDir).Modulus(),
+ 0.
+ };
+ // Find the intermediate point by interpolation using the distances from
+ // the end points.
+ const gp_XYZ aPntI =
+ (aPnt0 * aDist[1] + aPnt1 * aDist[0]) / (aDist[0] + aDist[1]);
+ aDist[2] = ((aPntI - aStart) ^ aDir).Modulus();
+ if (aDist[2] < aDist[0] && aDist[2] < aDist[1]) {
+ if (aDist[2]*aDist[2] < over2) {
+ res = 1;
+ if (tInter)
+ * tInter = (aPntI - aStart) * aDir;
+ }
+ } else if (aDist[0] < aDist[1]) {
+ if (aDist[0] * aDist[0] < over2) {
+ res = 1;
+ if (tInter)
+ * tInter = (aPnt0 - aStart) * aDir;
+ }
+ } else {
+ if (aDist[1] * aDist[1] < over2) {
+ res = 1;
+ if (tInter)
+ * tInter = (aPnt1 - aStart) * aDir;
+ }
+ }
+ }
+ }
+ return res;
+}
+
//=======================================================================
//function : seg_box_intersect
//purpose :
return aResult;
}
+//=======================================================================
+//function : seg_polygon_intersect
+//purpose :
+//=======================================================================
+
+int NIS_Triangulated::seg_polygon_intersect
+ (const NCollection_List<gp_XY> &thePolygon,
+ const gp_XY thePnt[2])
+{
+ Standard_Integer aResult = 0;
+
+ if (thePolygon.IsEmpty())
+ return aResult;
+
+ gp_XY aDir(thePnt[1] - thePnt[0]);
+ Standard_Real aDist = aDir.SquareModulus();
+
+ if (aDist > aTolConf) {
+ aDist = Sqrt(aDist);
+ aDir.Divide(aDist); // Normalize direction.
+
+ // Intersect the line passed through thePnt[0] and thePnt[1] with thePolygon
+ // Line is presented in form Ax + By + C = 0
+ Standard_Real aA = aDir.Y();
+ Standard_Real aB = -aDir.X();
+ Standard_Real aC = -(aA*thePnt[0].X() + aB*thePnt[0].Y());
+ gp_XY aSegment[2];
+ Standard_Real aSignedD[2];
+ Standard_Real aDelta = 0.01;
+
+ aSegment[0] = thePolygon.Last();
+ aSignedD[0] = aA*aSegment[0].X() + aB*aSegment[0].Y() + aC;
+
+ NCollection_List<gp_XY>::Iterator anIter(thePolygon);
+
+ for (; anIter.More(); anIter.Next()) {
+ aSegment[1] = anIter.Value();
+ aSignedD[1] = aA*aSegment[1].X() + aB*aSegment[1].Y() + aC;
+
+ // Check if there is an intersection.
+ if (Abs(aSignedD[0]) <= aTolConf || Abs(aSignedD[1]) <= aTolConf) {
+ Standard_Integer anIndexVtx =
+ (Abs(aSignedD[0]) > aTolConf) ? 1 :
+ (Abs(aSignedD[1]) > aTolConf) ? 0 : -1;
+ if (anIndexVtx != -1) {
+ // Check if the point aSegment[1] is inside the segment.
+ gp_XY aDP(aSegment[anIndexVtx] - thePnt[0]);
+ Standard_Real aParam = aDP.Dot(aDir);
+
+ if (aParam >= -aTolConf && aParam <= aDist + aTolConf) {
+ // Classify a point on the line that is close to aSegment[1] with
+ // respect to the polygon.
+ gp_XY aPShift;
+
+ if (aParam - aDelta >= 0.) {
+ aPShift = thePnt[0] + aDir.Multiplied(aParam - aDelta);
+ if (!IsIn(thePolygon, aPShift))
+ aResult = 1;
+ }
+
+ // Try to shift on another direction.
+ if (!aResult) {
+ if (aParam + aDelta <= aDist) {
+ aPShift = thePnt[0] + aDir.Multiplied(aParam + aDelta);
+ if (!IsIn(thePolygon, aPShift))
+ aResult = 1;
+ }
+ }
+ }
+ }
+ } else if (aSignedD[0]*aSignedD[1] < 0.) {
+ // Compute intersection of the segment with the line.
+ gp_XY aDSeg(aSegment[1] - aSegment[0]);
+ Standard_Real aSegLen = aDSeg.Modulus();
+ Standard_Real aParamOnSeg = aSegLen/(1 + Abs(aSignedD[1]/aSignedD[0]));
+ gp_XY aPOnLine
+ (aSegment[0] + aDSeg.Multiplied(aParamOnSeg/aSegLen));
+
+ // Check if aPOnLine inside the segment thePnt[1] - thePnt[0]
+ gp_XY aDP(aPOnLine - thePnt[0]);
+ Standard_Real aParam = aDP.Dot(aDir);
+
+ if (aParam >= -aTolConf && aParam <= aDist + aTolConf) {
+ gp_XY aPShift;
+
+ if (aParam - aDelta >= 0.) {
+ aPShift = thePnt[0] + aDir.Multiplied(aParam - aDelta);
+
+ if (!IsIn(thePolygon, aPShift))
+ aResult = 1;
+ }
+
+ // Try to shift on another direction.
+ if (!aResult) {
+ if (aParam + aDelta <= aDist) {
+ aPShift = thePnt[0] + aDir.Multiplied(aParam + aDelta);
+
+ if (!IsIn(thePolygon, aPShift))
+ aResult = 1;
+ }
+ }
+ }
+ }
+
+ if (aResult != 0)
+ break;
+
+ aSegment[0] = aSegment[1];
+ aSignedD[0] = aSignedD[1];
+ }
+ }
+
+ return aResult;
+}
+
+//=======================================================================
+//function : seg_polygon_included
+//purpose :
+//=======================================================================
+
+int NIS_Triangulated::seg_polygon_included
+ (const NCollection_List<gp_XY> &thePolygon,
+ const gp_XY thePnt[2])
+{
+ int aResult = 0;
+ int anIntersect = seg_polygon_intersect(thePolygon, thePnt);
+
+ if (anIntersect == 0) {
+ if (IsIn(thePolygon, thePnt[0]) && IsIn(thePolygon, thePnt[1]))
+ aResult = 1;
+ }
+
+ return aResult;
+}
+
+//=======================================================================
+//function : IsIn
+//purpose :
+//=======================================================================
+
+Standard_Boolean NIS_Triangulated::IsIn
+ (const NCollection_List<gp_XY> &thePolygon,
+ const gp_XY &thePoint)
+{
+ if (thePolygon.IsEmpty())
+ return Standard_False;
+
+ Standard_Integer aCounter = 0; // intersections counter
+ gp_XY aSegment[2];
+
+ aSegment[0] = thePolygon.Last();
+
+ NCollection_List<gp_XY>::Iterator anIter(thePolygon);
+
+ for (; anIter.More(); anIter.Next()) {
+ aSegment[1] = anIter.Value();
+
+ // Compute projection of the point onto the segment.
+ Standard_Real aParam = 0.;
+ const gp_XY aDelta = aSegment[1] - aSegment[0];
+ const gp_XY aDPP0 = thePoint - aSegment[0];
+ const Standard_Real aLen2 = aDelta.SquareModulus();
+
+ if (IsPositive(aLen2)) {
+ aParam = (aDelta*aDPP0)/aLen2;
+
+ if (aParam < 0.)
+ aParam = 0.;
+ else if (aParam > 1.)
+ aParam = 1.;
+ }
+ // Check if the point lies on the segment
+ gp_XY aPOnSeg = aSegment[0]*(1. - aParam) + aSegment[1]*aParam;
+ Standard_Real aSqrDist = (thePoint - aPOnSeg).SquareModulus();
+
+ if (aSqrDist < aTolConf) {
+ // The point is on the contour.
+ return Standard_True;
+ }
+
+ // Compute intersection.
+ const Standard_Real aProd(aDPP0 ^ aDelta);
+
+ if (IsPositive(thePoint.X() - aSegment[0].X())) {
+ if (!IsPositive(thePoint.X() - aSegment[1].X())) {
+ if (aProd > 0.)
+ aCounter++;
+ }
+ } else {
+ if (IsPositive(thePoint.X() - aSegment[1].X())) {
+ if (aProd < 0.)
+ aCounter++;
+ }
+ }
+
+ aSegment[0] = aSegment[1];
+ }
+
+ return (aCounter & 0x1);
+}
+
//=======================================================================
//function : allocateNodes
//purpose :
myAlloc->Free(mypNodes);
myNNodes = nNodes;
mypNodes = static_cast<Standard_ShortReal*>
- (myAlloc->Allocate(sizeof(Standard_ShortReal)*3*nNodes));
+ (myAlloc->Allocate(sizeof(Standard_ShortReal) * myNodeCoord * nNodes));
+ if (nNodes < 256)
+ myIndexType = 0;
+ else if (nNodes < 65536)
+ myIndexType = 1;
+ else
+ myIndexType = 2;
+ }
+}
+
+//=======================================================================
+//function : NodeAtInd
+//purpose : Get the node pointed by the i-th index in the array.
+//=======================================================================
+
+gp_Pnt NIS_Triangulated::nodeAtInd (const Standard_Integer * theArray,
+ const Standard_Integer theInd) const
+{
+ if (myIndexType == 0) {
+ const unsigned char * pInd =
+ reinterpret_cast<const unsigned char *>(theArray);
+ return gp_Pnt (mypNodes[myNodeCoord * pInd[theInd] + 0],
+ mypNodes[myNodeCoord * pInd[theInd] + 1],
+ myNodeCoord < 3 ? 0. :
+ mypNodes[myNodeCoord * pInd[theInd] + 2]);
+ }
+ if (myIndexType == 1) {
+ const unsigned short * pInd =
+ reinterpret_cast<const unsigned short *>(theArray);
+ return gp_Pnt (mypNodes[myNodeCoord * pInd[theInd] + 0],
+ mypNodes[myNodeCoord * pInd[theInd] + 1],
+ myNodeCoord < 3 ? 0. :
+ mypNodes[myNodeCoord * pInd[theInd] + 2]);
+ }
+ return gp_Pnt (mypNodes[myNodeCoord * theArray[theInd] + 0],
+ mypNodes[myNodeCoord * theArray[theInd] + 1],
+ myNodeCoord < 3 ? 0. :
+ mypNodes[myNodeCoord * theArray[theInd] + 2]);
+}
+
+//=======================================================================
+//function : nodeArrAtInd
+//purpose : Get the node pointed by the i-th index in the array.
+//=======================================================================
+
+float* NIS_Triangulated::nodeArrAtInd (const Standard_Integer * theArray,
+ const Standard_Integer theInd) const
+{
+ float* pResult = 0L;
+ if (myIndexType == 0) {
+ const unsigned char * pInd =
+ reinterpret_cast<const unsigned char *>(theArray);
+ pResult = &mypNodes[myNodeCoord * pInd[theInd]];
+ }
+ else if (myIndexType == 1) {
+ const unsigned short * pInd =
+ reinterpret_cast<const unsigned short *>(theArray);
+ pResult = &mypNodes[myNodeCoord * pInd[theInd]];
+ }
+ else {
+ pResult = &mypNodes[myNodeCoord * theArray[theInd]];
}
+ return pResult;
}
#include <NIS_InteractiveObject.hxx>
#include <Quantity_Color.hxx>
+#ifdef WNT
+// Disable the warning "operator new unmatched by delete"
+#pragma warning (push)
+#pragma warning (disable:4291)
+#endif
+
class Handle_NIS_TriangulatedDrawer;
class NCollection_BaseAllocator;
class Handle_NCollection_BaseAllocator;
+class NIS_TriangulatedDrawer;
/**
- * Block of comments describing class NIS_Triangulated
+ * Interactive object that consists of triangles, lines and polygons without
+ * normals. Particularly can be used to render planar 2D shapes.
+ *
+ * @par 2D and 3D model
+ * Vertices are stored in an array of float numbers, 2 or 3 numbers per vertex.
+ * The number of dimensions is defined in the constructor, see the parameter
+ * 'is2D'. When 2D is defined then for all vertices the Z coordinate is 0.
+ * To display planar objects in a plane different from XOY you should subclass
+ * this type together with the correponding Drawer and store the transformation
+ * parameters. In Drawer subclass either in method BeforeDraw() or in method
+ * Draw() you would call glTranslate() or glMultMatrix() so that all vertices
+ * should be located in their proper positions.
+ *
+ * @par Compressed storage
+ * For efficient memory utilization, indice (triangles, segments, polygons) are
+ * 8-bit, 16-bit or 32-bit numbers. The width of this numeric representation is
+ * chosen automatically when the total number of nodes is passed in the
+ * constructor or in any Set* method. For example, if this number of nodes is
+ * smaller than 256 then 8-bit representation is selected. The choice is stored
+ * in 'myIndexType' data member.
*/
class NIS_Triangulated : public NIS_InteractiveObject
{
protected:
- // Constants defining the mode (type) of presentation. They allow mixed type,
- // e.g., Triangulation+Line. Line and Segments are not mixable, their mix is
- // treated as Line only.
+ /**
+ * Constants defining the mode (type) of presentation. They allow mixed type,
+ * e.g., Triangulation+Line. Line and Segments are not mixable, their mix is
+ * treated as Line only.
+ */
enum {
Type_None = 0,
- Type_Loop = 1, // modifier to Line
+ Type_Loop = 1, //!< modifier to Line
Type_Line = 2,
Type_Segments = 4,
Type_Triangulation = 8,
Type_Polygons = 16
};
+ public:
+ /**
+ * Enumerated type of polygon rendering.
+ */
+ enum PolygonType {
+ Polygon_Default = 0, //!< Polygon as LINE, Triangulation as FILL
+ Polygon_Line = 1, //!< Both Polygon and Triangulation as LINE
+ Polygon_Fill = 2 //!< Both Polygon and Triangulation as FILL
+ };
+
public:
// ---------- PUBLIC METHODS ----------
* (this number may be defined later in methods Set*Prs) as well as the
* memory allocator where the nodes, lines and triangles will be stored by
* this instance.
+ * @param nNodes
+ * Total number of nodes that will be initialized for this object
+ * @param is2D
+ * If true then the nodes will be 2D in plane Z=0, otherwise normal 3D.
+ * @param theAlloc
+ * Allocator for internal data
*/
Standard_EXPORT NIS_Triangulated(const Standard_Integer nNodes = 0,
- const Handle_NCollection_BaseAllocator& =0L);
+ const Standard_Boolean is2D = Standard_False,
+ const Handle_NCollection_BaseAllocator&
+ theAlloc = 0L);
/**
* Define the polygonal presentration.
/**
* Create a default drawer instance.
*/
- Standard_EXPORT virtual Handle_NIS_Drawer
- DefaultDrawer () const;
-
+ Standard_EXPORT virtual NIS_Drawer *
+ DefaultDrawer (NIS_Drawer *) const;
/**
* Define the coordinates of node [ind].
/**
* Allocate a single polygon, should be called for each polygon following
- * the call SetPolygonsPrs().
+ * the call SetPolygonsPrs(). The polygon can be filled by node indices using
+ * the method SetPolygonNode().
* @param ind
* Index of the polygon, should be [0..Npolygons-1]
* @param theSz
* Number of points (segments) in the polygon.
- * @return
- * Pointer to the allocated buffer where you should store the indices
- * of all polygon nodes in order, total "theSz" integers.
*/
- Standard_EXPORT Standard_Integer* SetPolygon (const Standard_Integer ind,
+ Standard_EXPORT void SetPolygon (const Standard_Integer ind,
const Standard_Integer theSz);
/**
* Query the number of polygons.
*/
inline Standard_Integer NPolygons () const
- { return myNPolygons; }
+ { return static_cast<Standard_Integer>(myNPolygons); }
/**
* Query the node by its index.
* @return
- * pointer to array of 3 Standard_ShortReal values (X,Y,Z coordinates)
+ * pointer to array of 2 or 3 Standard_ShortReal values {X,Y(,Z) coord}
*/
inline const Standard_ShortReal * Node (const Standard_Integer ind) const
- { return &mypNodes[ind*3]; }
+ { return &mypNodes[ind * myNodeCoord]; }
/**
- * Query the triangle by its index.
- * @return
- * pointer to array of 3 Standard_Integer values (nodes 0, 1, 2)
+ * Define the node of a polygon by index.
+ * @param indPoly
+ * Index of the Polygon, should be less than the number of polygons that is
+ * defined in SetPolygonsPrs() and can be returned by NPOlygons().
+ * @param ind
+ * Index of the node in the Polygon. Should be less than the parameter theSz
+ * in the corresponding previous SetPolygon() call.
+ * @param iNode
+ * Index of the node in the given position of the Polygon.
*/
- inline const Standard_Integer * Triangle (const Standard_Integer ind) const
- { return &mypTriangles[ind*3]; }
+ Standard_EXPORT void SetPolygonNode
+ (const Standard_Integer indPoly,
+ const Standard_Integer ind,
+ const Standard_Integer iNode);
/**
- * Query the node of line or segments by index in the array of node indices.
- * This method does not make distinction of the presentation type
- * (field myType), so the correct definition of ind is to be done by the
- * caller.
- * @return
- * pointer to the Integer value representing the index of the node.
+ * Get the node with index 'ind' from the polygon number 'indPoly'.
*/
- inline const Standard_Integer * LineNode (const Standard_Integer ind) const
- { return &mypLines[ind]; }
-
+ Standard_EXPORT Standard_Integer PolygonNode(const Standard_Integer indPoly,
+ const Standard_Integer ind)const;
/**
- * Query the polygon.
- * @param ind
- * rank of the polygon [0 .. N-1]
- * @param outInd
- * <tt>[out]</tt> array of vertex indice
- * @return
- * number of vertice in the polygon - the dimension of outInd array
+ * Get the number of nodes for the polygon number 'indPoly'.
*/
- inline const Standard_Integer Polygon (const Standard_Integer ind,
- Standard_Integer* & outInd) const
- { return * (outInd = mypPolygons[ind])++; }
+ Standard_EXPORT Standard_Integer NPolygonNodes
+ (const Standard_Integer indPoly)const;
/**
* Set the boolean flag defining if the polygons or the triangulation
* Line/Segments.
* @param isDrawPolygons
* True defines that no triangulation is drawn, only polygons are. False
- * defines that only triangulation is draw, no polygons.
- * @param isUpdateV
- * True if all views should be updated, otherwise wait till the next update
+ * defines that only triangulation is drawn, no polygons.
*/
Standard_EXPORT void SetDrawPolygons
- (const Standard_Boolean isDrawPolygons,
- const Standard_Boolean isUpdateViews
- = Standard_True);
+ (const Standard_Boolean isDrawPolygons);
+ /**
+ * Set the type of polygon rendering.
+ */
+ Standard_EXPORT void SetPolygonType
+ (const PolygonType theType);
+
/**
* Set the normal color for presentation.
* @param theColor
* New color to use for the presentation.
- * @param isUpdateV
- * True if all views should be updated, otherwise wait till the next update
*/
- Standard_EXPORT void SetColor (const Quantity_Color& theColor,
- const Standard_Boolean isUpdateV
- = Standard_True);
+ Standard_EXPORT void SetColor (const Quantity_Color& theColor);
/**
* Get Normal, Transparent or Hilighted color of the presentation.
* Set the color for hilighted presentation.
* @param theColor
* New color to use for the presentation.
- * @param isUpdateV
- * True if all views should be updated, otherwise wait till the next update
*/
- Standard_EXPORT void SetHilightColor (const Quantity_Color& theColor,
- const Standard_Boolean isUpdateV
- = Standard_True);
+ Standard_EXPORT void SetHilightColor (const Quantity_Color& theColor);
/**
* Set the color for dynamic hilight presentation.
* @param theColor
* New color to use for the presentation.
- * @param isUpdateV
- * True if all views should be updated, otherwise wait till the next update
*/
- Standard_EXPORT void SetDynHilightColor(const Quantity_Color& theColor,
- const Standard_Boolean isUpdateV
- = Standard_True);
+ Standard_EXPORT void SetDynHilightColor(const Quantity_Color& theColor);
/**
* Set the width of line presentations in pixels.
* @param theWidth
* New line width to use for the presentation.
- * @param isUpdateV
- * True if all views should be updated, otherwise wait till the next update
*/
- Standard_EXPORT void SetLineWidth (const Standard_Real theWidth,
- const Standard_Boolean isUpdateV
- = Standard_True);
+ Standard_EXPORT void SetLineWidth (const Standard_Real theWidth);
+
+ /**
+ * Create a copy of theObject except its ID.
+ * @param theAll
+ * Allocator where the Dest should store its private data.
+ * @param theDest
+ * <tt>[in-out]</tt> The target object where the data are copied. If
+ * passed NULL then the target should be created.
+ */
+ Standard_EXPORT virtual void
+ Clone (const Handle_NCollection_BaseAllocator& theAll,
+ Handle_NIS_InteractiveObject& theDest) const;
/**
* Intersect the InteractiveObject geometry with a line/ray.
* detected. Otherwise returns the coordinate of thePnt on the ray. May be
* negative.
*/
- Standard_EXPORT Standard_Real
+ Standard_EXPORT virtual Standard_Real
Intersect (const gp_Ax1& theAxis,
const Standard_Real theOver) const;
const gp_Trsf& theTrf,
const Standard_Boolean isFull)const;
- Standard_EXPORT static int tri_line_intersect (const double start[3],
- const double dir[3],
- const float V0[3],
- const float V1[3],
- const float V2[3],
- double * tInter);
-
- Standard_EXPORT static int seg_line_intersect (const gp_XYZ& aStart,
- const gp_XYZ& aDir,
- const double over2,
- const float V0[3],
- const float V1[3],
- double * tInter);
+ /**
+ * Intersect the InteractiveObject geometry with a selection polygon.
+ * @param thePolygon
+ * the list of vertices of a free-form closed polygon without
+ * self-intersections. The last point should not coincide with the first
+ * point of the list. Any two neighbor points should not be confused.
+ * @param theTrf
+ * Position/Orientation of the polygon.
+ * @param isFullIn
+ * True if full inclusion is required, False - if partial.
+ * @return
+ * True if the InteractiveObject geometry intersects the polygon or is
+ * inside it
+ */
+ Standard_EXPORT virtual Standard_Boolean Intersect
+ (const NCollection_List<gp_XY> &thePolygon,
+ const gp_Trsf &theTrf,
+ const Standard_Boolean isFullIn) const;
+
+ Standard_EXPORT static int tri_line_intersect (const double start[3],
+ const double dir[3],
+ const float V0[3],
+ const float V1[3],
+ const float V2[3],
+ double * tInter);
+
+ Standard_EXPORT static int tri2d_line_intersect(const double start[3],
+ const double dir[3],
+ const float V0[2],
+ const float V1[2],
+ const float V2[2],
+ double * tInter);
+
+ Standard_EXPORT static int seg_line_intersect (const gp_XYZ& aStart,
+ const gp_XYZ& aDir,
+ const double over2,
+ const float V0[3],
+ const float V1[3],
+ double * tInter);
+
+ Standard_EXPORT static int seg2d_line_intersect(const gp_XYZ& aStart,
+ const gp_XYZ& aDir,
+ const double over2,
+ const float V0[2],
+ const float V1[2],
+ double * tInter);
Standard_EXPORT static int seg_box_intersect (const Bnd_B3f& theBox,
const gp_Pnt thePnt[2]);
Standard_EXPORT static int seg_box_included (const Bnd_B3f& theBox,
const gp_Pnt thePnt[2]);
+ Standard_EXPORT static int seg_polygon_intersect
+ (const NCollection_List<gp_XY> &thePolygon,
+ const gp_XY thePnt[2]);
+
+ Standard_EXPORT static int seg_polygon_included
+ (const NCollection_List<gp_XY> &thePolygon,
+ const gp_XY thePnt[2]);
+
Standard_EXPORT static void ComputeBox (Bnd_B3f& theBox,
const Standard_Integer nNodes,
- const Standard_ShortReal* pNodes);
+ const Standard_ShortReal* pNodes,
+ const Standard_Integer nCoord);
+
+ /**
+ * Classification of thePoint with respect to thePolygon.
+ * @param thePolygon
+ * the list of vertices of a free-form closed polygon without
+ * self-intersections. The last point should not coincide with the first
+ * point of the list. Any two neighbor points should not be confused.
+ * @param thePoint
+ * the point to be classified.
+ * @return
+ * Standard_True if thePoint in inside thePolygon or lies on its boundary.
+ */
+ Standard_EXPORT static Standard_Boolean
+ IsIn (const NCollection_List<gp_XY> &thePolygon,
+ const gp_XY &thePoint);
+
+ /**
+ * Implements deallocation of the object instance
+ */
+ Standard_EXPORT virtual void Delete () const;
+
+ /**
+ * Operator new for memory allocation uses Open CASCADE memory manager
+ */
+ void* operator new (size_t size)
+ {
+ return Standard::Allocate(size);
+ }
protected:
+ /**
+ * Allocator-based operator new for dynamic allocations in method Clone()
+ */
+ void* operator new (Standard_Size theSz,
+ const Handle(NCollection_BaseAllocator)& theAllocator)
+ {
+ return theAllocator->Allocate(theSz);
+ }
+
/**
* Create a 3D bounding box of the object.
*/
*/
Standard_EXPORT void allocateNodes (const Standard_Integer nNodes);
- protected:
- // ---------- PROTECTED FIELDS ----------
+ /**
+ * Get the node pointed by the i-th index in the array.
+ */
+ Standard_EXPORT gp_Pnt nodeAtInd (const Standard_Integer * theArr,
+ const Standard_Integer i) const;
/**
- * Combination of Type_* constants
+ * Get the node pointed by the i-th index in the array.
*/
- Standard_Integer myType;
- Standard_ShortReal * mypNodes;
- Standard_Integer * mypTriangles;
- Standard_Integer * mypLines;
- Standard_Integer ** mypPolygons;
- Standard_Integer myNNodes;
- Standard_Integer myNTriangles;
- Standard_Integer myNPolygons;
- Standard_Integer myNLineNodes;
- NCollection_BaseAllocator * myAlloc;
- Standard_Boolean myIsDrawPolygons;
+ Standard_EXPORT float* nodeArrAtInd (const Standard_Integer * theArr,
+ const Standard_Integer i) const;
+
+ protected:
+ // ---------- PROTECTED FIELDS ----------
+
+ NCollection_BaseAllocator * myAlloc; //!< Usually from InteractiveContext
+ Standard_Integer myType; //!< Combination of Type_* constants
+ Standard_ShortReal * mypNodes;
+ Standard_Integer * mypTriangles;
+ Standard_Integer * mypLines;
+ Standard_Integer ** mypPolygons;
+ Standard_Integer myNNodes;
+ Standard_Integer myNTriangles;
+ Standard_Integer myNLineNodes;
+ unsigned int myNPolygons : 24;
+ Standard_Boolean myIsDrawPolygons : 1;
+ Standard_Boolean myIsCloned : 1; //!< How it is allocated
+ unsigned int myIndexType : 2; //!< 0:8bit, 1:16bit, 2:32bit
+ unsigned int myNodeCoord : 2; //!< 2 or 3 coordinates
+ unsigned int myPolygonType : 2;
public:
// Declaration of CASCADE RTTI
DEFINE_STANDARD_RTTI (NIS_Triangulated)
+
+ friend class NIS_TriangulatedDrawer;
};
// Definition of HANDLE object using Standard_DefineHandle.hxx
DEFINE_STANDARD_HANDLE (NIS_Triangulated, NIS_InteractiveObject)
+#ifdef WNT
+#pragma warning (pop)
+#endif
+
#endif
const Quantity_Color theHilight,
const Quantity_Color theDynHilight)
: myLineWidth (1.f),
- myIsDrawPolygons (Standard_False)
+ myIsDrawPolygons (Standard_False),
+ myPolygonType (NIS_Triangulated::Polygon_Default),
+ myPolygonAsLineLoop (Standard_False)
{
myColor[Draw_Normal] = theNormal;
+ myColor[Draw_Top] = theNormal;
myColor[Draw_Transparent] = theNormal;
myColor[Draw_Hilighted] = theHilight;
myColor[Draw_DynHilighted] = theDynHilight;
const Handle(NIS_TriangulatedDrawer)& anOther =
static_cast <const Handle(NIS_TriangulatedDrawer)&> (theOther);
myColor[Draw_Normal] = anOther->myColor[Draw_Normal];
+ myColor[Draw_Top] = anOther->myColor[Draw_Top];
myColor[Draw_Transparent] = anOther->myColor[Draw_Transparent];
myColor[Draw_Hilighted] = anOther->myColor[Draw_Hilighted];
myColor[Draw_DynHilighted] = anOther->myColor[Draw_DynHilighted];
myLineWidth = anOther->myLineWidth;
myIsDrawPolygons = anOther->myIsDrawPolygons;
+ myPolygonType = anOther->myPolygonType;
}
}
+static const Standard_Integer nObjPerDrawer = 64;
+
//=======================================================================
//function : IsEqual
//purpose : Comparison of two Drawers (for Map impementation)
.SquareDistance (myColor[Draw_DynHilighted]) < anEpsilon2 &&
(anOther->myLineWidth - myLineWidth) *
(anOther->myLineWidth - myLineWidth) < 0.01 &&
- anOther->myIsDrawPolygons == myIsDrawPolygons);
+ anOther->myIsDrawPolygons == myIsDrawPolygons &&
+ anOther->myPolygonType == myPolygonType);
return aResult;
}
void NIS_TriangulatedDrawer::BeforeDraw (const DrawType theType,
const NIS_DrawList&)
{
- Quantity_Parameter aValue[3];
+ Quantity_Parameter aValue[4];
Quantity_TypeOfColor bidTC (Quantity_TOC_RGB);
GLfloat aLineWidth (myLineWidth);
Standard_Integer anOffsetHilighted = 0;
anOffsetHilighted = -11;
#endif
case Draw_Hilighted:
- if (myIsDrawPolygons)
- glEnable(GL_POLYGON_OFFSET_LINE);
- else
- glEnable(GL_POLYGON_OFFSET_FILL);
+ switch (myPolygonType) {
+ default:
+ case NIS_Triangulated::Polygon_Default:
+ if (myIsDrawPolygons) {
+ case NIS_Triangulated::Polygon_Line:
+ glEnable(GL_POLYGON_OFFSET_LINE);
+ } else {
+ case NIS_Triangulated::Polygon_Fill:
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ }
+ }
if (theType == Draw_Hilighted)
{
#ifdef NEGATIVE_POFFSET
anOffsetHilighted = 1;
#endif
}
+ myColor[theType].Values (aValue[0], aValue[1], aValue[2], bidTC);
+ glColor3d (aValue[0], aValue[1], aValue[2]);
break;
case Draw_Normal:
+ case Draw_Top:
case Draw_Transparent:
#ifndef NEGATIVE_POFFSET
anOffsetHilighted = 11;
#endif
+ myColor[theType].Values (aValue[0], aValue[1], aValue[2], bidTC);
+ aValue[3] = 1. - myTransparency;
+ if (myTransparency > 0.01) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ glColor4d (aValue[0], aValue[1], aValue[2], aValue[3]);
break;
default:
return;
if (anOffsetHilighted)
glPolygonOffset(1.f, static_cast<GLfloat>(anOffsetHilighted));
- myColor[theType].Values (aValue[0], aValue[1], aValue[2], bidTC);
- glColor3d (aValue[0], aValue[1], aValue[2]);
- if (myIsDrawPolygons)
- glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
- else
- glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+// myColor[theType].Values (aValue[0], aValue[1], aValue[2], bidTC);
+// glColor3d (aValue[0], aValue[1], aValue[2]);
+ switch (myPolygonType) {
+ default:
+ case NIS_Triangulated::Polygon_Default:
+ if (myIsDrawPolygons) {
+ case NIS_Triangulated::Polygon_Line:
+ glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+ } else {
+ case NIS_Triangulated::Polygon_Fill:
+ glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ }
+ }
glEnableClientState (GL_VERTEX_ARRAY);
glLineWidth (aLineWidth);
glShadeModel(GL_FLAT);
switch (theType) {
case Draw_Hilighted:
case Draw_DynHilighted:
- if (myIsDrawPolygons)
- glDisable(GL_POLYGON_OFFSET_LINE);
- else
- glDisable(GL_POLYGON_OFFSET_FILL);
+ switch (myPolygonType) {
+ default:
+ case NIS_Triangulated::Polygon_Default:
+ if (myIsDrawPolygons) {
+ case NIS_Triangulated::Polygon_Line:
+ glDisable(GL_POLYGON_OFFSET_LINE);
+ } else {
+ case NIS_Triangulated::Polygon_Fill:
+ glDisable(GL_POLYGON_OFFSET_FILL);
+ }
+ }
case Draw_Normal:
+ case Draw_Top:
case Draw_Transparent:
glDisableClientState(GL_VERTEX_ARRAY);
+ if (myTransparency > 0.01)
+ glDisable(GL_BLEND);
default:;
}
- if (myIsDrawPolygons)
+ if (myPolygonType == NIS_Triangulated::Polygon_Line ||
+ (myPolygonType == NIS_Triangulated::Polygon_Default && myIsDrawPolygons))
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
}
#endif
const NIS_Triangulated * pObject =
static_cast <const NIS_Triangulated *> (theObj.operator->());
- glVertexPointer (3, GL_FLOAT, 0, pObject->Node(0));
+ glVertexPointer (pObject->myNodeCoord, GL_FLOAT, 0, pObject->Node(0));
+
+ GLenum aType = GL_UNSIGNED_INT;
+ if (pObject->myIndexType == 0)
+ aType = GL_UNSIGNED_BYTE;
+ else if (pObject->myIndexType == 1)
+ aType = GL_UNSIGNED_SHORT;
+
if (myIsDrawPolygons == Standard_False) {
- if (pObject->IsTriangulation())
+ if (pObject->IsTriangulation()) {
glDrawElements (GL_TRIANGLES, pObject->NTriangles()*3,
- GL_UNSIGNED_INT, pObject->Triangle(0));
+ aType, pObject->mypTriangles);
+ }
} else {
if (pObject->IsPolygons()) {
+ GLenum aMode = GL_POLYGON;
+ if (myPolygonAsLineLoop &&
+ (myPolygonType == NIS_Triangulated::Polygon_Line ||
+ (myPolygonType == NIS_Triangulated::Polygon_Default &&
+ myIsDrawPolygons)))
+ aMode = GL_LINE_LOOP;
const Standard_Integer nPoly = pObject->NPolygons();
for (Standard_Integer i = 0; i < nPoly; i++) {
- Standard_Integer * arrNodes;
- const Standard_Integer nSize = pObject->Polygon (i, arrNodes);
- glDrawElements (GL_LINE_LOOP, nSize, GL_UNSIGNED_INT, arrNodes);
+ const Standard_Integer nSize = pObject->NPolygonNodes(i);
+ void* anArray;
+ if (pObject->myIndexType == 0)
+ anArray = reinterpret_cast<unsigned char *>(pObject->mypPolygons[i]) + 1;
+ else if (pObject->myIndexType == 1)
+ anArray = reinterpret_cast<unsigned short *>(pObject->mypPolygons[i]) + 1;
+ else
+ anArray = pObject->mypPolygons[i] + 1;
+ glDrawElements (aMode, nSize, aType, anArray);
}
}
}
if (pObject->IsSegments())
glDrawElements (GL_LINES, pObject->NLineNodes(),
- GL_UNSIGNED_INT, pObject->LineNode(0));
+ aType, pObject->mypLines);
else {
Standard_Boolean isLoop;
if (pObject->IsLine(isLoop))
if (isLoop) {
- glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+// glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
glDrawElements (GL_LINE_LOOP, pObject->NLineNodes(),
- GL_UNSIGNED_INT, pObject->LineNode(0));
- glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ aType, pObject->mypLines);
+// glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
} else {
glDrawElements (GL_LINE_STRIP, pObject->NLineNodes(),
- GL_UNSIGNED_INT, pObject->LineNode(0));
+ aType, pObject->mypLines);
}
}
+
}
+
*/
Standard_EXPORT virtual Standard_Boolean
IsEqual (const Handle_NIS_Drawer& theOth)const;
-private:
- Quantity_Color myColor[4];
+
+protected:
+ /**
+ * If myPolygonAsLineLoop is true then draw polygons of the object
+ * in the mode GL_LINE_LOOP instead of GL_POLYGON in the case if no filling
+ * was requested. This will eliminate the bug with Intel integrated graphic
+ * cards (e.g. 945G Express) for the sake of polygon offset functionality.
+ */
+ Standard_Boolean myPolygonAsLineLoop;
+
+ Quantity_Color myColor[5];
Standard_ShortReal myLineWidth;
Standard_Boolean myIsDrawPolygons;
+ unsigned int myPolygonType;
friend class NIS_Triangulated;
#include <NIS_InteractiveObject.hxx>
#include <gp_Ax1.hxx>
#include <Visual3d_View.hxx>
+#include <Bnd_B2f.hxx>
+#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
#ifdef WNT
#include <Windows.h>
#endif
NIS_View::NIS_View (const Handle(V3d_Viewer)& theViewer,
const Handle(Aspect_Window)& theWindow)
- : V3d_OrthographicView (theViewer)
+ : V3d_OrthographicView (theViewer),
+ myIsTopHilight(Standard_False),
+ myDoHilightSelected(Standard_True)
{
- if (!theWindow.IsNull()) {
- const Aspect_GraphicCallbackProc aCallback = &MyCallback;
- V3d_View::SetWindow (theWindow, NULL, aCallback, this);
- }
+ if (!theWindow.IsNull())
+ V3d_View::SetWindow (theWindow, NULL, &MyCallback, this);
}
//=======================================================================
void NIS_View::SetWindow(const Handle(Aspect_Window) &theWindow)
{
- const Aspect_GraphicCallbackProc aCallback = &MyCallback;
- V3d_View::SetWindow (theWindow, NULL, aCallback, this);
+ V3d_View::SetWindow (theWindow, NULL, &MyCallback, this);
}
// //=======================================================================
myContexts.Remove (anIter);
break;
}
+
+ NCollection_Map<Handle_NIS_Drawer>::Iterator anIterD (theCtx->GetDrawers ());
+ for (; anIterD.More(); anIterD.Next()) {
+ const Handle(NIS_Drawer)& aDrawer = anIterD.Value();
+ if (aDrawer.IsNull() == Standard_False) {
+ aDrawer->UpdateExListId(this);
+ }
+ }
}
//=======================================================================
//purpose :
//=======================================================================
-void NIS_View::FitAll3d ()
+Standard_Boolean NIS_View::FitAll3d (const Quantity_Coefficient theCoef)
+{
+ Standard_Boolean aResult(Standard_False);
+ /*
+ Standard_Integer aLimp[4] = { 1000000, -1000000, 1000000, -1000000 };
+ GetBndBox( aLimp[0], aLimp[1], aLimp[2], aLimp[3] );
+ if (aLimp[1] > -1000000 && aLimp[3] > -1000000 &&
+ aLimp[0] < aLimp[1] && aLimp[2] < aLimp[3])
+ {
+ // Scale the view
+ WindowFit (aLimp[0], aLimp[2], aLimp[1], aLimp[3]);
+ aResult = Standard_True;
+ }
+ */
+
+ Bnd_B3f aBox = GetBndBox();
+
+ // Check that the box is not empty
+ if (aBox.IsVoid() == Standard_False && MyView->IsDefined() == Standard_True) {
+ // Convert the 3D box to 2D representation in view coordinates
+ Standard_Real Umin,Umax,Vmin,Vmax,U,V,W;
+ gp_XYZ aCoord;
+
+ const gp_XYZ aCorner[2] = { aBox.CornerMin(), aBox.CornerMax() };
+
+ Standard_Boolean doFit = Standard_True;
+ while (doFit) {
+
+ for (Standard_Integer i = 0; i < 8; i++) {
+ if (i & 0x1) aCoord.SetX (aCorner[0].X());
+ else aCoord.SetX (aCorner[1].X());
+ if (i & 0x2) aCoord.SetY (aCorner[0].Y());
+ else aCoord.SetY (aCorner[1].Y());
+ if (i & 0x4) aCoord.SetZ (aCorner[0].Z());
+ else aCoord.SetZ (aCorner[1].Z());
+
+ MyView->Projects(aCoord.X(), aCoord.Y(), aCoord.Z(), U, V, W);
+ if (i) {
+ Umin = Min(Umin, U); Umax = Max(Umax, U);
+ Vmin = Min(Vmin, V); Vmax = Max(Vmax, V);
+ }
+ else {
+ Umin = Umax = U;
+ Vmin = Vmax = V;
+ }
+ }
+
+ if ( (Umax > Umin) && (Vmax > Vmin) ) {
+ Standard_Real OldUmin,OldUmax,OldVmin,OldVmax;
+ MyViewMapping.WindowLimit(OldUmin, OldVmin, OldUmax, OldVmax);
+ Standard_Real DxvOld = Abs(OldUmax - OldUmin);
+
+ // make a margin
+ Standard_Real Xrp, Yrp, DxvNew, DyvNew;
+
+ DxvNew = Abs(Umax - Umin); DyvNew = Abs(Vmax - Vmin);
+ DxvNew *= (1. + theCoef);
+ DyvNew *= (1. + theCoef);
+
+ Standard_Real aRatio = DxvNew / DxvOld;
+
+ Xrp = (Umin + Umax)/2. ; Yrp = (Vmin + Vmax)/2. ;
+ Umin = Xrp - DxvNew/2. ; Umax = Xrp + DxvNew/2. ;
+ Vmin = Yrp - DyvNew/2. ; Vmax = Yrp + DyvNew/2. ;
+
+ // fit view
+ FitAll(Umin, Vmin, Umax, Vmax);
+
+ // ratio 1e+6 often gives calculation error(s), reduce it
+ // if (aRatio < 1e+6) doFit = Standard_False;
+ if (aRatio < 100) doFit = Standard_False;
+ aResult = Standard_True;
+ }
+ else doFit = Standard_False;
+
+ }
+ }
+
+ return aResult;
+}
+
+//=======================================================================
+//function : GetBndBox
+//purpose :
+//=======================================================================
+
+Bnd_B3f NIS_View::GetBndBox() const
{
// Calculate the 3D bounding box of visible objects
// in all interactive contexts
}
}
- if (aBox.IsVoid()) {
- // No NIS objects displays, run the compatible method of V3d_View
- FitAll();
- return;
- }
-
// Take the bounding box of AIS objects displayed in the view
Standard_Real aVal[6];
View()->MinMaxValues(aVal[0], aVal[1], aVal[2], aVal[3], aVal[4], aVal[5]);
aBox.Add (gp_XYZ (aVal[3], aVal[4], aVal[5]));
}
+ return aBox;
+}
+
+//=======================================================================
+//function : GetBndBox
+//purpose :
+//=======================================================================
+
+void NIS_View::GetBndBox( Standard_Integer& theXMin, Standard_Integer& theXMax,
+ Standard_Integer& theYMin, Standard_Integer& theYMax ) const
+{
+ theXMin = theYMin = 0;
+ theXMax = theYMax = -1;
+
+ Bnd_B3f aBox = GetBndBox();
+
// Check that the box is not empty
if (aBox.IsVoid() == Standard_False) {
// Convert the 3D box to 2D representation in pixel coordinates
if (aLimp[0] < aLimp[1] && aLimp[2] < aLimp[3])
{
// Scale the view
- WindowFit (aLimp[0], aLimp[2], aLimp[1], aLimp[3]);
- return;
+ // WindowFit (aLimp[0], aLimp[2], aLimp[1], aLimp[3]);
+ theXMin = aLimp[0];
+ theXMax = aLimp[1];
+ theYMin = aLimp[2];
+ theYMax = aLimp[3];
}
}
}
}
#endif //IS_DISABLED
-// glEnable(GL_COLOR_MATERIAL);
GLboolean isDepthWriteMask, isDepthTest;
glGetBooleanv(GL_DEPTH_WRITEMASK,&isDepthWriteMask);
glGetBooleanv(GL_DEPTH_TEST,&isDepthTest);
glClear(GL_DEPTH_BUFFER_BIT);
}
+ TColStd_MapIteratorOfPackedMapOfInteger anIterM(thisView->myExListId);
+ for (; anIterM.More(); anIterM.Next())
+ if (anIterM.Key() != 0) {
+#ifdef ARRAY_LISTS
+ glDeleteLists (anIterM.Key(), 5);
+#else
+ glDeleteLists (anIterM.Key(), 1);
+ }
+#endif
+ thisView->myExListId.Clear();
+
for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Normal);
- for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
- anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Transparent);
+
+ // #818151 - selected object is hidden by covered unselected one
+ // display hilighted objects always above the rest ones
+ if (thisView->myIsTopHilight == Standard_True) {
+ glDepthFunc(GL_ALWAYS);
+ }
+
for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Hilighted);
for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
anIter.Value()->redraw (thisView, NIS_Drawer::Draw_DynHilighted);
+ for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
+ anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Transparent);
+
+ // draw top objects always above
+ if (thisView->myIsTopHilight == Standard_False) {
+ glDepthFunc(GL_ALWAYS);
+ }
+
+ for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
+ anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Top);
return 0;
}
void NIS_View::DynamicHilight (const Standard_Integer theX,
const Standard_Integer theY)
{
+ myDetected.Clear();
const Handle(NIS_InteractiveObject) aSelected = Pick (theX, theY);
// ASV: if at least one Context returns IsSelectable()==False,
if (aSelected != myDynHilighted) {
const Handle(NIS_View) aView (this);
if (myDynHilighted.IsNull() == Standard_False)
- myDynHilighted->GetDrawer()->SetDynamicHilighted (Standard_False,
- myDynHilighted, aView);
- if (aSelected.IsNull())
+ if (myDynHilighted->GetDrawer().IsNull() == Standard_False)
+ myDynHilighted->GetDrawer()->SetDynamicHilighted(Standard_False,
+ myDynHilighted, aView);
+
+ // 30.07.10 - NKV - synchronize behaviour with AIS interactive context (if need)
+ if (aSelected.IsNull() ||
+ (myDoHilightSelected == Standard_False &&
+ aSelected->GetDrawer()->GetContext()->IsSelected(aSelected)))
+ {
myDynHilighted.Nullify();
+ }
else {
aSelected->GetDrawer()->SetDynamicHilighted (Standard_True,
aSelected, aView);
{
if (theObj == myDynHilighted && theObj.IsNull() == Standard_False) {
const Handle(NIS_View) aView (this);
- myDynHilighted->GetDrawer()->SetDynamicHilighted (Standard_False,
- myDynHilighted, aView);
+ if (myDynHilighted->GetDrawer().IsNull() == Standard_False)
+ myDynHilighted->GetDrawer()->SetDynamicHilighted (Standard_False,
+ myDynHilighted, aView);
myDynHilighted.Nullify();
Redraw();
}
void NIS_View::Select (const Standard_Integer theX,
const Standard_Integer theY,
- const Standard_Boolean isForceMultiple)
+ const Standard_Boolean isForceMultiple,
+ const Standard_Boolean theRedraw)
{
+ myDetected.Clear();
const Handle(NIS_InteractiveObject) aSelected = Pick (theX, theY);
NCollection_List<NIS_InteractiveContext *>::Iterator anIter (myContexts);
for (; anIter.More(); anIter.Next())
const Handle(NIS_Drawer)& aDrawer = aSelected->GetDrawer();
aDrawer->SetDynamicHilighted (Standard_False, aSelected, this);
}
- Redraw();
+ if (theRedraw) Redraw();
}
//=======================================================================
const Standard_Integer theXmax,
const Standard_Integer theYmax,
const Standard_Boolean isForceMult,
- const Standard_Boolean isFullyIncluded)
+ const Standard_Boolean isFullyIncluded,
+ const Standard_Boolean theRedraw)
{
+ myDetected.Clear();
Standard_Real anX, anY, aZ;
if (theXmin == theXmax || theYmin == theYmax)
return;
pCtx->selectObjects (mapSelected, aBoxSel, aTrfInv, aTrf, isFullyIncluded);
pCtx->ProcessSelection (mapSelected, isForceMult);
}
- Redraw();
+ if (theRedraw) Redraw();
}
+//=======================================================================
+//function : Select
+//purpose : Selection by polygon
+//=======================================================================
+
+void NIS_View::Select (const NCollection_List<gp_XY> &thePolygon,
+ const Standard_Boolean isForceMult,
+ const Standard_Boolean isFullyIncluded,
+ const Standard_Boolean theRedraw)
+{
+ myDetected.Clear();
+ if (thePolygon.IsEmpty())
+ return;
+
+ Standard_Real anX, anY, aZ;
+
+ //Transformed box corresponding to the selected rectangle
+ Proj (anX, anY, aZ); // vector orthogonal to the view plane
+ const gp_Dir aProj (anX, anY, aZ);
+
+ const gp_XY &aPf = thePolygon.First();
+ // 3D point for the 3D coordinates
+ Convert((Standard_Integer) aPf.X(), (Standard_Integer) aPf.Y(), anX, anY, aZ);
+ const gp_Pnt anEye (anX, anY, aZ);
+
+ // 3D point for the 3D coordinates
+ const gp_XY &aPl = thePolygon.Last();
+
+ Convert((Standard_Integer) aPl.X(), (Standard_Integer) aPl.Y(), anX, anY, aZ);
+
+ // Compute transformation.
+ const gp_XYZ anXdir (gp_XYZ(anX, anY, aZ) - anEye.XYZ());
+ const gp_Ax3 anAx3 (anEye, aProj, anXdir);
+ gp_Trsf aTrf;
+ aTrf.SetTransformation (anAx3);
+ const gp_Trsf aTrfInv = aTrf.Inverted();
+
+ // Prepare list of 2d points of selection polygon.
+ NCollection_List<gp_XY> aPoints;
+ NCollection_List<gp_XY>::Iterator anIter(thePolygon);
+ Bnd_B2f aPolyBox;
+
+ for (; anIter.More(); anIter.Next()) {
+ const gp_XY &aP = anIter.Value();
+
+ Convert((Standard_Integer) aP.X(), (Standard_Integer) aP.Y(), anX, anY, aZ);
+ gp_XYZ aP3d(anX, anY, aZ);
+
+ aTrf.Transforms(aP3d);
+
+ gp_XY aP2d(aP3d.X(), aP3d.Y());
+
+ aPoints.Append(aP2d);
+ aPolyBox.Add(aP2d);
+ }
+
+ TColStd_PackedMapOfInteger mapSelected;
+ NCollection_List<NIS_InteractiveContext *>::Iterator anIterC(myContexts);
+
+ for (; anIterC.More(); anIterC.Next()) {
+ NIS_InteractiveContext * pCtx = anIterC.Value();
+ mapSelected.Clear();
+ pCtx->selectObjects (mapSelected, aPoints, aPolyBox, aTrf, isFullyIncluded);
+ pCtx->ProcessSelection (mapSelected, isForceMult);
+ }
+
+ if (theRedraw) Redraw();
+}
//=======================================================================
//function : Pick
//purpose :
//=======================================================================
-Handle_NIS_InteractiveObject NIS_View::Pick
- (const Standard_Integer theX,
- const Standard_Integer theY) const
+Handle_NIS_InteractiveObject NIS_View::Pick (const Standard_Integer theX,
+ const Standard_Integer theY)
{
// Find the ray passing through the clicked point in the view window.
Standard_Real anX, anY, aZ, anOver;
Handle_NIS_InteractiveObject NIS_View::Pick
(const gp_Ax1& theAxis,
const Standard_Real theOver,
- const Standard_Boolean isOnlySelectable) const
+ const Standard_Boolean isOnlySelectable)
{
+ typedef NCollection_List<NIS_InteractiveContext::DetectedEnt> LstDetected;
Standard_Real aDistance (0.1 * RealLast());
Handle(NIS_InteractiveObject) aSelected, aTmpSel;
+ LstDetected aDetected;
NCollection_List<NIS_InteractiveContext *>::Iterator anIterC (myContexts);
for (; anIterC.More(); anIterC.Next()) {
const Standard_Real aDist =
- anIterC.Value()->selectObject (aTmpSel, theAxis, theOver,
+ anIterC.Value()->selectObject (aTmpSel, aDetected, theAxis, theOver,
isOnlySelectable);
if (aDist < aDistance) {
aDistance = aDist;
aSelected = aTmpSel;
}
}
+
+ // simple iterating is enough to create list of detected objects
+ // in the order of increasing distance
+ myDetected.Clear();
+ for (LstDetected::Iterator anIt(aDetected); anIt.More(); anIt.Next())
+ myDetected.Append(anIt.Value().PObj);
+
return aSelected;
}
+
#include <V3d_OrthographicView.hxx>
#include <Standard_DefineHandle.hxx>
#include <NCollection_List.hxx>
+#include <NCollection_Vector.hxx>
+#include <Bnd_B3f.hxx>
+#include <TColStd_PackedMapOfInteger.hxx>
+#include <gp_XY.hxx>
class NIS_InteractiveContext;
class gp_Ax1;
*/
Standard_EXPORT void SetWindow(const Handle_Aspect_Window &theWindow);
+ /**
+ * Indicate whether to draw hilighted objects on top of all other ones
+ */
+ inline void SetHilightOnTop(const Standard_Boolean theTop = Standard_True)
+ { myIsTopHilight = theTop; }
+
+ /**
+ * Indicate whether to hilight selected object dynamically
+ * By default dynamic hilight works on all objects independently on its
+ * selected/non-selected state.
+ * This behaviour differs from the behaviour of AIS interactive context,
+ * that doesn't hilight dynamically (on mouse movements) selected objects.
+ * In the case both context are used in the same view the behaviour of both
+ * context can be made consistent by setting this flag to False
+ */
+ inline void SetDynHilightSelected (const Standard_Boolean
+ theHilight = Standard_True)
+ { myDoHilightSelected = theHilight; }
+
/**
* Zoom the view to fit to visible objects size and positions.
+ * @param theCoef
+ * Relative margin in both X and Y dimensions. For example, value 1.0
+ * will fit to twice the actual size.
+ * @return
+ * True if operation performed, False if failed (most likely because of
+ * very big actual scale)
+ */
+ Standard_EXPORT Standard_Boolean FitAll3d (const Quantity_Coefficient theCoef
+ = 0.01);
+
+ /**
+ * Gets bounding box covering objects displayed in viewer.
*/
- Standard_EXPORT void FitAll3d ();
+ Standard_EXPORT Bnd_B3f GetBndBox() const;
+
+ /**
+ * Gets bounding box covering objects displayed in viewer.
+ * If operation is fails when Xmax < Xmin abd Ymax < Ymin
+ */
+ Standard_EXPORT void GetBndBox(Standard_Integer& theXMin,
+ Standard_Integer& theXMax,
+ Standard_Integer& theYMin,
+ Standard_Integer& theYMax ) const;
// /**
// * Destructor.
*/
Standard_EXPORT void DynamicUnhilight(const Handle_NIS_InteractiveObject&);
+ /**
+ * Unhilights the currently hilighted object.
+ */
+ inline void DynamicUnhilight() { DynamicUnhilight(myDynHilighted); }
+
/**
* Set or unset the selected (hilighted) state of the object that is under
* the coordinates theX, theY.
* @param theX
* X coordinate of the view window
- * @param theX
+ * @param theY
* X coordinate of the view window
* @param isForceMult
* True if the effect of multi-Selection should be forced (e.g., when Shift
* is pressed).
+ * @param theRedraw
+ * True to redraw view automatically (default value).
*/
Standard_EXPORT void Select (const Standard_Integer theX,
const Standard_Integer theY,
const Standard_Boolean isForceMult
- = Standard_False);
+ = Standard_False,
+ const Standard_Boolean theRedraw
+ = Standard_True);
/**
* Set or unset the selected (hilighted) state of the objects that are
* True if only those objects are processed that are fully inside the
* selection rectangle. False if objects fully or partially included in
* the rectangle are processed.
+ * @param theRedraw
+ * True to redraw view automatically (default value).
*/
Standard_EXPORT void Select (const Standard_Integer theXmin,
const Standard_Integer theYmin,
const Standard_Boolean isForceMult
= Standard_False,
const Standard_Boolean isFullyIncluded
- = Standard_False);
+ = Standard_False,
+ const Standard_Boolean theRedraw
+ = Standard_True);
+
+ /**
+ * Set or unset the selected (hilighted) state of the objects that are
+ * intersected by 2D polygon in the view
+ * @param thePolygon
+ * defines the vertices of a free-form closed polygon without
+ * self-intersections. The last point should not coincide with the first
+ * point of the list. Points are interpreted as X and Y integer coordinates
+ * of the view window. Any two neighbor points should not be confused.
+ * @param isForceMult
+ * True if the effect of multi-Selection should be forced (e.g., when Shift
+ * is pressed).
+ * @param isFullyIncluded
+ * True if only those objects are processed that are fully inside the
+ * selection rectangle. False if objects fully or partially included in
+ * the rectangle are processed.
+ * @param theRedraw
+ * True to redraw view automatically (default value).
+ */
+ Standard_EXPORT void Select (const NCollection_List<gp_XY> &thePolygon,
+ const Standard_Boolean isForceMult
+ = Standard_False,
+ const Standard_Boolean isFullyIncluded
+ = Standard_False,
+ const Standard_Boolean theRedraw
+ = Standard_True);
/**
* Interactive selection by mouse click. Selection itself is performed in each
*/
Standard_EXPORT Handle_NIS_InteractiveObject
Pick (const Standard_Integer theX,
- const Standard_Integer theY) const;
+ const Standard_Integer theY);
/**
* Interactive selection by mouse click. Selection itself is performed in each
* 3D axis for objects selection
* @param theOver
* Overlap for the selecting axis
- * @param isOnlySelectable
+ * @param isOnlySel
* If False, any displayed object can be picked, otherwise only selectable
* ones.
* @return
* all contexts attached to this View.
*/
Standard_EXPORT Handle_NIS_InteractiveObject
- Pick (const gp_Ax1& theAxis,
- const Standard_Real theOver,
- const Standard_Boolean isOnlySelectable) const;
+ Pick (const gp_Ax1& theAxis,
+ const Standard_Real theOver,
+ const Standard_Boolean isOnlySel);
+
+ /**
+ * Gets all objects detected by last call of Pick() method
+ */
+ inline NCollection_Vector<NIS_InteractiveObject *> GetDetected() const
+ { return myDetected; }
+
+ /**
+ * Obtain the IDs of ex-lists.
+ */
+ inline TColStd_PackedMapOfInteger& GetExListId ()
+ { return myExListId; }
protected:
// ---------- PROTECTED METHODS ----------
NCollection_List<NIS_InteractiveContext *> myContexts;
Handle_NIS_InteractiveObject myDynHilighted;
+ Standard_Boolean myIsTopHilight : 1;
+ Standard_Boolean myDoHilightSelected : 1;
+ NCollection_Vector<NIS_InteractiveObject *> myDetected;
+ TColStd_PackedMapOfInteger myExListId;
friend class NIS_InteractiveContext;
} else if (it.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
const Handle(NIS_InteractiveObject) anObj =
Handle(NIS_InteractiveObject)::DownCast (it.Key1());
- TheNISContext()->Remove(anObj,Standard_False);
+ TheNISContext()->Remove(anObj);
}
it.Next();
}
TheAISContext()->UpdateCurrentViewer();
- TheNISContext()->UpdateViews();
+// TheNISContext()->UpdateViews();
GetMapOfAIS().Clear();
}
}
} else if (it.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
const Handle(NIS_InteractiveObject) aShape =
Handle(NIS_InteractiveObject)::DownCast(it.Key1());
- TheNISContext()->Erase(aShape,Standard_False);
+ TheNISContext()->Erase(aShape);
}
it.Next();
}
Handle(AIS_InteractiveObject)::DownCast (anObj);
TheAISContext()->Display(aShape, Standard_False);
} else if (anObj->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
- const Handle(NIS_InteractiveObject) aShape =
+ Handle(NIS_InteractiveObject) aShape =
Handle(NIS_InteractiveObject)::DownCast (anObj);
- TheNISContext()->Display(aShape, 0L, Standard_False);
+ TheNISContext()->Display(aShape);
}
}
}
TheAISContext() ->UpdateCurrentViewer();
- TheNISContext() ->UpdateViews();
+// TheNISContext() ->UpdateViews();
}
return 0;
}
} else if (it.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
const Handle(NIS_InteractiveObject) aShape =
Handle(NIS_InteractiveObject)::DownCast(it.Key1());
- TheNISContext()->Erase(aShape,Standard_False);
+ TheNISContext()->Erase(aShape);
}
it.Next();
}
TheAISContext() ->UpdateCurrentViewer();
- TheNISContext()->UpdateViews();
+// TheNISContext()->UpdateViews();
}
//===============================================================
} else if (anObj->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
const Handle(NIS_InteractiveObject) aShape =
Handle(NIS_InteractiveObject)::DownCast (anObj);
- TheNISContext()->Erase(aShape,Standard_False);
+ TheNISContext()->Erase(aShape);
}
}
}
TheAISContext() ->UpdateCurrentViewer();
- TheNISContext() ->UpdateViews();
+// TheNISContext() ->UpdateViews();
}
return 0;
}
} else if (it.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
const Handle(NIS_InteractiveObject) aShape =
Handle(NIS_InteractiveObject)::DownCast(it.Key1());
- TheNISContext()->Erase(aShape,Standard_False);
+ TheNISContext()->Erase(aShape);
}
it.Next();
}
TheAISContext() ->UpdateCurrentViewer();
- TheNISContext() ->UpdateViews();
+// TheNISContext() ->UpdateViews();
return 0;
}
} else if (it.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
const Handle(NIS_InteractiveObject) aShape =
Handle(NIS_InteractiveObject)::DownCast(it.Key1());
- TheNISContext()->Erase(aShape,Standard_False);
+ TheNISContext()->Erase(aShape);
}
it.Next();
}
Handle(AIS_InteractiveObject)::DownCast(it.Key1());
TheAISContext()->Display(aShape, Standard_False);
} else if (it.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
- const Handle(NIS_InteractiveObject) aShape =
+ Handle(NIS_InteractiveObject) aShape =
Handle(NIS_InteractiveObject)::DownCast(it.Key1());
- TheNISContext()->Display(aShape, 0L, Standard_False);
+ TheNISContext()->Display(aShape);
}
it.Next();
}
TheAISContext() ->UpdateCurrentViewer();
- TheNISContext() ->UpdateViews();
+// TheNISContext() ->UpdateViews();
}
return 0;
}
} else if (anObj->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
Handle(NIS_InteractiveObject) aShape =
Handle(NIS_InteractiveObject)::DownCast(anObj);
- TheNISContext()->Display(aShape, 0L, Standard_False);
+ TheNISContext()->Display(aShape);
}
}
else { // Create the AIS_Shape from a name
}
// Upadate the screen and redraw the view
TheAISContext()->UpdateCurrentViewer();
- TheNISContext()->UpdateViews();
+// TheNISContext()->UpdateViews();
return 0;
}