0025687: Visualization, XCAF - eliminate visual artifacts at the edges of faces
authoribs <ibs@opencascade.com>
Thu, 26 Feb 2015 09:50:32 +0000 (12:50 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 26 Feb 2015 09:51:24 +0000 (12:51 +0300)
AIS_ColoredShape::Compute() - improve logic to split input shape into Closed and Open volumes
with back-face culling enabled when possible.

Change last argument of method StdPrs_ShadedShape::Add() from boolean to enumeration StdPrs_Volume
which controls parsing of Closed/Open volumes within input shape.
Make method StdPrs_ShadedShape::ExploreSolids() public.

Extend Draw Harness command vaspects with option -setvisibility to hide subshape (using AIS_ColoredShape).
Add new test cases bugs/bis/bug25687_1 and bugs/bis/bug25687_2.

the logic of bindSubShapes method clarified

Conflicts:

src/AIS/AIS_ColoredShape.cxx

AIS_ColoredShape::dispatchColors considers the colors of displayed shapes in connection with specific priority

the color of specific shape can be exported from several ways: the color of this shape, the color of a compound containing this shape. The highest priority has the color of shape than the one of the compound. The color with highest priority will be displayed.

This patch accounts for the highest priority of the shape color.

For example: w - wire has GREEN color; e - edge has RED color; "w" contains "e"; all edges of "w" will be displayed in GREEN color except "e" edge, it will be displayed in RED color

Added sample generating model of Intel i7-4790 CPU on which the problem can be reproduced

12 files changed:
samples/tcl/cpu.tcl [new file with mode: 0644]
samples/tcl/dimensions.tcl
samples/tcl/pencil.tcl
samples/tcl/xde.tcl
src/AIS/AIS_ColoredShape.cxx
src/AIS/AIS_ColoredShape.hxx
src/StdPrs/StdPrs.cdl
src/StdPrs/StdPrs_ShadedShape.cdl
src/StdPrs/StdPrs_ShadedShape.cxx
src/ViewerTest/ViewerTest.cxx
tests/bugs/vis/bug25687_1 [new file with mode: 0644]
tests/bugs/vis/bug25687_2 [new file with mode: 0644]

diff --git a/samples/tcl/cpu.tcl b/samples/tcl/cpu.tcl
new file mode 100644 (file)
index 0000000..4cf4d2a
--- /dev/null
@@ -0,0 +1,331 @@
+# Sample model of Intel i7-4790 CPU
+# Dimensions are taken from specs and foto found in Internet
+
+#Category: XDE
+#Title: Intel i7-4790 CPU
+
+pload MODELING VISUALIZATION XDE
+
+puts "Making board..."
+
+# board is rectangle 37.5 x 37.5 mm with semi-round holes on two sides;
+# assumed board thickness is 1 mm
+dset L 37.5
+dset t 1.
+polyline pboard 0 0 0 L 0 0 L L 0 0 L 0 0 0 0 
+mkplane fboard pboard
+circle cslot -0.2 32.2 0 1
+mkedge eslot cslot
+wire wslot eslot
+mkplane fslot wslot
+bcut fboard fboard fslot
+ttranslate fslot L+0.4 0 0
+bcut fboard fboard fslot
+prism board fboard 0 0 t
+
+# make faces representing dard-green parts of the board sides
+mkoffset dgbot fboard 1 -0.5
+mkplane dgbot dgbot_1
+tcopy dgbot dgtop
+ttranslate dgtop 0 0 0.5*t
+box aux 36.6 17.7 0 10 8.4 2*t
+bcut dgtop dgtop aux
+prism pbot dgbot 0 0 0.5*t
+prism ptop dgtop 0 0 0.5*t
+bfuse board board pbot
+bfuse board board ptop
+
+# add triangular faces indicating base corner of the plate
+polyline btri 0.5 0.5 0 1.5 0.5 0 0.5 1.5 0 0.5 0.5 0
+polyline ttri 0.5 0.5 t 2.5 0.5 t 0.5 2.5 t 0.5 0.5 t
+thrusections stri 1 1 btri ttri
+bfuse board board stri
+
+explode board so
+renamevar board_1 board
+
+puts "Making case..."
+
+# case is made of two filleted prisms, base and top
+polyline lbase 3.4 1.8 t L-3.4 1.8 t L-3.4 11.4 t L-1.8 11.4 t L-1.8 25.2 t \
+               L-3.4 25.2 t L-3.4 L-3 t 3.4 L-3 t 3.4 25.2 t \
+               1.8 25.2 t 1.8 11.4 t 3.4 11.4 t 3.4 1.8 t
+mkplane f lbase
+explode f e
+chfi2d fbase f f_1 f_2 F 1.3 f_2 f_3 F 0.7 f_3 f_4 F 0.7 f_4 f_5 F 0.7 \
+               f_5 f_6 F 0.7 f_6 f_7 F 1.3 f_7 f_8 F 1.3 f_8 f_9 F 0.7 \
+               f_9 f_10 F 0.7 f_10 f_11 F 0.7 f_11 f_12 F 0.7 f_12 f_1 F 1.3
+
+polyline ltop 4. 3.4 t L-4 3.4 t L-4 L-4.8 t 4 L-4.8 t 4. 3.4 t
+mkplane f ltop
+explode f e
+chfi2d ftop f f_1 f_2 F 1.6 f_2 f_3 F 1.6 f_3 f_4 F 1.6 f_4 f_1 F 1.6
+
+# make case, assume height of base 1 mm and top additional 2.5 mm
+prism pbase fbase 0 0 1
+prism ptop ftop 0 0 3.5
+bfuse case pbase ptop
+
+explode case so
+renamevar case_1 case
+
+# write text on top of the case
+# note that font is chosen by availability of Unicode symbols,
+# it is different from actual font found on processor
+set font "Arial Unicode MS"
+#set text "i\u24c2\u00a911\nINTEL\u00ae CORE\u2122 i7-4790\nSR1QF 3.60GHZ\nMALAY\nL411B540 \u24d4"
+#text2brep title $text "Arial Unicode MS" 1.7 x=10 y=24 z=4.51
+# alternative variant to work-around issue #25852
+set text "i\u20dd\u20dd11\nINTEL\u20dd CORE\u2122 i7-4790\nSR1QF 3.60GHZ\nMALAY\nL411B540 \u20dd"
+text2brep title0 $text $font 1.7 x=10 y=24 z=4.51
+text2brep title1 "    M    C" $font 0.77 x=10 y=24.2 z=4.51
+text2brep title2 "R" $font 0.77 x=15.3 y=21.9 z=4.51
+text2brep title3 "e4" $font 0.7 x=18.6 y=15.1 z=4.51
+compound title0 title1 title2 title3 title
+
+puts "Adding contact pads..."
+
+# contact pads on top side (round); we need 42 with R=0.3 and 1 with R=0.6
+pcylinder rpad 0.27 0.1
+eval compound [lrepeat 42 rpad] cpad
+set lpad [explode cpad]
+for {set i 1} {$i <= 20} {incr i} {
+  ttranslate cpad_[expr 2*$i  ] [expr 4.5  + $i * 0.7] L-0.7 t
+  ttranslate cpad_[expr 2*$i-1] [expr 4.85 + $i * 0.7] L-1.3 t
+}
+ttranslate cpad_41 L-0.7 L-0.7 t
+ttranslate cpad_42 L-0.7   0.7 t
+pcylinder Rpad 0.5 0.1
+ttranslate Rpad 0.9 L-0.9 t
+eval compound $lpad Rpad rpads
+
+# contact pads at the bottom
+box pad -0.45 -0.27 -0.1 0.9 0.54 0.1
+trotate pad 0 0 0 0 0 1 60
+ellipse c 0 0 -0.1 0.5 0.4
+mkedge e c
+wire w e
+mkplane f w
+prism b f 0 0 0.1
+bcommon bpad pad b
+explode bpad so
+renamevar bpad_1 bpad
+#donly bpad; boundings bpad
+
+# pattern of presence of bottom pads, on XY plane (top view)
+set pattern [join {
+..ooooooooooooooo...ooooooooooooooooo... 
+.oooooooooooooooo...ooooooooooooooooooo. 
+.oooooooooooooooooooooooooooooooooooooo. 
+.oooooooooooooooooooooooooooooooooooooo. 
+.oooooooooooooooooooooooooooooooooooooo. 
+.oooooooooooooooooooooooooooooooooooooo. 
+.oooooooooooooooooooooooooooooooooooooo. 
+.oooooooooooooooooooooooooooooooooooooo. 
+.ooooooooooo................ooooooooooo. 
+.oooooooooo.................ooooooooooo. 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+..oooooooooo................oooooooooo.. 
+..oooooooooo................oooooooooo.. 
+..oooooooooo................oooooooooo.. 
+..oooooooooo................oooooooooo.. 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+oooooooooooo................oooooooooooo 
+.ooooooooooo.................ooooooooooo 
+.ooooooooooo................oooooooooooo 
+.ooooooooooooooooooooooooooooooooooooooo 
+oooooooooooooooooooooooooooooooooooooooo 
+oooooooooooooooooooooooooooooooooooooooo 
+oooooooooooooooooooooooooooooooooooooooo 
+oooooooooooooooooooooooooooooooooooooooo 
+.ooooooooooooooooooooooooooooooooooooooo 
+..oooooooooooooooo...oooooooooooooooooo. 
+...ooooooooooooooo...ooooooooooooooooo.. 
+} ""]                                 
+
+set nbpads 0
+for {set i 0} {$i < 1600} {incr i} { 
+  if { [string index $pattern $i] == "o" } { incr nbpads }
+}
+eval compound [lrepeat $nbpads bpad] cpad
+set lpad [explode cpad]
+for {set ipad 1; set iplace 0} {$ipad <= $nbpads && $iplace < 1600} {incr ipad; incr iplace} {
+  while { [string index $pattern $iplace] == "." } { incr iplace }
+  set icol [expr $iplace % 40]
+  set irow [expr $iplace / 40]
+  ttranslate cpad_$ipad [expr 1 + 0.91 * $icol] [expr [dval L] - 1 - 0.91 * $irow] 0
+}
+
+# round and square contact pads on top side
+# note re-use of rpad object used for bootom round pads
+eval compound [lrepeat 8 rpad] crpads
+set lrpad [explode crpads]
+ttranslate crpads_1 25.3  8.4  -0.1
+ttranslate crpads_2 12.2 29.2  -0.1
+ttranslate crpads_3 12.5 15.   -0.1
+ttranslate crpads_4 12.5 18.75 -0.1
+ttranslate crpads_5 12.5 19.5  -0.1
+ttranslate crpads_6 12.5 20.25 -0.1
+ttranslate crpads_7 12.5 21.   -0.1
+ttranslate crpads_8 12.5 22.5  -0.1
+box spad_1 12.21 13.75 -0.1 0.58 0.58 0.1
+box spad_2 12.21 23.2  -0.1 0.58 0.58 0.1
+
+# final compound for all bottom pads
+eval compound $lpad $lrpad spad_1 spad_2 bpads
+
+# resistor-like packages at the bottom
+box rpk1 -0.6 -0.25 -0.5 0.3 0.5 0.5
+box rpk2 -0.3 -0.25 -0.5 0.6 0.5 0.5
+box rpk3  0.3 -0.25 -0.5 0.3 0.5 0.5
+compound rpk1 rpk2 rpk3 rpk
+
+eval compound [lrepeat 47 rpk] crpk
+set lrpk [explode crpk]
+# rotate first 26 packages vertically
+for {set i 1} {$i <= 26} {incr i} {trotate crpk_$i 0 0 0 0 0 1 90}
+# first 9 are vertical column on the right side of the bottom view
+for {set i 1} {$i <=  9} {incr i} {
+  ttranslate crpk_$i 13.4 [expr 9.8 + 1.6 * $i] 0 
+}
+# next 8 are 2x4 grid in top left corner
+for {set i 1} {$i <=  4} {incr i} {
+  ttranslate crpk_[expr  9 + $i] 23. [expr 21.5 + 1.6 * $i] 0 
+  ttranslate crpk_[expr 13 + $i] 24. [expr 21.5 + 1.6 * $i] 0 
+}
+# others are translated individually, vertical first, bottom to top
+ttranslate crpk_18 21.5  9.4 0
+ttranslate crpk_19 21.5 11.0 0
+ttranslate crpk_20 21.5 12.6 0
+ttranslate crpk_21 22.5  9.8 0
+ttranslate crpk_22 20.0 12.2 0
+ttranslate crpk_23 24.0 13.6 0
+ttranslate crpk_24 24.0 15.2 0
+ttranslate crpk_25 19.5 16.0 0
+ttranslate crpk_26 20.5 16.0 0
+# now horizontal, bottom to top
+ttranslate crpk_27 23.7  9.5 0
+ttranslate crpk_28 23.7 10.5 0
+ttranslate crpk_29 22.8 11.5 0
+ttranslate crpk_30 22.8 12.5 0
+ttranslate crpk_31 22.7 14.3 0
+ttranslate crpk_32 22.7 16.0 0
+ttranslate crpk_33 22.8 17.0 0
+ttranslate crpk_34 22.8 19.1 0
+ttranslate crpk_35 22.7 20.0 0
+ttranslate crpk_36 23.0 20.9 0
+ttranslate crpk_37 23.3 21.8 0
+
+ttranslate crpk_38 19.8 21.6 0
+ttranslate crpk_39 19.8 22.6 0
+ttranslate crpk_40 19.8 23.6 0
+ttranslate crpk_41 21.6 22.2 0
+ttranslate crpk_42 21.6 23.2 0
+ttranslate crpk_43 21.6 24.2 0
+
+ttranslate crpk_44 18.0 24.6 0
+ttranslate crpk_45 18.0 25.6 0
+ttranslate crpk_46 18.0 26.6 0
+ttranslate crpk_47 18.0 27.6 0
+
+eval compound $lrpk brpk
+
+# show result in plain 3d viewer
+if [info exists i7_show_3dview] {
+  vinit Driver1/Viewer1/View1
+  vclear 
+  vsetdispmode 1
+
+  vlight clear
+  vlight add amb
+  vlight add directional direction 1 -1 -2 head 1
+
+  vdisplay case
+  vsetcolor case 0.7 0.7 0.7
+
+  vdisplay title
+  vsetcolor title 0.1 0.1 0.1
+
+  # board is mostly yellow (edges, triangle markers)
+  foreach f [explode board f] { vdisplay $f; vsetcolor $f 0.7 0.5 0.3 }
+  # top and bottom faces are light-green (outside) and dark-green (inside)
+  vsetcolor board_4 0 0.6 0.55
+  vsetcolor board_5 0 0.6 0.55
+  vsetcolor board_12 0 0.3 0.33
+  vsetcolor board_15 0 0.3 0.33
+
+  vdisplay rpads
+  vsetcolor rpads 0.7 0.6 0.4
+
+  vdisplay bpads
+  vsetcolor bpads 0.7 0.6 0.4
+
+  vdisplay brpk
+  vsetcolor brpk 0.5 0.4 0.3
+
+  donly board case rpads brpk; fit
+}
+
+# make XDE document
+catch {Close D}
+pload OCAF XDE
+
+NewDocument D MDTV-XCAF
+
+SetName D [XAddShape D board 0] "Board"
+foreach f [explode board f] { XSetColor D $f 0.7 0.5 0.3 }
+XSetColor D board_4 0 0.6 0.55
+XSetColor D board_5 0 0.6 0.55
+XSetColor D board_12 0 0.3 0.33
+XSetColor D board_15 0 0.3 0.33
+
+SetName D [XAddShape D case 0] "Case"
+XSetColor D case 0.7 0.7 0.7
+
+SetName D [XAddShape D title 0] "Case title"
+XSetColor D title 0.1 0.1 0.1
+
+SetName D [XAddShape D rpads 1] "Top side contact pads"
+SetName D [XAddShape D bpads 1] "Bottom contact pads"
+SetName D [XFindShape D bpad] "Contact pad"
+SetName D [XFindShape D rpad] "Round pad"
+SetName D [XFindShape D Rpad] "Big round pad"
+SetName D [XFindShape D spad_1] "Square pad 1"
+SetName D [XFindShape D spad_2] "Square pad 2"
+XSetColor D rpad 0.7 0.6 0.4
+XSetColor D Rpad 0.7 0.6 0.4
+XSetColor D bpad 0.7 0.6 0.4
+XSetColor D spad_1 0.7 0.6 0.4
+XSetColor D spad_2 0.7 0.6 0.4
+
+SetName D [XAddShape D brpk 1] "Bottom packages"
+SetName D [XFindShape D rpk] "Bottom package"
+XSetColor D rpk1 0.7 0.7 0.7
+XSetColor D rpk2 0.5 0.4 0.3
+XSetColor D rpk3 0.7 0.7 0.7
+
+XShow D
+vlight clear
+vlight add amb
+vlight add directional direction 1 -1 -2 head 1
+vsetdispmode 1
+vfit
+
+# save to STEP if variable i7_save_xde is defined (specifies file name)
+if [info exists i7_save_xde] {
+  param write.surfacecurve.mode 0
+  WriteStep D $i7_save_xde
+}
\ No newline at end of file
index 9de59e5..f80a4b3 100644 (file)
@@ -1,11 +1,11 @@
-#Category: Demos
-#Title: Dimensions in 3d viewer
-
 # Dimensions demo
 #
 # It shows capability of OCC to create different kinds
 # of dimensions (linear and angular) with 2D or 3D text.
 
+#Category: Visualization
+#Title: Dimensions in 3d viewer
+
 set aTopLoc [locate_data_file occ/Top.brep]
 set aBotLoc [locate_data_file occ/Bottom.brep]
 set aHatch  [locate_data_file images/hatch_1.png]
index 9ed2c53..c48eb28 100644 (file)
@@ -1,6 +1,6 @@
 # Sample demonstrating assignment of colors to faces in XDE
 
-#Category: Data Exchange
+#Category: XDE
 #Title: Assignment of colors to faces
 
 pload MODELING VISUALIZATION OCAF XDE
index 2e00651..63f120a 100644 (file)
@@ -1,7 +1,7 @@
 # Simple sample demonstrating work with assemblies in XDE, and assignment of 
 # names and colors to components vs. instances
 
-#Category: Application Framework
+#Category: XDE
 #Title: Work with assemblies, colors etc. in XDE
 
 pload MODELING
index fe327ec..de89c42 100644 (file)
@@ -305,7 +305,6 @@ void AIS_ColoredShape::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
     thePrs->SetInfiniteState (Standard_True);
   }
 
