0031440: Visualization - Impossible to make common behaviour for multi-selection...
authormzernova <mzernova@opencascade.com>
Tue, 14 Apr 2020 21:54:32 +0000 (00:54 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 23 Apr 2020 07:44:30 +0000 (10:44 +0300)
A special mode for the selecting by polygon is added to select only completely overlapping objects.

In order to track the sensitives that were included completely by defined polygon, the boundary points of the polygonal frustrum are stored in the variable myBoundaryPoints.

If an sensitive intersects with at least one of the frustrums from myFrustums, then checking whether this object intersects with borders using the isIntersectBoundary method; if not, then the sensitive were included completely by defined polygon.

Because the polygon can be concave, then to check the sensitive were included completely by defined polygon, it is not enough to check of all its points, it is necessary that the edges of the sensitive do not intersect polygonal frustrum. To do this, for polygonal selection, a call to the Overlaps method for a point was replaced by a call to a segment where necessary.

bugs/vis/bug31440: test case added

14 files changed:
src/AIS/AIS_ViewController.cxx
src/MeshVS/MeshVS_SensitiveQuad.cxx
src/Select3D/Select3D_SensitiveCircle.cxx
src/Select3D/Select3D_SensitivePoly.cxx
src/Select3D/Select3D_SensitiveSegment.cxx
src/Select3D/Select3D_SensitiveTriangle.cxx
src/Select3D/Select3D_SensitiveTriangulation.cxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx
src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx
src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/bugs/vis/bug27008
tests/bugs/vis/bug31440 [new file with mode: 0644]

index 87a4864..d4e79f7 100644 (file)
@@ -2210,7 +2210,6 @@ void AIS_ViewController::handleSelectionPoly (const Handle(AIS_InteractiveContex
             aPolyIter.ChangeValue() = gp_Pnt2d (aNewPnt.x(), -aNewPnt.y());
           }
 
-          theCtx->MainSelector()->AllowOverlapDetection (false);
           if (myGL.Selection.IsXOR)
           {
             theCtx->ShiftSelect (aPolyline, theView, false);
@@ -2219,6 +2218,7 @@ void AIS_ViewController::handleSelectionPoly (const Handle(AIS_InteractiveContex
           {
             theCtx->Select (aPolyline, theView, false);
           }
+          theCtx->MainSelector()->AllowOverlapDetection (false);
         }
       }
 
index 454d9da..e12f3f7 100644 (file)
@@ -67,6 +67,12 @@ Standard_Boolean MeshVS_SensitiveQuad::Matches (SelectBasics_SelectingVolumeMana
 {
   if (!theMgr.IsOverlapAllowed()) // check for inclusion
   {
+    if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+    {
+      SelectBasics_PickResult aDummy;
+      return theMgr.Overlaps (myVertices[0], myVertices[1], myVertices[2], Select3D_TOS_INTERIOR, aDummy)
+          && theMgr.Overlaps (myVertices[0], myVertices[2], myVertices[3], Select3D_TOS_INTERIOR, aDummy);
+    }
     for (Standard_Integer aPntIdx = 0; aPntIdx < 4; ++aPntIdx)
     {
       if (!theMgr.Overlaps (myVertices[aPntIdx]))
index 3f3f14f..82bf115 100644 (file)
@@ -211,6 +211,11 @@ Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolume
     Points3D (anArrayOfPnt);
     if (!theMgr.IsOverlapAllowed())
     {
+      if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+      {
+        SelectBasics_PickResult aDummy;
+        return theMgr.Overlaps (anArrayOfPnt, mySensType, aDummy);
+      }
       for (Standard_Integer aPntIdx = anArrayOfPnt->Lower(); aPntIdx <= anArrayOfPnt->Upper(); ++aPntIdx)
       {
         if (!theMgr.Overlaps (anArrayOfPnt->Value(aPntIdx)))
index bca131d..d582fef 100644 (file)
@@ -254,6 +254,11 @@ Standard_Boolean Select3D_SensitivePoly::elementIsInside (SelectBasics_Selecting
   }
 
   const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx);
+  if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+  {
+    SelectBasics_PickResult aDummy;
+    return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0), myPolyg.Pnt3d (aSegmentIdx + 1), aDummy);
+  }
   return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0))
       && theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 1));
 }
index 5207411..c402199 100644 (file)
@@ -45,6 +45,10 @@ Standard_Boolean Select3D_SensitiveSegment::Matches (SelectBasics_SelectingVolum
 {
   if (!theMgr.IsOverlapAllowed()) // check for inclusion
   {
+    if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+    {
+      return theMgr.Overlaps (myStart, myEnd, thePickResult);
+    }
     return theMgr.Overlaps (myStart, thePickResult) && theMgr.Overlaps (myEnd, thePickResult);
   }
 
index 2b14690..47291ad 100644 (file)
@@ -50,6 +50,11 @@ Standard_Boolean Select3D_SensitiveTriangle::Matches (SelectBasics_SelectingVolu
 {
   if (!theMgr.IsOverlapAllowed())
   {
+    if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+    {
+      SelectBasics_PickResult aDummy;
+      return theMgr.Overlaps (myPoints[0], myPoints[1], myPoints[2], mySensType, aDummy);
+    }
     return theMgr.Overlaps (myPoints[0])
         && theMgr.Overlaps (myPoints[1])
         && theMgr.Overlaps (myPoints[2]);
index e80dbc6..ad76770 100644 (file)
@@ -314,6 +314,11 @@ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_
   {
     const gp_Pnt& aSegmPnt1 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 1));
     const gp_Pnt& aSegmPnt2 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 2));
+    if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+    {
+      SelectBasics_PickResult aDummy;
+      return theMgr.Overlaps (aSegmPnt1, aSegmPnt2, aDummy);
+    }
     return theMgr.Overlaps (aSegmPnt1) && theMgr.Overlaps (aSegmPnt2);
   }
   else
@@ -324,6 +329,11 @@ Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_
     const gp_Pnt& aPnt1 = myTriangul->Nodes().Value (aNode1);
     const gp_Pnt& aPnt2 = myTriangul->Nodes().Value (aNode2);
     const gp_Pnt& aPnt3 = myTriangul->Nodes().Value (aNode3);
+    if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
+    {
+      SelectBasics_PickResult aDummy;
+      return theMgr.Overlaps (aPnt1, aPnt2, aPnt3, mySensType, aDummy);
+    }
     return theMgr.Overlaps (aPnt1)
         && theMgr.Overlaps (aPnt2)
         && theMgr.Overlaps (aPnt3);
index 03cbffa..89230c7 100644 (file)
@@ -230,6 +230,7 @@ void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const TColgp_Array1
     return;
 
   mySelectingVolumes[FrustumSet]->Build (thePoints);
+  Handle(SelectMgr_TriangularFrustumSet)::DownCast (mySelectingVolumes[FrustumSet])->SetAllowOverlapDetection (IsOverlapAllowed());
 }
 
 //=======================================================================
@@ -402,7 +403,7 @@ void SelectMgr_SelectingVolumeManager::AllowOverlapDetection (const Standard_Boo
 //=======================================================================
 Standard_Boolean SelectMgr_SelectingVolumeManager::IsOverlapAllowed() const
 {
-  return myActiveSelectionType != Box || myToAllowOverlap;
+  return myToAllowOverlap || myActiveSelectionType == Point;
 }
 
 //=======================================================================
index 5b89bbd..6b3fe78 100644 (file)
@@ -158,7 +158,6 @@ public:
   //! Throws exception if active selection type is not Point.
   Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE;
 
-  //! Is used for rectangular selection only
   //! If theIsToAllow is false, only fully included sensitives will be detected, otherwise the algorithm will
   //! mark both included and overlapped entities as matched
   Standard_EXPORT virtual void AllowOverlapDetection (const Standard_Boolean theIsToAllow);
index 7da5398..78a5d72 100644 (file)
 
 #define MEMORY_BLOCK_SIZE 512 * 7
 
+// =======================================================================
+// function : SelectMgr_TriangularFrustumSet
+// purpose  :
+// =======================================================================
+SelectMgr_TriangularFrustumSet::SelectMgr_TriangularFrustumSet()
+:  myToAllowOverlap (Standard_False)
+{}
+
 // =======================================================================
 // function : BuildSelectingVolume
 // purpose  : Meshes polygon bounded by polyline. Than organizes a set of
@@ -34,14 +42,20 @@ void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoint
   myFrustums.Clear();
 
   Handle(NCollection_IncAllocator) anAllocator = new NCollection_IncAllocator (MEMORY_BLOCK_SIZE);
-  Handle(BRepMesh_DataStructureOfDelaun) aMeshStructure = new BRepMesh_DataStructureOfDelaun(anAllocator);
+  Handle(BRepMesh_DataStructureOfDelaun) aMeshStructure = new BRepMesh_DataStructureOfDelaun (anAllocator);
   Standard_Integer aPtsLower = thePoints.Lower();
   Standard_Integer aPtsUpper = thePoints.Upper();
   IMeshData::VectorOfInteger anIndexes(aPtsUpper - aPtsLower, anAllocator);
+  myBoundaryPoints.Resize (aPtsLower, aPtsLower + 2 * (thePoints.Size()) - 1, Standard_False);
+
   for (Standard_Integer aPtIdx = aPtsLower; aPtIdx <= aPtsUpper; ++aPtIdx)
   {
-    BRepMesh_Vertex aVertex(thePoints.Value(aPtIdx).XY(), aPtIdx, BRepMesh_Frontier);
-    anIndexes.Append(aMeshStructure->AddNode(aVertex));
+    BRepMesh_Vertex aVertex (thePoints.Value (aPtIdx).XY(), aPtIdx, BRepMesh_Frontier);
+    anIndexes.Append (aMeshStructure->AddNode (aVertex));
+    const gp_Pnt aNearPnt = myBuilder->ProjectPntOnViewPlane (aVertex.Coord().X(), aVertex.Coord().Y(), 0.0);
+    const gp_Pnt aFarPnt  = myBuilder->ProjectPntOnViewPlane (aVertex.Coord().X(), aVertex.Coord().Y(), 1.0);
+    myBoundaryPoints.SetValue (aPtIdx, aNearPnt);
+    myBoundaryPoints.SetValue (aPtIdx + thePoints.Size(), aFarPnt);
   }
 
   Standard_Real aPtSum = 0;
@@ -118,6 +132,14 @@ Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustumSet::ScaleAndTransform
     aRes->myFrustums.Append (Handle(SelectMgr_TriangularFrustum)::DownCast (anIter.Value()->ScaleAndTransform (theScale, theTrsf)));
   }
 
+  aRes->myBoundaryPoints.Resize (myBoundaryPoints.Lower(), myBoundaryPoints.Upper(), Standard_False);
+  for (Standard_Integer anIdx = myBoundaryPoints.Lower(); anIdx <= myBoundaryPoints.Upper(); anIdx++)
+  {
+    gp_Pnt aPoint = myBoundaryPoints.Value (anIdx);
+    theTrsf.Transforms (aPoint.ChangeCoord());
+    aRes->myBoundaryPoints.SetValue (anIdx, aPoint);
+  }
+
   return aRes;
 }
 
