From d33222c108e49e3db564f209ded4fe25935c3731 Mon Sep 17 00:00:00 2001 From: apl Date: Thu, 25 Sep 2014 13:54:33 +0400 Subject: [PATCH] =?UTF-8?q?=EF=BB=BF0025129:=20Visualization=20-=20add=20i?= =?UTF-8?q?nteractive=20object=20for=20Points=20Cloud=20objects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/AIS/AIS.cdl | 3 +- src/AIS/AIS_PointCloud.cxx | 451 ++++++++++++++++++ src/AIS/AIS_PointCloud.hxx | 128 +++++ src/AIS/AIS_Shape.cdl | 6 +- src/AIS/AIS_Shape.cxx | 33 +- src/AIS/AIS_TexturedShape.cxx | 2 +- src/AIS/FILES | 2 + src/Graphic3d/Graphic3d_ArrayOfPoints.cdl | 4 +- src/Graphic3d/Graphic3d_ArrayOfPoints.cxx | 5 +- .../StdPrs_WFDeflectionRestrictedFace.cdl | 10 +- .../StdPrs_WFDeflectionRestrictedFace.cxx | 45 ++ src/ViewerTest/ViewerTest_ObjectCommands.cxx | 240 ++++++++++ tests/v3d/grids.list | 2 + tests/v3d/point_cloud/sphere | 30 ++ 14 files changed, 917 insertions(+), 44 deletions(-) create mode 100644 src/AIS/AIS_PointCloud.cxx create mode 100644 src/AIS/AIS_PointCloud.hxx create mode 100644 tests/v3d/point_cloud/sphere diff --git a/src/AIS/AIS.cdl b/src/AIS/AIS.cdl index 3abdfc8c15..657e746594 100644 --- a/src/AIS/AIS.cdl +++ b/src/AIS/AIS.cdl @@ -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 index 0000000000..c9c588f426 --- /dev/null +++ b/src/AIS/AIS_PointCloud.cxx @@ -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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 index 0000000000..b16ba185d4 --- /dev/null +++ b/src/AIS/AIS_PointCloud.hxx @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 diff --git a/src/AIS/AIS_Shape.cdl b/src/AIS/AIS_Shape.cdl index 6793959936..7b81d6f1c8 100644 --- a/src/AIS/AIS_Shape.cdl +++ b/src/AIS/AIS_Shape.cdl @@ -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) diff --git a/src/AIS/AIS_Shape.cxx b/src/AIS/AIS_Shape.cxx index 416f39274c..468b684de0 100644 --- a/src/AIS/AIS_Shape.cxx +++ b/src/AIS/AIS_Shape.cxx @@ -77,37 +77,6 @@ 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... diff --git a/src/AIS/AIS_TexturedShape.cxx b/src/AIS/AIS_TexturedShape.cxx index e50d019b7b..b755174944 100644 --- a/src/AIS/AIS_TexturedShape.cxx +++ b/src/AIS/AIS_TexturedShape.cxx @@ -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; } diff --git a/src/AIS/FILES b/src/AIS/FILES index 9b7b40d1f5..2f3c30c8e9 100755 --- a/src/AIS/FILES +++ b/src/AIS/FILES @@ -21,3 +21,5 @@ AIS_DiameterDimension.hxx AIS_DiameterDimension.cxx AIS_RadiusDimension.hxx AIS_RadiusDimension.cxx +AIS_PointCloud.hxx +AIS_PointCloud.cxx diff --git a/src/Graphic3d/Graphic3d_ArrayOfPoints.cdl b/src/Graphic3d/Graphic3d_ArrayOfPoints.cdl index 1f9bf64ceb..c63e0e3d06 100644 --- a/src/Graphic3d/Graphic3d_ArrayOfPoints.cdl +++ b/src/Graphic3d/Graphic3d_ArrayOfPoints.cdl @@ -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 is TRUE , you must use only AddVertex(Point,Color) method. + -- When is TRUE , you must use only AddVertex(Point,Normal) method. end; diff --git a/src/Graphic3d/Graphic3d_ArrayOfPoints.cxx b/src/Graphic3d/Graphic3d_ArrayOfPoints.cxx index 841000f601..3909b0638e 100644 --- a/src/Graphic3d/Graphic3d_ArrayOfPoints.cxx +++ b/src/Graphic3d/Graphic3d_ArrayOfPoints.cxx @@ -15,6 +15,7 @@ #include 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) {} diff --git a/src/StdPrs/StdPrs_WFDeflectionRestrictedFace.cdl b/src/StdPrs/StdPrs_WFDeflectionRestrictedFace.cdl index 303264a15f..cf82512008 100644 --- a/src/StdPrs/StdPrs_WFDeflectionRestrictedFace.cdl +++ b/src/StdPrs/StdPrs_WFDeflectionRestrictedFace.cdl @@ -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; diff --git a/src/StdPrs/StdPrs_WFDeflectionRestrictedFace.cxx b/src/StdPrs/StdPrs_WFDeflectionRestrictedFace.cxx index dfe4c045b4..90896def57 100644 --- a/src/StdPrs/StdPrs_WFDeflectionRestrictedFace.cxx +++ b/src/StdPrs/StdPrs_WFDeflectionRestrictedFace.cxx @@ -17,6 +17,8 @@ #include #include +#include +#include #include #include #include @@ -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); +} diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx index 009a941b80..7c27d41705 100644 --- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx +++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -5366,6 +5367,228 @@ static int VVertexMode (Draw_Interpretor& theDI, return 0; } +//======================================================================= +//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); } diff --git a/tests/v3d/grids.list b/tests/v3d/grids.list index 7be59dc047..6603b373a4 100644 --- a/tests/v3d/grids.list +++ b/tests/v3d/grids.list @@ -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 index 0000000000..70dd27a1e3 --- /dev/null +++ b/tests/v3d/point_cloud/sphere @@ -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