-  const Standard_Boolean isClosed = StdPrs_ToolShadedShape::IsClosed (myshape);
   if (theMode == AIS_Shaded)
   {
     // compute mesh for entire shape beforehand to ensure consistency and optimizations (parallelization)
@@ -320,15 +319,59 @@ void AIS_ColoredShape::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
     StdPrs_ShadedShape::Tessellate (myshape, myDrawer);
   }
 
-  // 1) myShapeColors + myshape --> array[TopAbs_ShapeEnum] of map of color-to-compound
-  DataMapOfShapeCompd aTypeKeyshapeDrawshapeArray[(size_t )TopAbs_SHAPE];
-  dispatchColors (myshape, myShapeColors, aTypeKeyshapeDrawshapeArray);
+  TopoDS_Compound anOpened, aClosed;
+  BRep_Builder aBuilder;
+  aBuilder.MakeCompound (aClosed);
+  aBuilder.MakeCompound (anOpened);
+  if (theMode == AIS_Shaded && myshape.ShapeType() <= TopAbs_SOLID)
+  {
+    StdPrs_ShadedShape::ExploreSolids (myshape, aBuilder, aClosed, anOpened, Standard_False);
+  }
+  else
+  {
+    aBuilder.Add (anOpened, myshape);
+  }
+
+  // myShapeColors + anOpened --> array[TopAbs_ShapeEnum] of map of color-to-compound
+  DataMapOfShapeCompd aDispatchedOpened [(size_t)TopAbs_SHAPE];
+  dispatchColors (anOpened, myShapeColors, aDispatchedOpened);
+  addShapesWithCustomProps (thePrs, aDispatchedOpened, theMode, StdPrs_Volume_Opened);
+
+  if (theMode == AIS_Shaded)
+  {
+    if (isShapeEntirelyVisible())
+    {
+      // myShapeColors + aClosed --> array[TopAbs_ShapeEnum] of map of color-to-compound
+      DataMapOfShapeCompd aDispatchedClosed [(size_t)TopAbs_SHAPE];
+      dispatchColors (aClosed, myShapeColors, aDispatchedClosed);
+      addShapesWithCustomProps (thePrs, aDispatchedClosed, theMode, StdPrs_Volume_Closed);
+    }
+    else
+    {
+      for (TopoDS_Iterator aSolidIter (aClosed); aSolidIter.More(); aSolidIter.Next())
+      {
+        DataMapOfShapeCompd aDispatchedClosed [(size_t)TopAbs_SHAPE];
+        dispatchColors (aSolidIter.Value(), myShapeColors, aDispatchedClosed);
+        addShapesWithCustomProps (thePrs, aDispatchedClosed, theMode,
+                                  isShapeEntirelyVisible (aDispatchedClosed) ? StdPrs_Volume_Closed : StdPrs_Volume_Opened);
+      }
+    }
+  }
+}
 