@@ -145,12 +167,43 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const SelectMgr_Vec3&
 // =======================================================================
 Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const SelectMgr_Vec3& theMinPnt,
                                                            const SelectMgr_Vec3& theMaxPnt,
-                                                           Standard_Boolean* /*theInside*/) const
+                                                           Standard_Boolean* theInside) const
 {
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
     if (anIter.Value()->Overlaps (theMinPnt, theMaxPnt, NULL))
-      return Standard_True;
+    {
+      if (myToAllowOverlap || theInside == NULL)
+      {
+        return Standard_True;
+      }
+      else
+      {
+        gp_Pnt aMinMaxPnts[2] = { gp_Pnt (theMinPnt.x(), theMinPnt.y(), theMinPnt.z()),
+                                  gp_Pnt (theMaxPnt.x(), theMaxPnt.y(), theMaxPnt.z())};
+
+        gp_Pnt anOffset[3] = { gp_Pnt (aMinMaxPnts[1].X() - aMinMaxPnts[0].X(), 0.0, 0.0),
+                               gp_Pnt (0.0, aMinMaxPnts[1].Y() - aMinMaxPnts[0].Y(), 0.0),
+                               gp_Pnt (0.0, 0.0, aMinMaxPnts[1].Z() - aMinMaxPnts[0].Z()) };
+
+        Standard_Integer aSign = 1;
+        for (Standard_Integer aPntsIdx = 0; aPntsIdx < 2; aPntsIdx++)
+        {
+          for (Standard_Integer aCoordIdx = 0; aCoordIdx < 3; aCoordIdx++)
+          {
+            gp_Pnt anOffsetPnt = aMinMaxPnts [aPntsIdx].XYZ() + aSign * anOffset [aCoordIdx].XYZ();
+            if (isIntersectBoundary (aMinMaxPnts [aPntsIdx], anOffsetPnt)
+             || isIntersectBoundary (anOffsetPnt, anOffsetPnt.XYZ() + aSign * anOffset [(aCoordIdx + 1) % 3].XYZ()))
+            {
+              *theInside &= Standard_False;
+              return Standard_True;
+            }
+          }
+          aSign = -aSign;
+        }
+        return Standard_True;
+      }
+    }
   }
 
   return Standard_False;
