\feff0025129: Visualization - add interactive object for Points Cloud objects
authorapl <apl@opencascade.com>
Thu, 25 Sep 2014 09:54:33 +0000 (13:54 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 25 Sep 2014 11:58:15 +0000 (15:58 +0400)
New class AIS_PointCloud for displaying point sets.
Update Graphic3d_ArrayOfPoints, OpenGl_PrimitiveArray and OpenGl_VertexBuffer classes to be able to use normals for points.

Add Draw Harness command vpointcloud.
Add test case v3d/point_cloud/sphere.

Move protected method AIS_Shape::DisplayBox() to public function StdPrs_WFDeflectionRestrictedFace::AddBox().

Small correction of grids.list for v3d tests

14 files changed:
src/AIS/AIS.cdl
src/AIS/AIS_PointCloud.cxx [new file with mode: 0644]
src/AIS/AIS_PointCloud.hxx [new file with mode: 0644]
src/AIS/AIS_Shape.cdl
src/AIS/AIS_Shape.cxx
src/AIS/AIS_TexturedShape.cxx
src/AIS/FILES
src/Graphic3d/Graphic3d_ArrayOfPoints.cdl
src/Graphic3d/Graphic3d_ArrayOfPoints.cxx
src/StdPrs/StdPrs_WFDeflectionRestrictedFace.cdl
src/StdPrs/StdPrs_WFDeflectionRestrictedFace.cxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx
tests/v3d/grids.list
tests/v3d/point_cloud/sphere [new file with mode: 0644]

index 3abdfc8..657e746 100644 (file)
@@ -364,7 +364,8 @@ is
 
     ---Category: General Objects
     class ConnectedInteractive;          --signature 0
-    class MultipleConnectedInteractive;  --signature 1        
+    class MultipleConnectedInteractive;  --signature 1
+    imported PointCloud;
 
            ---Category:  DIMENSIONS AND RELATIONS
  
diff --git a/src/AIS/AIS_PointCloud.cxx b/src/AIS/AIS_PointCloud.cxx
new file mode 100644 (file)
index 0000000..c9c588f
--- /dev/null
@@ -0,0 +1,451 @@
+// Created on: 2014-08-13
+// Created by: Maxim GLIBIN
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <AIS_PointCloud.hxx>
+
+#include <AIS_Drawer.hxx>
+#include <AIS_GraphicTool.hxx>
+#include <Graphic3d_AspectFillArea3d.hxx>
+#include <Graphic3d_AspectMarker3d.hxx>
+#include <Graphic3d_Group.hxx>
+#include <Prs3d_PointAspect.hxx>
+#include <Prs3d_Presentation.hxx>
+#include <Prs3d_Root.hxx>
+#include <Prs3d_ShadingAspect.hxx>
+#include <PrsMgr_ModedPresentation.hxx>
+#include <PrsMgr_Presentations.hxx>
+#include <Select3D_SensitiveBox.hxx>
+#include <SelectMgr_EntityOwner.hxx>
+#include <SelectMgr_Selection.hxx>
+#include <StdPrs_WFDeflectionRestrictedFace.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (AIS_PointCloud, AIS_InteractiveObject)
+IMPLEMENT_STANDARD_RTTIEXT(AIS_PointCloud, AIS_InteractiveObject)
+
+//==================================================
+// Function: AIS_PointCloud
+// Purpose : Constructor
+//==================================================
+AIS_PointCloud::AIS_PointCloud()
+{
+  SetDisplayMode (AIS_PointCloud::DM_Points);
+  SetHilightMode (AIS_PointCloud::DM_BndBox);
+}
+
+//=======================================================================
+//function : GetPoints
+//purpose  :
+//=======================================================================
+const Handle(Graphic3d_ArrayOfPoints) AIS_PointCloud::GetPoints() const
+{
+  return myPoints;
+}
+
+//=======================================================================
+//function : GetBoundingBox
+//purpose  :
+//=======================================================================
+Bnd_Box AIS_PointCloud::GetBoundingBox() const
+{
+  return myBndBox;
+}
+
+//! Auxiliary method
+static inline Bnd_Box getBoundingBox (const Handle(Graphic3d_ArrayOfPoints)& thePoints)
+{
+  Bnd_Box aBndBox;
+  if (thePoints.IsNull())
+  {
+    return aBndBox;
+  }
+
+  const Standard_Integer aNbVertices = thePoints->VertexNumber();
+  for (Standard_Integer aVertIter = 1; aVertIter <= aNbVertices; ++aVertIter)
+  {
+    aBndBox.Add (thePoints->Vertice (aVertIter));
+  }
+  return aBndBox;
+}
+
+//=======================================================================
+//function : SetPoints
+//purpose  :
+//=======================================================================
+void AIS_PointCloud::SetPoints (const Handle(Graphic3d_ArrayOfPoints)& thePoints)
+{
+  myPoints = thePoints;
+  myBndBox = getBoundingBox (thePoints);
+}
+
+//=======================================================================
+//function : SetPoints
+//purpose  :
+//=======================================================================
+void AIS_PointCloud::SetPoints (const Handle(TColgp_HArray1OfPnt)&     theCoords,
+                                const Handle(Quantity_HArray1OfColor)& theColors,
+                                const Handle(TColgp_HArray1OfDir)&     theNormals)
+{
+  myPoints.Nullify();
+  myBndBox.SetVoid();
+  if (theCoords.IsNull())
+  {
+    return;
+  }
+
+  const Standard_Integer aNbPoints = theCoords->Length();
+  if ((!theNormals.IsNull() && theNormals->Length() != aNbPoints)
+   || (!theColors.IsNull()  && theColors->Length()  != aNbPoints))
+  {
+    // invalid input
+    return;
+  }
+
+  const Standard_Boolean hasColors  = !theColors.IsNull()  && theColors->Length()  == aNbPoints;
+  const Standard_Boolean hasNormals = !theNormals.IsNull() && theNormals->Length() == aNbPoints;
+
+  const Standard_Integer aDiffColors  = hasColors  ? (theColors->Lower()  - theCoords->Lower()) : 0;
+  const Standard_Integer aDiffNormals = hasNormals ? (theNormals->Lower() - theCoords->Lower()) : 0;
+
+  myPoints = new Graphic3d_ArrayOfPoints (aNbPoints, hasColors, hasNormals);
+  for (Standard_Integer aPntIter = theCoords->Lower(); aPntIter <= theCoords->Upper(); ++aPntIter)
+  {
+    myPoints->AddVertex (theCoords->Value (aPntIter));
+    if (hasColors)
+    {
+      myPoints->SetVertexColor (myPoints->VertexNumber(),
+                                theColors->Value (aPntIter + aDiffColors));
+    }
+    if (hasNormals)
+    {
+      myPoints->SetVertexNormal (myPoints->VertexNumber(),
+                                 theNormals->Value (aPntIter + aDiffNormals));
+    }
+  }
+  myBndBox = getBoundingBox (myPoints);
+}
+
+//=======================================================================
+//function : SetColor
+//purpose  :
+//=======================================================================
+void AIS_PointCloud::SetColor (const Quantity_NameOfColor theColor)
+{
+  SetColor (Quantity_Color (theColor));
+}
+
+//=======================================================================
+//function : SetColor
+//purpose  :
+//=======================================================================
+void AIS_PointCloud::SetColor (const Quantity_Color& theColor)
+{
+  AIS_InteractiveObject::SetColor(theColor);
+
+  if (!myDrawer->HasPointAspect())
+  {
+    myDrawer->SetPointAspect (new Prs3d_PointAspect (Aspect_TOM_POINT, theColor, 1.0));
+    *myDrawer->PointAspect()->Aspect() = *myDrawer->Link()->PointAspect()->Aspect();
+  }
+  if (!myDrawer->HasShadingAspect())
+  {
+    myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
+    *myDrawer->ShadingAspect()->Aspect() = *myDrawer->Link()->ShadingAspect()->Aspect();
+  }
+
+  // Override color
+  myDrawer->ShadingAspect()->SetColor (theColor);
+  myDrawer->PointAspect()  ->SetColor (theColor);
+
+  const PrsMgr_Presentations&        aPrsList     = Presentations();
+  Handle(Graphic3d_AspectMarker3d)   aPointAspect = myDrawer->PointAspect()->Aspect();
+  Handle(Graphic3d_AspectFillArea3d) anAreaAspect = myDrawer->ShadingAspect()->Aspect();
+  for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
+  {
+    const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
+    if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
+    {
+      continue;
+    }
+
+    const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
+
+    // Set aspects for presentation
+    aPrs->SetPrimitivesAspect (aPointAspect);
+    aPrs->SetPrimitivesAspect (anAreaAspect);
+
+    // Go through all groups to change color for all primitives
+    for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
+    {
+      const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
+      if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_MARKER))
+      {
+        aGroup->SetGroupPrimitivesAspect (aPointAspect);
+      }
+      if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
+      {
+        aGroup->SetGroupPrimitivesAspect (anAreaAspect);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : UnsetColor
+//purpose  :
+//=======================================================================
+void AIS_PointCloud::UnsetColor()
+{
+  if (!HasColor())
+  {
+    return;
+  }
+
+  AIS_InteractiveObject::UnsetColor();
+
+  if (!HasWidth())
+  {
+    myDrawer->SetPointAspect (Handle(Prs3d_PointAspect)());
+  }
+  else
+  {
+    Quantity_Color      aColor;
+    Aspect_TypeOfMarker aType  = Aspect_TOM_POINT;
+    Standard_Real       aScale = 1.0;
+    myDrawer->Link()->PointAspect()->Aspect()->Values (aColor, aType, aScale);
+    myDrawer->PointAspect()->SetColor (aColor);
+  }
+
+  if (HasMaterial()
+   || IsTransparent())
+  {
+    Graphic3d_MaterialAspect aMat = AIS_GraphicTool::GetMaterial (HasMaterial() ? myDrawer : myDrawer->Link());
+    if (HasMaterial())
+    {
+      Quantity_Color aColor = myDrawer->Link()->ShadingAspect()->Color (myCurrentFacingModel);
+      aMat.SetColor (aColor);
+    }
+    if (IsTransparent())
+    {
+      Standard_Real aTransp = myDrawer->ShadingAspect()->Transparency (myCurrentFacingModel);
+      aMat.SetTransparency (aTransp);
+    }
+    myDrawer->ShadingAspect()->SetMaterial (aMat, myCurrentFacingModel);
+  }
+  else
+  {
+    myDrawer->SetShadingAspect (Handle(Prs3d_ShadingAspect)());
+  }
+  myDrawer->SetPointAspect (Handle(Prs3d_PointAspect)());
+
+  // modify shading presentation without re-computation
+  const PrsMgr_Presentations&        aPrsList   = Presentations();
+  Handle(Graphic3d_AspectFillArea3d) anAreaAsp  = myDrawer->Link()->ShadingAspect()->Aspect();
+  Handle(Graphic3d_AspectMarker3d)   aMarkerAsp = myDrawer->Link()->PointAspect()->Aspect();
+  for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
+  {
+    const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
+    if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
+    {
+      continue;
+    }
+
+    const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
+    aPrs->SetPrimitivesAspect (anAreaAsp);
+    aPrs->SetPrimitivesAspect (aMarkerAsp);
+    for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
+    {
+      const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
+
+      // Check if aspect of given type is set for the group,
+      // because setting aspect for group with no already set aspect
+      // can lead to loss of presentation data
+      if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
+      {
+        aGroup->SetGroupPrimitivesAspect (anAreaAsp);
+      }
+      if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_MARKER))
+      {
+        aGroup->SetGroupPrimitivesAspect (aMarkerAsp);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : SetMaterial
+//purpose  :
+//=======================================================================
+void AIS_PointCloud::SetMaterial (const Graphic3d_NameOfMaterial theMatName)
+{
+  SetMaterial (Graphic3d_MaterialAspect (theMatName));
+}
+
+//=======================================================================
+//function : SetMaterial
+//purpose  :
+//=======================================================================
+void AIS_PointCloud::SetMaterial (const Graphic3d_MaterialAspect& theMat)
+{
+  if (!myDrawer->HasShadingAspect())
+  {
+    myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
+    *myDrawer->ShadingAspect()->Aspect() = *myDrawer->Link()->ShadingAspect()->Aspect();
+  }
+  hasOwnMaterial = Standard_True;
+
+  myDrawer->ShadingAspect()->SetMaterial (theMat, myCurrentFacingModel);
+  if (HasColor())
+  {
+    myDrawer->ShadingAspect()->SetColor (myOwnColor, myCurrentFacingModel);
+  }
+  myDrawer->ShadingAspect()->SetTransparency (myTransparency, myCurrentFacingModel);
+
+  // modify shading presentation without re-computation
+  const PrsMgr_Presentations&        aPrsList  = Presentations();
+  Handle(Graphic3d_AspectFillArea3d) anAreaAsp = myDrawer->ShadingAspect()->Aspect();
+  for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
+  {
+    const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
+    if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
+    {
+      continue;
+    }
+
+    const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
+    aPrs->SetPrimitivesAspect (anAreaAsp);
+    for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
+    {
+      const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
+      if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
+      {
+        aGroup->SetGroupPrimitivesAspect (anAreaAsp);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : UnsetMaterial
+//purpose  :
+//=======================================================================
+void AIS_PointCloud::UnsetMaterial()
+{
+  if (!HasMaterial())
+  {
+    return;
+  }
+
+  if (HasColor()
+   || IsTransparent())
+  {
+    myDrawer->ShadingAspect()->SetMaterial (myDrawer->Link()->ShadingAspect()->Material (myCurrentFacingModel),
+                                            myCurrentFacingModel);
+    if (HasColor())
+    {
+      myDrawer->ShadingAspect()->SetColor        (myOwnColor,     myCurrentFacingModel);
+      myDrawer->ShadingAspect()->SetTransparency (myTransparency, myCurrentFacingModel);
+    }
+  }
+  else
+  {
+    myDrawer->SetShadingAspect (Handle(Prs3d_ShadingAspect)());
+  }
+  hasOwnMaterial = Standard_False;
+
+  // modify shading presentation without re-computation
+  const PrsMgr_Presentations&        aPrsList  = Presentations();
+  Handle(Graphic3d_AspectFillArea3d) anAreaAsp = myDrawer->ShadingAspect()->Aspect();
+  for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
+  {
+    const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
+    if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
+    {
+      continue;
+    }
+
+    const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
+    aPrs->SetPrimitivesAspect (anAreaAsp);
+    for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
+    {
+      const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
+      if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
+      {
+        aGroup->SetGroupPrimitivesAspect (anAreaAsp);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : Compute
+//purpose  :
+//=======================================================================
+void AIS_PointCloud::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePrsMgr*/,
+                              const Handle(Prs3d_Presentation)&           thePrs,
+                              const Standard_Integer                      theMode)
+{
+  thePrs->Clear();
+  switch (theMode)
+  {
+    case AIS_PointCloud::DM_Points:
+    {
+      const Handle(Graphic3d_ArrayOfPoints) aPoints = GetPoints();
+      if (aPoints.IsNull())
+      {
+        return;
+      }
+
+      Handle(Graphic3d_AspectMarker3d) aMarkerAspect = myDrawer->PointAspect()->Aspect();
+      if (!myDrawer->HasPointAspect())
+      {
+        aMarkerAspect->SetType (Aspect_TOM_POINT);
+      }
+
+      Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePrs);
+      aGroup->SetGroupPrimitivesAspect (aMarkerAspect);
+      aGroup->AddPrimitiveArray (aPoints);
+      break;
+    }
+    case AIS_PointCloud::DM_BndBox:
+    {
+      Bnd_Box aBndBox = GetBoundingBox();
+      if (aBndBox.IsVoid())
+      {
+        return;
+      }
+
+      StdPrs_WFDeflectionRestrictedFace::AddBox (thePrs, aBndBox, myDrawer);
+      break;
+    }
+  }
+}
+
+//=======================================================================
+//function : ComputeSelection
+//purpose  :
+//=======================================================================
+void AIS_PointCloud::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
+                                       const Standard_Integer             /*theMode*/)
+{
+  Bnd_Box aBndBox = GetBoundingBox();
+  if (aBndBox.IsVoid())
+  {
+    return;
+  }
+
+  Handle(SelectMgr_EntityOwner) anOwner  = new SelectMgr_EntityOwner (this);
+  Handle(Select3D_SensitiveBox) aSensBox = new Select3D_SensitiveBox (anOwner, aBndBox);
+  theSelection->Add (aSensBox);
+}
diff --git a/src/AIS/AIS_PointCloud.hxx b/src/AIS/AIS_PointCloud.hxx
new file mode 100644 (file)
index 0000000..b16ba18
--- /dev/null
@@ -0,0 +1,128 @@
+// Created on: 2014-08-13
+// Created by: Maxim GLIBIN
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _AIS_PointCloud_HeaderFile
+#define _AIS_PointCloud_HeaderFile
+
+#include <AIS.hxx>
+#include <AIS_InteractiveObject.hxx>
+#include <Bnd_Box.hxx>
+#include <Graphic3d_ArrayOfPoints.hxx>
+#include <Quantity_HArray1OfColor.hxx>
+#include <Standard.hxx>
+#include <Standard_DefineHandle.hxx>
+#include <Standard_Macro.hxx>
+#include <TColgp_HArray1OfDir.hxx>
+#include <TColgp_HArray1OfPnt.hxx>
+
+DEFINE_STANDARD_HANDLE(AIS_PointCloud, AIS_InteractiveObject)
+
+//! Interactive object for set of points.
+//! The presentation supports two display modes:
+//! - Points.
+//! - Bounding box for highlighting.
+//! Presentation provides selection by bouding box.
+//! Selection and consequently highlighting can disabled by
+//! setting default selection mode to -1. There will be no way
+//! to select object from interactive view. Any calls to
+//! AIS_InteractiveContext::AddOrRemoveSelected should be also prohibited,
+//! to avoid programmatic highlighting (workaround is setting non-supported
+//! hilight mode, e.g. 100);
+class AIS_PointCloud : public AIS_InteractiveObject
+{
+
+public:
+
+  //! Display modes supported by this Point Cloud object
+  enum DisplayMode
+  {
+    DM_Points = 0, //!< display as normal points, default presentation
+    DM_BndBox = 2  //!< display as bounding box,  default for highlighting
+  };
+
+public:
+
+  //! Constructor.
+  Standard_EXPORT AIS_PointCloud();
+
+  //! Sets the points from array of points.
+  //! Method will not copy the input data - array will be stored as handle.
+  //! @param thePoints [in] the array of points
+  Standard_EXPORT virtual void SetPoints (const Handle(Graphic3d_ArrayOfPoints)& thePoints);
+
+  //! Sets the points with optional colors.
+  //! The input data will be copied into internal buffer.
+  //! The input arrays should have equal length, otherwise
+  //! the presentation will not be computed and displayed.
+  //! @param theCoords  [in] the array of coordinates
+  //! @param theColors  [in] optional array of colors
+  //! @param theNormals [in] optional array of normals
+  Standard_EXPORT virtual void SetPoints (const Handle(TColgp_HArray1OfPnt)&     theCoords,
+                                          const Handle(Quantity_HArray1OfColor)& theColors  = NULL,
+                                          const Handle(TColgp_HArray1OfDir)&     theNormals = NULL);
+
+public:
+
+  //! Get the points array.
+  //! Method might be overridden to fill in points array dynamically from application data structures.
+  //! @return the array of points
+  Standard_EXPORT virtual const Handle(Graphic3d_ArrayOfPoints) GetPoints() const;
+
+  //! Get bounding box for presentation.
+  Standard_EXPORT virtual Bnd_Box GetBoundingBox() const;
+
+public:
+
+  //! Setup custom color. Affects presentation only when no per-point color attribute has been assigned.
+  Standard_EXPORT virtual void SetColor (const Quantity_NameOfColor theColor);
+
+  //! Setup custom color. Affects presentation only when no per-point color attribute has been assigned.
+  Standard_EXPORT virtual void SetColor (const Quantity_Color& theColor);
+
+  //! Restore default color.
+  Standard_EXPORT virtual void UnsetColor();
+
+  //! Setup custom material. Affects presentation only when normals are defined.
+  Standard_EXPORT virtual void SetMaterial (const Graphic3d_NameOfMaterial theMatName);
+
+  //! Setup custom material. Affects presentation only when normals are defined.
+  Standard_EXPORT virtual void SetMaterial (const Graphic3d_MaterialAspect& theMat);
+
+  //! Restore default material.
+  Standard_EXPORT virtual void UnsetMaterial();
+
+protected:
+
+  //! Prepare presentation for this object.
+  Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+                                        const Handle(Prs3d_Presentation)&           thePrs,
+                                        const Standard_Integer                      theMode);
+
+  //! Prepare selection for this object.
+  Standard_EXPORT virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
+                                                 const Standard_Integer             theMode);
+
+private:
+
+  Handle(Graphic3d_ArrayOfPoints) myPoints;    //!< points array for presentation
+  Bnd_Box                         myBndBox;    //!< bounding box for presentation
+
+public:
+
+  DEFINE_STANDARD_RTTI(AIS_PointCloud)
+
+};
+
+#endif // _AIS_PointCloud_HeaderFile
index 6793959..7b81d6f 100644 (file)
@@ -290,11 +290,7 @@ uses
            aProjector           : Projector from Prs3d;
             aPresentation        : Presentation from Prs3d;
            ashape               : Shape from TopoDS) is static private;
-               
-    DisplayBox(myclass; aPrs : Presentation from Prs3d;
-                       aBox : Box from Bnd;
-                       aDrawer : Drawer from Prs3d) is protected;
-               
+
     setColor (me;
               theDrawer : Drawer from AIS;
               theColor  : Color  from Quantity)
index 416f392..468b684 100644 (file)
 
 static Standard_Boolean myFirstCompute;
 
-void AIS_Shape::DisplayBox(const Handle(Prs3d_Presentation)& aPrs,
-                           const Bnd_Box& B,
-                           const Handle(Prs3d_Drawer)& aDrawer)
-{
-  static const Standard_Integer Indx[][3] =
-  { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 0, 1 }, { 0, 0, 1 },
-    { 0, 1, 1 }, { 1, 1, 1 }, { 1, 1, 0 }, { 0, 1, 0 },
-    { 0, 0, 0 }, { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 },
-    { 0, 1, 1 }, { 0, 1, 0 }, { 1, 1, 0 }, { 1, 0, 0 } };
-
-  if ( B.IsVoid() )
-    return; // nothing to show
-
-  Standard_Real X[2],Y[2],Z[2];
-  B.Get(X[0], Y[0], Z[0], X[1], Y[1], Z[1]);
-
-  Handle(Graphic3d_Group) G = Prs3d_Root::CurrentGroup(aPrs);
-  Quantity_Color Q;
-  Aspect_TypeOfLine A;
-  Standard_Real W;
-  aDrawer->LineAspect()->Aspect()->Values(Q,A,W);
-
-  G->SetGroupPrimitivesAspect(new Graphic3d_AspectLine3d(Q,Aspect_TOL_DOTDASH,W));
-
-  Handle(Graphic3d_ArrayOfPolylines) aPolyline = new Graphic3d_ArrayOfPolylines(16);
-  Standard_Integer i(0);
-  for(;i<16;i++)
-    aPolyline->AddVertex(X[Indx[i][0]],Y[Indx[i][1]],Z[Indx[i][2]]);
-  G->AddPrimitiveArray(aPolyline);
-}
-
 static Standard_Boolean IsInList(const TColStd_ListOfInteger& LL, const Standard_Integer aMode)
 {
   TColStd_ListIteratorOfListOfInteger It(LL);
@@ -238,7 +207,7 @@ void AIS_Shape::Compute(const Handle(PrsMgr_PresentationManager3d)& /*aPresentat
     {
       // bounding box
       if (IsInfinite()) StdPrs_WFDeflectionShape::Add(aPrs,myshape,myDrawer);
-      else DisplayBox(aPrs,BoundingBox(),myDrawer);
+      else StdPrs_WFDeflectionRestrictedFace::AddBox (aPrs, BoundingBox(), myDrawer);
     }
   } // end switch
   aPrs->ReCompute(); // for hidden line recomputation if necessary...
index e50d019..b755174 100644 (file)
@@ -374,7 +374,7 @@ void AIS_TexturedShape::Compute (const Handle(PrsMgr_PresentationManager3d)& /*t
       }
       else
       {
-        AIS_Shape::DisplayBox (thePrs, BoundingBox(), myDrawer);
+        StdPrs_WFDeflectionRestrictedFace::AddBox (thePrs, BoundingBox(), myDrawer);
       }
       break;
     }
index 9b7b40d..2f3c30c 100755 (executable)
@@ -21,3 +21,5 @@ AIS_DiameterDimension.hxx
 AIS_DiameterDimension.cxx
 AIS_RadiusDimension.hxx
 AIS_RadiusDimension.cxx
+AIS_PointCloud.hxx
+AIS_PointCloud.cxx
index 1f9bf64..c63e0e3 100644 (file)
@@ -19,11 +19,13 @@ is
 
   -- constructor
   Create (maxVertexs: Integer from Standard;
-          hasVColors: Boolean from Standard = Standard_False)
+          hasVColors: Boolean from Standard = Standard_False;
+          hasVNormals: Boolean from Standard = Standard_False)
   returns ArrayOfPoints from Graphic3d;
   ---Purpose: Creates an array of points,
   -- a single pixel point is drawn at each vertex.
   -- The array must be filled using the AddVertex(Point) method. 
   -- When <hasVColors> is TRUE , you must use only AddVertex(Point,Color) method.
+  -- When <hasVNormals> is TRUE , you must use only AddVertex(Point,Normal) method.
 
 end;
index 841000f..3909b06 100644 (file)
@@ -15,6 +15,7 @@
 #include <Graphic3d_ArrayOfPoints.ixx>
 
 Graphic3d_ArrayOfPoints::Graphic3d_ArrayOfPoints (const Standard_Integer theMaxVertexs,
-                                                  const Standard_Boolean theHasVColors)
-: Graphic3d_ArrayOfPrimitives (Graphic3d_TOPA_POINTS, theMaxVertexs, 0, 0, Standard_False, theHasVColors, Standard_False, Standard_False)
+                                                  const Standard_Boolean theHasVColors,
+                                                  const Standard_Boolean theHasVNormals)
+: Graphic3d_ArrayOfPrimitives (Graphic3d_TOPA_POINTS, theMaxVertexs, 0, 0, theHasVNormals, theHasVColors, Standard_False, Standard_False)
 {}
index 303264a..cf82512 100644 (file)
@@ -29,13 +29,13 @@ inherits Root from Prs3d
       -- The presentation includes the restriction curves.
 
 uses
+    Box                  from Bnd,
     HSurface             from BRepAdaptor,
     Presentation         from Prs3d,
     Drawer               from Prs3d,
     Length               from Quantity, 
     NListOfSequenceOfPnt from Prs3d
 
-    
 is
     Add(myclass; aPresentation: Presentation from Prs3d; 
                 aFace        : HSurface     from BRepAdaptor;
@@ -113,7 +113,13 @@ is
        -- as a geometric surface.  
        -- Curves give a sequence of face curves, it is used if the PrimitiveArray  
         -- visualization approach is activated (it is activated by default).
-        
+
+    AddBox (myclass;
+            thePrs    : Presentation from Prs3d;
+            theBndBox : Box          from Bnd;
+            theDrawer : Drawer       from Prs3d);
+    ---Purpose: Adds box as polyline to the presentation object
+
     Match(myclass; X,Y,Z    : Length   from Quantity;
                    aDistance: Length   from Quantity;
                   aFace    : HSurface from BRepAdaptor;
index dfe4c04..90896de 100644 (file)
@@ -17,6 +17,8 @@
 #include <StdPrs_WFDeflectionRestrictedFace.ixx>
 
 #include <Hatch_Hatcher.hxx>
+#include <Graphic3d_ArrayOfPolylines.hxx>
+#include <Graphic3d_AspectLine3d.hxx>
 #include <Graphic3d_Group.hxx>
 #include <gp_Pnt.hxx>
 #include <gp_Pnt2d.hxx>
@@ -625,3 +627,46 @@ Standard_Boolean StdPrs_WFDeflectionRestrictedFace::MatchVIso
                       aDrawer->UIsoAspect()->Number(),
                       aDrawer->VIsoAspect()->Number());
 }
+
+namespace
+{
+  static const Standard_Integer THE_INDICES[][3] =
+  { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 0, 1 }, { 0, 0, 1 },
+    { 0, 1, 1 }, { 1, 1, 1 }, { 1, 1, 0 }, { 0, 1, 0 },
+    { 0, 0, 0 }, { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 },
+    { 0, 1, 1 }, { 0, 1, 0 }, { 1, 1, 0 }, { 1, 0, 0 } };
+}
+
+//=======================================================================
+//function : AddBox
+//purpose  :
+//=======================================================================
+void StdPrs_WFDeflectionRestrictedFace::AddBox (const Handle(Prs3d_Presentation)& thePrs,
+                                                const Bnd_Box&                    theBndBox,
+                                                const Handle(Prs3d_Drawer)&       theDrawer)
+{
+  if (theBndBox.IsVoid())
+  {
+    return;
+  }
+
+  Standard_Real X[2], Y[2], Z[2];
+  theBndBox.Get (X[0], Y[0], Z[0], X[1], Y[1], Z[1]);
+
+  Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePrs);
+  Quantity_Color    aColor;
+  Aspect_TypeOfLine aDummyLineType;
+  Standard_Real     aWidth = 1.0;
+  theDrawer->LineAspect()->Aspect()->Values (aColor, aDummyLineType, aWidth);
+
+  aGroup->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (aColor, Aspect_TOL_DOTDASH, aWidth));
+
+  Handle(Graphic3d_ArrayOfPolylines) aPolyline = new Graphic3d_ArrayOfPolylines(16);
+  for(Standard_Integer aVertIter = 0; aVertIter < 16; ++aVertIter)
+  {
+    aPolyline->AddVertex (X[THE_INDICES[aVertIter][0]],
+                          Y[THE_INDICES[aVertIter][1]],
+                          Z[THE_INDICES[aVertIter][2]]);
+  }
+  aGroup->AddPrimitiveArray (aPolyline);
+}
index 009a941..7c27d41 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <AIS_Shape.hxx>
 #include <AIS_DisplayMode.hxx>
+#include <AIS_PointCloud.hxx>
 #include <TColStd_MapOfInteger.hxx>
 #include <AIS_MapOfInteractive.hxx>
 #include <ViewerTest_AutoUpdater.hxx>
@@ -5367,6 +5368,228 @@ static int VVertexMode (Draw_Interpretor& theDI,
 }
 
 //=======================================================================
+//function : VPointCloud
+//purpose  : Create interactive object for arbitary set of points.
+//=======================================================================
+static Standard_Integer VPointCloud (Draw_Interpretor& theDI,
+                                     Standard_Integer  theArgNum,
+                                     const char**      theArgs)
+{
+  Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
+  if (anAISContext.IsNull())
+  {
+    std::cerr << "Error: no active view!\n";
+    return 1;
+  }
+
+  // command to execute
+  enum Command
+  {
+    CloudForShape, // generate point cloud for shape
+    CloudSphere,   // generate point cloud for generic sphere
+    Unknow
+  };
+
+  // count number of non-optional command arguments
+  Command aCmd = Unknow;
+  Standard_Integer aCmdArgs = 0;
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNum; ++anArgIter)
+  {
+    Standard_CString anArg = theArgs[anArgIter];
+    TCollection_AsciiString aFlag (anArg);
+    aFlag.LowerCase();
+    if (aFlag.IsRealValue() || aFlag.Search ("-") != 1)
+    {
+      aCmdArgs++;
+    }
+  }
+  switch (aCmdArgs)
+  {
+    case 2  : aCmd = CloudForShape; break;
+    case 7  : aCmd = CloudSphere; break;
+    default :
+      std::cout << "Error: wrong number of arguments! See usage:\n";
+      theDI.PrintHelp (theArgs[0]);
+      return 1;
+  }
+
+  // parse options
+  Standard_Boolean toRandColors = Standard_False;
+  Standard_Boolean hasNormals   = Standard_True;
+  Standard_Boolean isSetArgNorm = Standard_False;
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNum; ++anArgIter)
+  {
+    Standard_CString anArg = theArgs[anArgIter];
+    TCollection_AsciiString aFlag (anArg);
+    aFlag.LowerCase();
+    if (aFlag == "-randcolors"
+     || aFlag == "-randcolor")
+    {
+      if (isSetArgNorm && hasNormals)
+      {
+        std::cout << "Error: wrong syntax - normals can not be enabled with colors at the same time\n";
+        return 1;
+      }
+      toRandColors = Standard_True;
+      hasNormals   = Standard_False;
+    }
+    else if (aFlag == "-normals"
+          || aFlag == "-normal")
+    {
+      if (toRandColors)
+      {
+        std::cout << "Error: wrong syntax - normals can not be enabled with colors at the same time\n";
+        return 1;
+      }
+      isSetArgNorm = Standard_True;
+      hasNormals   = Standard_True;
+    }
+    else if (aFlag == "-nonormals"
+          || aFlag == "-nonormal")
+    {
+      isSetArgNorm = Standard_True;
+      hasNormals   = Standard_False;
+    }
+  }
+
+  Standard_CString aName = theArgs[1];
+
+  // generate arbitrary set of points
+  Handle(Graphic3d_ArrayOfPoints) anArrayPoints;
+  if (aCmd == CloudForShape)
+  {
+    Standard_CString aShapeName = theArgs[2];
+    TopoDS_Shape     aShape     = DBRep::Get (aShapeName);
+
+    if (aShape.IsNull())
+    {
+      std::cout << "Error: no shape with name '" << aShapeName << "' found\n";
+      return 1;
+    }
+
+    // calculate number of points
+    TopLoc_Location  aLocation;
+    Standard_Integer aNbPoints = 0;
+    for (TopExp_Explorer aFaceIt (aShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
+    {
+      const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current());
+      Handle(Poly_Triangulation) aTriangulation = StdPrs_ToolShadedShape::Triangulation (aFace, aLocation);
+      if (!aTriangulation.IsNull())
+      {
+        aNbPoints += aTriangulation->NbNodes();
+      }
+    }
+    if (aNbPoints < 3)
+    {
+      std::cout << "Error: shape should be triangulated!\n";
+      return 1;
+    }
+
+    anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, toRandColors, hasNormals);
+    for (TopExp_Explorer aFaceIt (aShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
+    {
+      const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current());
+      Handle(Poly_Triangulation) aTriangulation = StdPrs_ToolShadedShape::Triangulation (aFace, aLocation);
+      if (aTriangulation.IsNull())
+      {
+        continue;
+      }
+
+      const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
+      const gp_Trsf&            aTrsf  = aLocation.Transformation();
+
+      // extract normals from nodes
+      TColgp_Array1OfDir aNormals (aNodes.Lower(), hasNormals ? aNodes.Upper() : aNodes.Lower());
+      if (hasNormals)
+      {
+        Poly_Connect aPolyConnect (aTriangulation);
+        StdPrs_ToolShadedShape::Normal (aFace, aPolyConnect, aNormals);
+      }
+
+      for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
+      {
+        gp_Pnt aPoint = aNodes (aNodeIter);
+        if (!aLocation.IsIdentity())
+        {
+          aPoint.Transform (aTrsf);
+          if (hasNormals)
+          {
+            aNormals (aNodeIter).Transform (aTrsf);
+          }
+        }
+
+        // add vertex into array of points
+        const Standard_Integer anIndexOfPoint = anArrayPoints->AddVertex (aPoint);
+        if (toRandColors)
+        {
+          Quantity_Color aColor (360.0 * Standard_Real(anIndexOfPoint) / Standard_Real(aNbPoints),
+                                 1.0, 0.5, Quantity_TOC_HLS);
+          anArrayPoints->SetVertexColor (anIndexOfPoint, aColor);
+        }
+
+        if (hasNormals)
+        {
+          anArrayPoints->SetVertexNormal (anIndexOfPoint, aNormals (aNodeIter));
+        }
+      }
+    }
+  }
+  else if (aCmd == CloudSphere)
+  {
+    Standard_Real aCenterX       = Draw::Atof (theArgs[2]);
+    Standard_Real aCenterY       = Draw::Atof (theArgs[3]);
+    Standard_Real aCenterZ       = Draw::Atof (theArgs[4]);
+    Standard_Real aRadius        = Draw::Atof (theArgs[5]);
+    Standard_Integer aNbPoints   = Draw::Atoi (theArgs[6]);
+
+    TCollection_AsciiString aDistribution = TCollection_AsciiString(theArgs[7]);
+    aDistribution.LowerCase();
+    if ( aDistribution != "surface" && aDistribution != "volume" )
+    {
+      std::cout << "Error: wrong arguments! See usage:\n";
+      theDI.PrintHelp (theArgs[0]);
+      return 1;
+    }
+    Standard_Boolean isSurface = aDistribution == "surface";
+
+    gp_Pnt aCenter(aCenterX, aCenterY, aCenterZ);
+
+    anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, toRandColors, hasNormals);
+    for (Standard_Integer aPntIt = 0; aPntIt < aNbPoints; ++aPntIt)
+    {
+      Standard_Real anAlpha   = (Standard_Real (rand() % 2000) / 1000.0) * M_PI;
+      Standard_Real aBeta     = (Standard_Real (rand() % 2000) / 1000.0) * M_PI;
+      Standard_Real aDistance = isSurface ?
+        aRadius : (Standard_Real (rand() % aNbPoints) / aNbPoints) * aRadius;
+
+      gp_Dir aDir (Cos (anAlpha) * Sin (aBeta),
+                   Sin (anAlpha),
+                   Cos (anAlpha) * Cos (aBeta));
+      gp_Pnt aPoint = aCenter.Translated (aDir.XYZ() * aDistance);
+
+      const Standard_Integer anIndexOfPoint = anArrayPoints->AddVertex (aPoint);
+      if (toRandColors)
+      {
+        Quantity_Color aColor (360.0 * Standard_Real (anIndexOfPoint) / Standard_Real (aNbPoints),
+                               1.0, 0.5, Quantity_TOC_HLS);
+        anArrayPoints->SetVertexColor (anIndexOfPoint, aColor);
+      }
+
+      if (hasNormals)
+      {
+        anArrayPoints->SetVertexNormal (anIndexOfPoint, aDir);
+      }
+    }
+  }
+
+  // set array of points in point cloud object
+  Handle(AIS_PointCloud) aPointCloud = new AIS_PointCloud();
+  aPointCloud->SetPoints (anArrayPoints);
+  VDisplayAISObject (aName, aPointCloud);
+  return 0;
+}
+
+//=======================================================================
 //function : ObjectsCommands
 //purpose  :
 //=======================================================================
@@ -5562,4 +5785,21 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
                    "vvertexmode -set {isolated | all | inherited} - sets the default vertex draw mode and updates the mode for all displayed objects\n"
                    "vvertexmode -set {isolated | all | inherited} name1 name2 ... - sets the vertex draw mode for the specified object(s)\n",
                    __FILE__, VVertexMode, group);
+
+  theCommands.Add ("vpointcloud",
+                   "vpointcloud name shape [-randColor] [-normals] [-noNormals]"
+                   "\n\t\t: Create an interactive object for arbitary set of points"
+                   "\n\t\t: from triangulated shape."
+                   "\n"
+                   "vpointcloud name x y z r npts {surface|volume}\n"
+                   "            ... [-randColor] [-normals] [-noNormals]"
+                   "\n\t\t: Create arbitrary set of points (npts) randomly distributed"
+                   "\n\t\t: on spheric surface or within spheric volume (x y z r)."
+                   "\n\t\t:"
+                   "\n\t\t: Additional options:"
+                   "\n\t\t:  -randColor - generate random color per point"
+                   "\n\t\t:  -normals   - generate normal per point (default)"
+                   "\n\t\t:  -noNormals - do not generate normal per point"
+                   "\n",
+                   __FILE__, VPointCloud, group);
 }
index 7be59dc..6603b37 100644 (file)
@@ -14,3 +14,5 @@
 014 raytrace
 015 materials
 016 ivtk
+017 mesh
+018 point_cloud
diff --git a/tests/v3d/point_cloud/sphere b/tests/v3d/point_cloud/sphere
new file mode 100644 (file)
index 0000000..70dd27a
--- /dev/null
@@ -0,0 +1,30 @@
+puts "========"
+puts "Point cloud object from triangulated sphere"
+puts "========"
+
+# create sphere
+sphere ss 10
+mkface s ss
+incmesh s 0.01
+
+# draw sphere
+vinit View1
+vclear
+vsetdispmode 1
+vaxo
+vpointcloud p s -nonormals
+vaspects p -setcolor GREEN
+vfit
+vrotate 0.2 0.0 0.0
+vdump $::imagedir/${::casename}_green.png
+
+# random colors mode
+vpointcloud p s -randcolors
+vdump $::imagedir/${::casename}_rand.png
+
+# mode with normals
+vpointcloud p s -normals
+vsetmaterial p COPPER
+vdump $::imagedir/${::casename}_copper.png
+
+vmoveto 200 200