-  // 2) finally add appropriate presentations (1 color -- 1 compound) according to theMode
+//=======================================================================
+//function : addShapesWithCustomProps
+//purpose  :
+//=======================================================================
+void AIS_ColoredShape::addShapesWithCustomProps (const Handle(Prs3d_Presentation)& thePrs,
+                                                 DataMapOfShapeCompd*              theDispatched,
+                                                 const Standard_Integer            theMode,
+                                                 const StdPrs_Volume               theVolume)
+{
   Handle(AIS_ColoredDrawer) aCustomDrawer;
   for (size_t aShType = 0; aShType < (size_t )TopAbs_SHAPE; ++aShType)
   {
-    DataMapOfShapeCompd& aKeyshapeDrawshapeMap = aTypeKeyshapeDrawshapeArray[aShType];
+    DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theDispatched[aShType];
     for (DataMapOfShapeCompd::Iterator aMapIter (aKeyshapeDrawshapeMap);
          aMapIter.More(); aMapIter.Next())
     {
@@ -351,30 +394,15 @@ void AIS_ColoredShape::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
       // Draw each kind of subshapes and personal-colored shapes in a separate group
       // since it's necessary to set transparency/material for all subshapes
       // without affecting their unique colors
-      Handle(Graphic3d_Group) aCurrGroup = Prs3d_Root::NewGroup (thePrs);
-      switch (theMode)
+      if (theMode == AIS_Shaded
+       && aShapeDraw.ShapeType() <= TopAbs_FACE
+       && !IsInfinite())
       {
-        default:
-        case AIS_Shaded:
-        {
-          if ((Standard_Integer )aShapeDraw.ShapeType() <= TopAbs_FACE
-           && !IsInfinite())
-          {
-            StdPrs_ShadedShape::Add (thePrs, aShapeDraw, aDrawer);
-
-            aDrawer->SetShadingAspectGlobal (Standard_False);
-            Handle(Graphic3d_AspectFillArea3d) anAsp = aDrawer->ShadingAspect()->Aspect();
-            isClosed ? anAsp->SuppressBackFace() : anAsp->AllowBackFace();
-            aCurrGroup->SetGroupPrimitivesAspect (anAsp);
-            break;
-          }
-          // compute wire-frame otherwise
-        }
-        case AIS_WireFrame:
-        {
-          StdPrs_WFDeflectionShape::Add (thePrs, aShapeDraw, aDrawer);
-          break;
-        }
+        StdPrs_ShadedShape::Add (thePrs, aShapeDraw, aDrawer, theVolume);
+      }
+      else
+      {
+        StdPrs_WFDeflectionShape::Add (thePrs, aShapeDraw, aDrawer);
       }
     }
   }
@@ -448,22 +476,23 @@ Standard_Boolean AIS_ColoredShape::dispatchColors (const TopoDS_Shape&        th
 }
 
 //! Function to check if specified compound is sub-shape of another one
-inline Standard_Boolean isContainCompound (const TopoDS_Shape&    theShape,
-                                           const TopoDS_Compound& theCompound)
+inline Standard_Boolean isFirstCmpContainSecondOne (const TopoDS_Shape& theFirstCmp,
+                                                    const TopoDS_Shape& theSecondCmp)
 {
-  if (theShape.ShapeType() != TopAbs_COMPOUND)
+  if (theFirstCmp.ShapeType()  != TopAbs_COMPOUND
+   || theSecondCmp.ShapeType() != TopAbs_COMPOUND)
   {
     return Standard_False;
   }
 
-  for (TopoDS_Iterator aSubShapeIter (theShape); aSubShapeIter.More(); aSubShapeIter.Next())
+  for (TopoDS_Iterator aFirstCmpIter (theFirstCmp); aFirstCmpIter.More(); aFirstCmpIter.Next())
   {
-    if (aSubShapeIter.Value().ShapeType() != TopAbs_COMPOUND)
+    if (aFirstCmpIter.Value().ShapeType() != TopAbs_COMPOUND)
     {
       continue;
     }
-    else if (aSubShapeIter.Value() == theCompound
-          || isContainCompound (aSubShapeIter.Value(), theCompound))
+    else if (aFirstCmpIter.Value() == theSecondCmp
+          || isFirstCmpContainSecondOne (aFirstCmpIter.Value(), theSecondCmp))
     {
       return Standard_True;
     }
@@ -487,47 +516,110 @@ void AIS_ColoredShape::dispatchColors (const TopoDS_Shape&        theBaseShape,
   for (DataMapOfShapeColor::Iterator aKeyShapeIter (theKeyshapeColorMap);
        aKeyShapeIter.More(); aKeyShapeIter.Next())
   {
-    const TopoDS_Shape&    aKeySh = aKeyShapeIter.Key();
-    const TopAbs_ShapeEnum aType  = aKeySh.ShapeType();
-    TopAbs_ShapeEnum aSubType = (aType == TopAbs_SOLID || aType == TopAbs_SHELL)
-                              ? TopAbs_FACE
-                              : (aType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_SHAPE);
-    switch (aSubType)
+    const TopoDS_Shape& aKeyShape = aKeyShapeIter.Key();
+    bindSubShapes (aSubshapeKeyshapeMap, theBaseShape, aKeyShape, aKeyShape);
+  }
+
+  // Fill the array of maps per shape type
+  dispatchColors (theBaseShape, theBaseShape,
+                  aSubshapeKeyshapeMap, TopAbs_SHAPE,
+                  theTypeKeyshapeDrawshapeArray);
+}
+
+//=======================================================================
+//function : isShapeEntirelyVisible
+//purpose  :
+//=======================================================================
+Standard_Boolean AIS_ColoredShape::isShapeEntirelyVisible (DataMapOfShapeCompd* theDispatched) const
+{
+  Handle(AIS_ColoredDrawer) aCustomDrawer;
+  for (size_t aShType = (size_t )TopAbs_COMPOUND; aShType <= (size_t )TopAbs_FACE; ++aShType)
+  {
+    const DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theDispatched[aShType];
+    for (DataMapOfShapeCompd::Iterator aMapIter (aKeyshapeDrawshapeMap); aMapIter.More(); aMapIter.Next())
     {
-      case TopAbs_SHAPE:
+      if (myShapeColors.Find (aMapIter.Key(), aCustomDrawer)
+      && !aCustomDrawer.IsNull()
+      &&  aCustomDrawer->IsHidden())
       {
-        if (aType == TopAbs_COMPOUND
-        && !isContainCompound (theBaseShape, TopoDS::Compound (aKeySh)))
-        {
-          for (TopoDS_Iterator aSubShapeIter (aKeySh); aSubShapeIter.More(); aSubShapeIter.Next())
-          {
-            if (!aSubshapeKeyshapeMap.IsBound (aSubShapeIter.Value()))
-            {
-              aSubshapeKeyshapeMap.Bind (aSubShapeIter.Value(), aKeySh);
-            }
-          }
-        }
-        else
-        {
-          aSubshapeKeyshapeMap.Bind (aKeySh, aKeySh);
-        }
-        break;
+        return Standard_False;
       }
-      default:
+    }
+  }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : isShapeEntirelyVisible
+//purpose  :
+//=======================================================================
+Standard_Boolean AIS_ColoredShape::isShapeEntirelyVisible() const
+{
+  for (DataMapOfShapeColor::Iterator aMapIter (myShapeColors); aMapIter.More(); aMapIter.Next())
+  {
+    if (aMapIter.Value()->IsHidden())
+    {
+      return Standard_False;
+    }
+  }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : bindSubShapes
+//purpose  :
+//=======================================================================
+void AIS_ColoredShape::bindSubShapes (DataMapOfShapeShape& theSubshapeKeyshapeMap,
+                                      const TopoDS_Shape&  theBaseShape,
+                                      const TopoDS_Shape&  theShapeWithColor,
+                                      const TopoDS_Shape&  theColorKeyShape)
+{
+  TopAbs_ShapeEnum aShapeWithColorType = theShapeWithColor.ShapeType();
+  if (aShapeWithColorType == TopAbs_COMPOUND)
+  {
+    if (isFirstCmpContainSecondOne (theBaseShape, theShapeWithColor))
+    {
+      if (!theSubshapeKeyshapeMap.IsBound (theShapeWithColor))
       {
-        for (TopExp_Explorer anExp (aKeySh, aSubType); anExp.More(); anExp.Next())
-        {
-          if (!aSubshapeKeyshapeMap.IsBound (anExp.Current()))
-          {
-            aSubshapeKeyshapeMap.Bind (anExp.Current(), aKeySh);
-          }
-        }
+        theSubshapeKeyshapeMap.Bind (theShapeWithColor, theColorKeyShape);
+      }
+    }
+    else
+    {
+      for (TopoDS_Iterator aSubShapeIter (theShapeWithColor); aSubShapeIter.More(); aSubShapeIter.Next())
+      {
+        bindSubShapes (theSubshapeKeyshapeMap, theBaseShape, aSubShapeIter.Value(), theColorKeyShape);
       }
     }
   }
-
-  // Fill the array of maps per shape type
-  dispatchColors (theBaseShape, theBaseShape,
-                  aSubshapeKeyshapeMap, TopAbs_SHAPE,
-                  theTypeKeyshapeDrawshapeArray);
+  else if (aShapeWithColorType == TopAbs_SOLID || aShapeWithColorType == TopAbs_SHELL)
+  {
+    for (TopExp_Explorer anExp (theShapeWithColor, TopAbs_FACE); anExp.More(); anExp.Next())
+    {
+      if (!theSubshapeKeyshapeMap.IsBound (anExp.Current()))
+      {
+        theSubshapeKeyshapeMap.Bind (anExp.Current(), theColorKeyShape);
+      }
+    }
+  }
+  else if (aShapeWithColorType == TopAbs_WIRE)
+  {
+    for (TopExp_Explorer anExp (theShapeWithColor, TopAbs_EDGE); anExp.More(); anExp.Next())
+    {
+      if (!theSubshapeKeyshapeMap.IsBound (anExp.Current()))
+      {
+        theSubshapeKeyshapeMap.Bind (anExp.Current(), theColorKeyShape);
+      }
+    }
+  }
+  else
+  {
+    // bind single face, edge and vertex
+    // force rebind if required due to the color of single shape has
+    // higher priority than the color of "compound" shape (wire is a
+    // compound of edges, shell is a compound of faces) that contains
+    // this single shape.
+    theSubshapeKeyshapeMap.Bind (theShapeWithColor, theColorKeyShape);
+  }
 }
+
index c9affe1..0830004 100644 (file)
@@ -23,6 +23,7 @@
 #include <NCollection_IndexedDataMap.hxx>
 #include <TopTools_ShapeMapHasher.hxx>
 #include <TopoDS_Compound.hxx>
+#include <StdPrs_Volume.hxx>
 
 //! Customizable properties.
 class AIS_ColoredDrawer : public AIS_Drawer
@@ -139,6 +140,37 @@ protected:
 
 protected:
 
+  //! Add shape to presentation
+  //! @param thePrs         the presentation
+  //! @param theDispatched  the shapes map with unique attributes
+  //! @param theMode        display mode
+  //! @param theVolume      how to interpret theDispatched shapes - as Closed volumes, as Open volumes
+  //!                       or to perform Autodetection
+  Standard_EXPORT void addShapesWithCustomProps (const Handle(Prs3d_Presentation)& thePrs,
+                                                 DataMapOfShapeCompd*              theDispatched,
+                                                 const Standard_Integer            theMode,
+                                                 const StdPrs_Volume               theVolume);
+
+  //! Check all shapes from myShapeColorsfor visibility
+  Standard_EXPORT Standard_Boolean isShapeEntirelyVisible() const;
+
+  //! Check a shape with unique attributes for visibility of all 2d subshape
+  Standard_EXPORT Standard_Boolean isShapeEntirelyVisible (DataMapOfShapeCompd* theDispatched) const;
+
+  //! Resolve (parse) theKeyShape into subshapes, search in they for theBaseShape,
+  //! bind all resolved subshapes with theOriginKeyShape and store all binds in theSubshapeKeyshapeMap
+  //! @param theSubshapeKeyshapeMap        shapes map: resolved and found theBaseShape subshape -> theOriginKeyShape 
+  //! @param theBaseShape                  a shape to be sought
+  //! @param theBaseKey                    a shape to be resolved (parse) into smaller (in topological sense)
+  //!                                      subshapes for new bind cycle
+  //! @param theOriginKeyShape             the key to be used for undetailed shapes (default colors)
+  Standard_EXPORT static void bindSubShapes (DataMapOfShapeShape& theSubshapeKeyshapeMap,
+                                             const TopoDS_Shape&  theBaseShape,
+                                             const TopoDS_Shape&  theKeyShape,
+                                             const TopoDS_Shape&  theOriginKeyShape);
+
+protected:
+
   DataMapOfShapeColor myShapeColors;
 
 public:
index a3bf056..d3dfe34 100644 (file)
@@ -35,6 +35,7 @@ uses
        TopoDS,
        TopExp,
   TopAbs,
+  BRep,
        BRepTools,
        Bnd,
   TColStd,
@@ -48,6 +49,17 @@ uses
        Graphic3d
 
 is
+
+   enumeration Volume is
+     Volume_Autodetection,
+     Volume_Closed,
+     Volume_Opened
+   end Volume;
+   ---Purpose: defines the way how to interpret input shapes
+   --          Volume_Autodetection to perform Autodetection (would split input shape into two groups)
+   --          Volume_Closed as Closed volumes (to activate back-face culling and capping plane algorithms)
+   --          Volume_Opened as Open volumes (shells or solids with holes)
+
    class ToolPoint;
    class ToolVertex;
    class ToolRFace;
index 385bc33..2f722b9 100755 (executable)
@@ -24,7 +24,10 @@ uses
   Presentation from Prs3d,
   Drawer       from Prs3d,
   Shape        from TopoDS,
-  Pnt2d        from gp
+  Pnt2d        from gp,
+  Builder      from BRep,
+  Compound     from TopoDS,
+  Volume       from StdPrs
 
 is
 
@@ -32,9 +35,11 @@ is
        thePresentation    : Presentation from Prs3d;
        theShape           : Shape        from TopoDS;
        theDrawer          : Drawer       from Prs3d;
-       theToExploreSolids : Boolean from Standard = Standard_True);
+       theVolume          : Volume       from StdPrs = StdPrs_Volume_Autodetection);
   ---Purpose: Shades <theShape>.
-  -- @param theToExploreSolids when set to true, explodes compound into two groups - with closed Solids and open Shells
+  -- @param theVolumeType defines the way how to interpret input shapes - as Closed volumes (to activate back-face 
+  --                      culling and capping plane algorithms), as Open volumes (shells or solids with holes)
+  --                      or to perform Autodetection (would split input shape into two groups)
 
   Add (myclass;
        thePresentation    : Presentation from Prs3d;
@@ -44,13 +49,24 @@ is
        theUVOrigin        : Pnt2d        from gp;
        theUVRepeat        : Pnt2d        from gp;
        theUVScale         : Pnt2d        from gp;
-       theToExploreSolids : Boolean from Standard = Standard_True);
+       theVolume          : Volume       from StdPrs = StdPrs_Volume_Autodetection);
   ---Purpose: Shades <theShape> with texture coordinates.
-  -- @param theToExploreSolids when set to true, explodes compound into two groups - with closed Solids and open Shells
+  -- @param theVolumeType defines the way how to interpret input shapes - as Closed volumes (to activate back-face 
+  --                      culling and capping plane algorithms), as Open volumes (shells or solids with holes)
+  --                      or to perform Autodetection (would split input shape into two groups)
 
   Tessellate (myclass;
               theShape  : Shape  from TopoDS;
               theDrawer : Drawer from Prs3d);
   ---Purpose: Validates triangulation within the shape and performs tessellation if necessary.
 
+  ExploreSolids (myclass;
+                 theShape            : Shape  from TopoDS;
+                 theBuilder          : Builder from BRep;
+                 theClosed           : out Compound from TopoDS;
+                 theOpened           : out Compound from TopoDS;
+                 theIgnore1DSubShape : Boolean from Standard);
+  ---Purpose: Searches closed and unclosed subshapes in shape structure and puts them
+  --          into two compounds for separate processing of closed and unclosed sub-shapes
+
 end ShadedShape;
index 160417b..d6e8403 100644 (file)
@@ -237,56 +237,6 @@ namespace
     return anArray;
   }
 
-  //! Searches closed and unclosed subshapes in shape structure
-  //! and puts them into two compounds for separate processing of closed and unclosed sub-shapes.
-  static void exploreSolids (const TopoDS_Shape& theShape,
-                             const BRep_Builder& theBuilder,
-                             TopoDS_Compound&    theCompoundForClosed,
-                             TopoDS_Compound&    theCompoundForOpened)
-  {
-    if (theShape.IsNull())
-    {
-      return;
-    }
-
-    switch (theShape.ShapeType())
-    {
-      case TopAbs_COMPOUND:
-      case TopAbs_COMPSOLID:
-      {
-        for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
-        {
-          exploreSolids (anIter.Value(), theBuilder, theCompoundForClosed, theCompoundForOpened);
-        }
-        return;
-      }
-      case TopAbs_SOLID:
-      {
-        for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
-        {
-          const TopoDS_Shape& aSubShape   = anIter.Value();
-          const Standard_Boolean isClosed = aSubShape.ShapeType() == TopAbs_SHELL &&
-                                            BRep_Tool::IsClosed (aSubShape) &&
-                                            StdPrs_ToolShadedShape::IsTriangulated (aSubShape);
-          theBuilder.Add (isClosed ? theCompoundForClosed : theCompoundForOpened, aSubShape);
-        }
-        return;
-      }
-      case TopAbs_SHELL:
-      case TopAbs_FACE:
-      {
-        theBuilder.Add (theCompoundForOpened, theShape);
-        return;
-      }
-      case TopAbs_WIRE:
-      case TopAbs_EDGE:
-      case TopAbs_VERTEX:
-      case TopAbs_SHAPE:
-      default:
-        return;
-    }
-  }
-
   //! Prepare shaded presentation for specified shape
   static Standard_Boolean shadeFromShape (const TopoDS_Shape&               theShape,
                                           const Handle(Prs3d_Presentation)& thePrs,
@@ -436,17 +386,77 @@ namespace
 };
 
 // =======================================================================
+// function : ExploreSolids
+// purpose  :
+// =======================================================================
+void StdPrs_ShadedShape::ExploreSolids (const TopoDS_Shape&    theShape,
+                                        const BRep_Builder&    theBuilder,
+                                        TopoDS_Compound&       theClosed,
+                                        TopoDS_Compound&       theOpened,
+                                        const Standard_Boolean theIgnore1DSubShape)
+{
+  if (theShape.IsNull())
+  {
+    return;
+  }
+
+  switch (theShape.ShapeType())
+  {
+    case TopAbs_COMPOUND:
+    case TopAbs_COMPSOLID:
+    {
+      for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
+      {
+        ExploreSolids (anIter.Value(), theBuilder, theClosed, theOpened, theIgnore1DSubShape);
+      }
+      return;
+    }
+    case TopAbs_SOLID:
+    {
+      for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
+      {
+        const TopoDS_Shape& aSubShape   = anIter.Value();
+        const Standard_Boolean isClosed = aSubShape.ShapeType() == TopAbs_SHELL &&
+                                          BRep_Tool::IsClosed (aSubShape)       &&
+                                          StdPrs_ToolShadedShape::IsTriangulated (aSubShape);
+        theBuilder.Add (isClosed ? theClosed : theOpened, aSubShape);
+      }
+      return;
+    }
+    case TopAbs_SHELL:
+    case TopAbs_FACE:
+    {
+      theBuilder.Add (theOpened, theShape);
+      return;
+    }
+    case TopAbs_WIRE:
+    case TopAbs_EDGE:
+    case TopAbs_VERTEX:
+    {
+      if (!theIgnore1DSubShape)
+      {
+        theBuilder.Add (theOpened, theShape);
+      }
+      return;
+    }
+    case TopAbs_SHAPE:
+    default:
+      return;
+  }
+}
+
+// =======================================================================
 // function : Add
 // purpose  :
 // =======================================================================
 void StdPrs_ShadedShape::Add (const Handle(Prs3d_Presentation)& thePrs,
                               const TopoDS_Shape&               theShape,
                               const Handle(Prs3d_Drawer)&       theDrawer,
-                              const Standard_Boolean            theToExploreSolids)
+                              const StdPrs_Volume               theVolume)
 {
   gp_Pnt2d aDummy;
   StdPrs_ShadedShape::Add (thePrs, theShape, theDrawer,
-                           Standard_False, aDummy, aDummy, aDummy, theToExploreSolids);
+                           Standard_False, aDummy, aDummy, aDummy, theVolume);
 }
 
 // =======================================================================