@@ -185,7 +238,25 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const TColgp_Array1Of
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
     if (anIter.Value()->Overlaps (theArrayOfPts, theSensType, theClipRange, thePickResult))
-      return Standard_True;
+    {
+      if (myToAllowOverlap)
+      {
+        return Standard_True;
+      }
+      else
+      {
+        Standard_Integer aPtsLower = theArrayOfPts.Lower();
+        Standard_Integer aPtsUpper = theArrayOfPts.Upper();
+        for (Standard_Integer anIdx = aPtsLower; anIdx <= aPtsUpper; anIdx++)
+        {
+          if (isIntersectBoundary (theArrayOfPts.Value (anIdx), theArrayOfPts.Value (anIdx < aPtsUpper ? anIdx + 1 : aPtsLower)))
+          {
+            return Standard_False;
+          }
+        }
+        return Standard_True;
+      }
+    }
   }
 
   return Standard_False;
@@ -203,7 +274,20 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const gp_Pnt& thePnt1
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
     if (anIter.Value()->Overlaps (thePnt1, thePnt2, theClipRange, thePickResult))
-      return Standard_True;
+    {
+      if (myToAllowOverlap)
+      {
+        return Standard_True;
+      }
+      else
+      {
+        if (isIntersectBoundary (thePnt1, thePnt2))
+        {
+          return Standard_False;
+        }
+        return Standard_True;
+      }
+    }
   }
 
   return Standard_False;
