#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;
}
+