@@ -484,7 +494,7 @@ void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePrs,
                               const gp_Pnt2d&                    theUVOrigin,
                               const gp_Pnt2d&                    theUVRepeat,
                               const gp_Pnt2d&                    theUVScale,
-                              const Standard_Boolean             theToExploreSolids)
+                              const StdPrs_Volume                theVolume)
 {
   if (theShape.IsNull())
   {
@@ -503,14 +513,14 @@ void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePrs,
   if ((theShape.ShapeType() == TopAbs_COMPOUND
     || theShape.ShapeType() == TopAbs_COMPSOLID
     || theShape.ShapeType() == TopAbs_SOLID)
-   &&  theToExploreSolids)
+   &&  theVolume == StdPrs_Volume_Autodetection)
   {
     // collect two compounds: for opened and closed (solid) sub-shapes
     TopoDS_Compound anOpened, aClosed;
     BRep_Builder aBuilder;
     aBuilder.MakeCompound (aClosed);
     aBuilder.MakeCompound (anOpened);
-    exploreSolids (theShape, aBuilder, aClosed, anOpened);
+    ExploreSolids (theShape, aBuilder, aClosed, anOpened, Standard_True);
 
     TopoDS_Iterator aShapeIter (aClosed);
     if (aShapeIter.More())
@@ -528,9 +538,10 @@ void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePrs,
   }
   else
   {
+    // if the shape type is not compound, composolid or solid, use autodetection back-facing filled
     shadeFromShape (theShape, thePrs, theDrawer,
                     theHasTexels, theUVOrigin, theUVRepeat, theUVScale,
-                    StdPrs_ToolShadedShape::IsClosed (theShape));
+                    (theVolume == StdPrs_Volume_Closed ? Standard_True : Standard_False));
   }
 
   if (theDrawer->IsFaceBoundaryDraw())