@@ -223,7 +307,22 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const gp_Pnt& thePnt1
   for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next())
   {
     if (anIter.Value()->Overlaps (thePnt1, thePnt2, thePnt3, theSensType, theClipRange, thePickResult))
-      return Standard_True;
+    {
+      if (myToAllowOverlap)
+      {
+        return Standard_True;
+      }
+      else
+      {
+        if (isIntersectBoundary (thePnt1, thePnt2)
+         || isIntersectBoundary (thePnt2, thePnt3)
+         || isIntersectBoundary (thePnt3, thePnt1))
+        {
+          return Standard_False;
+        }
+        return Standard_True;
+      }
+    }
   }
 
   return Standard_False;
@@ -243,4 +342,83 @@ void SelectMgr_TriangularFrustumSet::GetPlanes (NCollection_Vector<SelectMgr_Vec
   }
 }
 
+//=======================================================================
+// function : SetAllowOverlapDetection
+// purpose  :
+//=======================================================================
+void SelectMgr_TriangularFrustumSet::SetAllowOverlapDetection (const Standard_Boolean theIsToAllow)
+{
+  myToAllowOverlap = theIsToAllow;
+}
+
+//=======================================================================
+// function : isIntersectBoundary
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_TriangularFrustumSet::isIntersectBoundary (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2) const
+{
+  Standard_Integer aFacesNb = myBoundaryPoints.Size() / 2;
+  gp_Vec aDir = thePnt2.XYZ() - thePnt1.XYZ();
+  gp_Pnt anOrig = thePnt1;
+
+  for (Standard_Integer anIdx = myBoundaryPoints.Lower(); anIdx < aFacesNb + myBoundaryPoints.Lower(); anIdx++)
+  {
+    gp_Pnt aFace[4] = { myBoundaryPoints.Value (anIdx),
+                        myBoundaryPoints.Value (anIdx + aFacesNb),
+                        myBoundaryPoints.Value (anIdx % aFacesNb + 1 + aFacesNb),
+                        myBoundaryPoints.Value (anIdx % aFacesNb + 1) };
+
+    if (segmentTriangleIntersection (anOrig, aDir, aFace[0], aFace[1], aFace[2])
+     || segmentTriangleIntersection (anOrig, aDir, aFace[0], aFace[2], aFace[3]))
+    {
+      return Standard_True;
+    }
+  }
+  return Standard_False;
+}
+
+//=======================================================================
+// function : segmentTriangleIntersection
+// purpose  : Moller-Trumbore ray-triangle intersection test
+//=======================================================================
+Standard_Boolean SelectMgr_TriangularFrustumSet::segmentTriangleIntersection (const gp_Pnt& theOrig, const gp_Vec& theDir,
+                                                                              const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3) const
+{
+  gp_Vec        aPVec, aTVec, aQVec;
+  Standard_Real aD, aInvD, anU, aV, aT;
+
+  gp_Vec anEdge1 = theV2.XYZ() - theV1.XYZ();
+  gp_Vec anEdge2 = theV3.XYZ() - theV1.XYZ();
+
+  aPVec = theDir.Crossed (anEdge2);
+  aD = anEdge1.Dot (aPVec);
+  if (fabs (aD) < gp::Resolution())
+  {
+    return Standard_False;
+  }
+
+  aInvD = 1.0 / aD;
+  aTVec = theOrig.XYZ() - theV1.XYZ();
+  anU = aInvD * aTVec.Dot (aPVec);
+  if (anU < 0.0 || anU > 1.0)
+  {
+    return Standard_False;
+  }
+
+  aQVec = aTVec.Crossed (anEdge1);
+  aV = aInvD * theDir.Dot (aQVec);
+  if (aV < 0.0 || anU + aV > 1.0)
+  {
+    return Standard_False;
+  }
+
+  aT = aInvD * anEdge2.Dot (aQVec);
+  if (aT < 0 || aT > 1)
+  {
+    return Standard_False;
+  }
+
+  return Standard_True;
+}
+
 #undef MEMORY_BLOCK_SIZE
