From: mzernova Date: Tue, 14 Apr 2020 21:54:32 +0000 (+0300) Subject: 0031440: Visualization - Impossible to make common behaviour for multi-selection... X-Git-Tag: V7_5_0_beta~219 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=a24a782174bd9ef8482051a46838fa587c2a54d7 0031440: Visualization - Impossible to make common behaviour for multi-selection in viewer 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 --- diff --git a/src/AIS/AIS_ViewController.cxx b/src/AIS/AIS_ViewController.cxx index 87a4864bc7..d4e79f7a48 100644 --- a/src/AIS/AIS_ViewController.cxx +++ b/src/AIS/AIS_ViewController.cxx @@ -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); } } diff --git a/src/MeshVS/MeshVS_SensitiveQuad.cxx b/src/MeshVS/MeshVS_SensitiveQuad.cxx index 454d9da39c..e12f3f70ce 100644 --- a/src/MeshVS/MeshVS_SensitiveQuad.cxx +++ b/src/MeshVS/MeshVS_SensitiveQuad.cxx @@ -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])) diff --git a/src/Select3D/Select3D_SensitiveCircle.cxx b/src/Select3D/Select3D_SensitiveCircle.cxx index 3f3f14f5c2..82bf115bde 100644 --- a/src/Select3D/Select3D_SensitiveCircle.cxx +++ b/src/Select3D/Select3D_SensitiveCircle.cxx @@ -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))) diff --git a/src/Select3D/Select3D_SensitivePoly.cxx b/src/Select3D/Select3D_SensitivePoly.cxx index bca131d685..d582fef161 100644 --- a/src/Select3D/Select3D_SensitivePoly.cxx +++ b/src/Select3D/Select3D_SensitivePoly.cxx @@ -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)); } diff --git a/src/Select3D/Select3D_SensitiveSegment.cxx b/src/Select3D/Select3D_SensitiveSegment.cxx index 520741138b..c402199ce9 100644 --- a/src/Select3D/Select3D_SensitiveSegment.cxx +++ b/src/Select3D/Select3D_SensitiveSegment.cxx @@ -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); } diff --git a/src/Select3D/Select3D_SensitiveTriangle.cxx b/src/Select3D/Select3D_SensitiveTriangle.cxx index 2b14690632..47291ad68a 100644 --- a/src/Select3D/Select3D_SensitiveTriangle.cxx +++ b/src/Select3D/Select3D_SensitiveTriangle.cxx @@ -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]); diff --git a/src/Select3D/Select3D_SensitiveTriangulation.cxx b/src/Select3D/Select3D_SensitiveTriangulation.cxx index e80dbc6470..ad7677011b 100644 --- a/src/Select3D/Select3D_SensitiveTriangulation.cxx +++ b/src/Select3D/Select3D_SensitiveTriangulation.cxx @@ -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); diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx index 03cbffa88f..89230c7668 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx @@ -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; } //======================================================================= diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx index 5b89bbdd92..6b3fe7822d 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx @@ -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); diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx index 7da53986e4..78a5d72654 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx @@ -22,6 +22,14 @@ #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 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 diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx index fc2d4c122c..08f4cb5b01 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx @@ -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& 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 diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index 9bc02b1375..3ac07336ef 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -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", diff --git a/tests/bugs/vis/bug27008 b/tests/bugs/vis/bug27008 index 24a6bfdcf4..6a326d51f7 100644 --- a/tests/bugs/vis/bug27008 +++ b/tests/bugs/vis/bug27008 @@ -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 index 0000000000..1d6a897eeb --- /dev/null +++ b/tests/bugs/vis/bug31440 @@ -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