index 2b3a5ce..7790ba1 100644 (file)
@@ -1377,6 +1377,9 @@ static int VSetInteriorStyle (Draw_Interpretor& theDI,
 //! Auxiliary structure for VAspects
 struct ViewerTest_AspectsChangeSet
 {
+  Standard_Integer         ToSetVisibility;
+  Standard_Integer         Visibility;
+
   Standard_Integer         ToSetColor;
   Quantity_Color           Color;
 
@@ -1394,7 +1397,9 @@ struct ViewerTest_AspectsChangeSet
 
   //! Empty constructor
   ViewerTest_AspectsChangeSet()
-  : ToSetColor        (0),
+  : ToSetVisibility   (0),
+    Visibility        (1),
+    ToSetColor        (0),
     Color             (DEFAULT_COLOR),
     ToSetLineWidth    (0),
     LineWidth         (1.0),
@@ -1406,7 +1411,8 @@ struct ViewerTest_AspectsChangeSet
   //! @return true if no changes have been requested
   Standard_Boolean IsEmpty() const
   {
-    return ToSetLineWidth    == 0
+    return ToSetVisibility   == 0
+        && ToSetLineWidth    == 0
         && ToSetTransparency == 0
         && ToSetColor        == 0
         && ToSetMaterial     == 0;
@@ -1416,6 +1422,11 @@ struct ViewerTest_AspectsChangeSet
   Standard_Boolean Validate (const Standard_Boolean theIsSubPart) const
   {
     Standard_Boolean isOk = Standard_True;
+    if (Visibility != 0 && Visibility != 1)
+    {
+      std::cout << "Error: the visibility should be equal to 0 or 1 (0 - invisible; 1 - visible) (specified " << Visibility << ")\n";
+      isOk = Standard_False;
+    }
     if (LineWidth <= 0.0
      || LineWidth >  10.0)
     {
@@ -1640,6 +1651,18 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
         aChangeSet->Transparency = 0.0;
       }
     }
+    else if (anArg == "-setvis"
+          || anArg == "-setvisibility")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at " << anArg << "\n";
+        return 1;
+      }
+
+      aChangeSet->ToSetVisibility = 1;
+      aChangeSet->Visibility = Draw::Atoi (theArgVec[anArgIter]);
+    }
     else if (anArg == "-setalpha")
     {
       if (++anArgIter >= theArgNb)
@@ -1782,6 +1805,8 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
     }
     else if (anArg == "-unset")
     {
+      aChangeSet->ToSetVisibility = 1;
+      aChangeSet->Visibility = 1;
       aChangeSet->ToSetLineWidth = -1;
       aChangeSet->LineWidth = 1.0;
       aChangeSet->ToSetTransparency = -1;
@@ -1819,7 +1844,7 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
     Handle(AIS_InteractiveObject)  aPrs  = aPrsIter.Current();
     Handle(AIS_ColoredShape) aColoredPrs;
     Standard_Boolean toDisplay = Standard_False;
-    if (aChanges.Length() > 1)
+    if (aChanges.Length() > 1 || aChangeSet->ToSetVisibility == 1)
     {
       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aPrs);
       if (aShapePrs.IsNull())
@@ -1844,7 +1869,12 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
     {
       NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
       aChangeSet = &aChangesIter.ChangeValue();
-      if (aChangeSet->ToSetMaterial == 1)
+      if (aChangeSet->ToSetVisibility == 1)
+      {
+        Handle(AIS_ColoredDrawer) aColDrawer = aColoredPrs->CustomAspects (aColoredPrs->Shape());
+        aColDrawer->SetHidden (aChangeSet->Visibility == 0);
+      }
+      else if (aChangeSet->ToSetMaterial == 1)
       {
         aCtx->SetMaterial (aPrs, aChangeSet->Material, Standard_False);
       }
@@ -1884,6 +1914,11 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
              aSubShapeIter.More(); aSubShapeIter.Next())
         {
           const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
+          if (aChangeSet->ToSetVisibility == 1)
+          {
+            Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
+            aCurColDrawer->SetHidden (aChangeSet->Visibility == 0);
+          }
           if (aChangeSet->ToSetColor == 1)
           {
             aColoredPrs->SetCustomColor (aSubShape, aChangeSet->Color);
@@ -4625,6 +4660,7 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
 
   theCommands.Add("vaspects",
               "vaspects [-noupdate|-update] [name1 [name2 [...]]]"
+      "\n\t\t:          [-setvisibility 0|1]"
       "\n\t\t:          [-setcolor ColorName] [-setcolor R G B] [-unsetcolor]"
       "\n\t\t:          [-setmaterial MatName] [-unsetmaterial]"
       "\n\t\t:          [-settransparency Transp] [-unsettransparency]"
diff --git a/tests/bugs/vis/bug25687_1 b/tests/bugs/vis/bug25687_1
new file mode 100644 (file)
index 0000000..499d50a
--- /dev/null
@@ -0,0 +1,28 @@
+puts "============"
+puts "OCC25687"
+puts "AIS_ColoredShape should activate back-face culling for valid Solids."
+puts "============"
+puts ""
+
+set x_check_coord 225
+set y_check_coord 32
+
+box b 10 10 10
+explode b f
+
+vinit View1
+vclear
+vaxo
+vsetdispmode 1
+
+vdisplay b
+vviewparams -proj 0.5 0.3 0.1
+vfit
+
+vaspects b -subshapes b_1 -setcolor GREEN
+
+if {"[vreadpixel ${x_check_coord} ${y_check_coord} rgb name]" == "GREEN"} {
+  puts "Error: back-face culling should be turned ON, but back-face is still visible."
+}
+
+set only_screen 1
diff --git a/tests/bugs/vis/bug25687_2 b/tests/bugs/vis/bug25687_2
new file mode 100644 (file)
index 0000000..48c1939
--- /dev/null
@@ -0,0 +1,29 @@
+puts "============"
+puts "OCC25687"
+puts "AIS_ColoredShape should disable back-face culling for Solids with hidden Face"
+puts "============"
+puts ""
+
+set x_check_coord 200
+set y_check_coord 200
+
+box b 10 10 10
+explode b f
+
+vinit View1
+vclear
+vaxo
+vsetdispmode 1
+
+vdisplay b
+vviewparams -proj 0.5 0.3 0.1
+vfit
+
+vaspects b -subshapes b_1 -setcolor GREEN
+vaspects b -subshapes b_2 -setvis 0
+
+if {"[vreadpixel ${x_check_coord} ${y_check_coord} rgb name]" != "GREEN"} {
+  puts "Error: back-face culling should be disabled, but seems to be not."
+}
+
+set only_screen 1