index fc2d4c1..08f4cb5 100644 (file)
@@ -37,7 +37,7 @@ class SelectMgr_TriangularFrustumSet : public SelectMgr_BaseFrustum
 {
 public:
 
-  SelectMgr_TriangularFrustumSet() {};
+  SelectMgr_TriangularFrustumSet();
 
   ~SelectMgr_TriangularFrustumSet() {};
 
@@ -84,9 +84,24 @@ public:
   //! Ax + By + Cz + D = 0) to the given vector
   Standard_EXPORT virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const Standard_OVERRIDE;
 
+  //! If theIsToAllow is false, only fully included sensitives will be detected, otherwise the algorithm will
+  //! mark both included and overlapped entities as matched
+  Standard_EXPORT virtual void SetAllowOverlapDetection (const Standard_Boolean theIsToAllow);
+
+private:
+
+  //! Checks whether the segment intersects with the boundary of the current volume selection
+  Standard_EXPORT Standard_Boolean isIntersectBoundary (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2) const;
+
+  //! Checks whether the triangle intersects with a segment
+  Standard_EXPORT Standard_Boolean segmentTriangleIntersection (const gp_Pnt &theOrig, const gp_Vec& theDir,
+                                                                const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3) const;
+
 private:
 
-    SelectMgr_TriangFrustums myFrustums;
+  SelectMgr_TriangFrustums myFrustums;
+  TColgp_Array1OfPnt       myBoundaryPoints;
+  Standard_Boolean         myToAllowOverlap;
 };
 
 #endif // _SelectMgr_TriangularFrustumSet_HeaderFile
index 9bc02b1..3ac0733 100644 (file)
@@ -7635,12 +7635,7 @@ static Standard_Integer VSelect (Draw_Interpretor& ,
       return 1;
     }
   }
-  if (toAllowOverlap
-   && aPnts.Length() != 2)
-  {
-    std::cout << "Syntax error: -allowoverlap key is applied only for rectangle selection\n";
-    return 1;
-  }
+
   if (toAllowOverlap)
   {
     aCtx->MainSelector()->AllowOverlapDetection (toAllowOverlap);
@@ -14279,10 +14274,10 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "- 1) single click selection\n"
     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
-    "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
-    "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
-    "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
-    " (partial inclusion - overlap - is not allowed by default)\n"
+    "- 4) -allowoverlap manages overlap and inclusion detection in rectangular and polygonal selection.\n"
+    "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined \n"
+    "     rectangle or polygon will be detected, otherwise algorithm will chose only fully included sensitives.\n"
+    "     Default behavior is to detect only full inclusion. (partial inclusion - overlap - is not allowed by default)\n"
     "- 5) any of these selections with shift button pressed",
     __FILE__, VSelect, group);
   theCommands.Add ("vmoveto",
index 24a6bfd..6a326d5 100644 (file)
@@ -15,7 +15,7 @@ vsetdispmode m 2
 
 vselmode m 8 1
 vselect 0 0 409 409 0 409
-if { [vnbselected] != "56748" } { puts "Error: the number of selected elements differs for mode 8" }
+if { [vnbselected] != "55607" } { puts "Error: the number of selected elements differs for mode 8" }
 vdump $imagedir/${casename}_mode_8.png
 
 vselect 0 0
diff --git a/tests/bugs/vis/bug31440 b/tests/bugs/vis/bug31440
new file mode 100644 (file)
index 0000000..1d6a897
--- /dev/null
@@ -0,0 +1,34 @@
+puts "============"
+puts "0031440: Visualization - Impossible to make common behaviour for multi-selection in viewer"
+puts "============"
+puts ""
+
+vinit View1
+vpoint radP1 0 0 0
+vpoint radP2 50 50 0
+vpoint radP3 100 0 0
+vcircle circle radP1 radP2 radP3 1
+vfit
+
+vselect 50 300 150 300 150 100 50 100
+if {[vreadpixel 120 200 rgb name] != "DARKGOLDENROD"} { puts "ERROR: the circle is selected with no overlap mode activated" }
+vselect 0 0
+
+vselect 50 300 360 300 360 100 50 100
+if {[vreadpixel 120 200 rgb name] != "GRAY73"} { puts "ERROR: the circle is not selected" }
+vselect 0 0
+vclear
+
+box b 0 0 0 1 1 1
+vdisplay b 
+vfit
+vselmode b 2 1
+vviewparams -scale 500
+
+vdrawparray line polylines v 10 9 0 v 400 9 0 v 400 209 0 v 200 109 0 v 10 209 0 v 10 9 0
+vdisplay line -2d
+vsetcolor line red
+
+vselect 10 400 400 400 400 200 200 300 10 200
+
+vdump ${imagedir}/${casename}.png