[原创]HOW TO: OCC中渲染状态下显示Shape边线(Edge)的最佳实践
作者:spas
n年前曾经用过Open Cascade,嫌太慢放弃了,现在升到6.3版本,速度有了很大提升。刚好工作中有需要,就好好研究了一下。本篇是介绍如何在渲染状态下显示Shape边线(Edge)的最佳实践。找了很多地方都没有找到,只好自己摸索。现贴出来与大家共享。
实践一
假设shape是一个已经生成的TopoDS_Shape对象。如下代码:
//显示ShapeHandle (AIS_MyShape)
ais =newAIS_MyShape(shape);
myAISContext->SetColor(ais,qcolor,Standard_False);
myAISContext->SetMaterial(ais,material,Standard_False);
myAISContext->SetTransparency(ais, transparency/10.0,Standard_False);
myAISContext->SetDisplayMode(ais,1,Standard_False);
myAISContext->Display(ais, updateview);
//生成边线组
BRep_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
for(TopExp_Explorer ex(shape,TopAbs_EDGE) ; ex.More(); ex.Next())
{
TopoDS_Edge F =TopoDS::Edge(ex.Current());
builder.Add(comp, F);
}
//显示边线组
Handle (AIS_Shape) compShape =newAIS_Shape(comp);
myAISContext->SetColor(compShape, myEdgeColor,Standard_False);
myAISContext->Display(compShape, updateview);
这种方法的缺点:由于对一个物体生成了两个AIS_Shape,故在进行数据管理时会引起更复杂的编码。
最佳实践:
思路:从继承自己的Shape,定制其显示行为。如下代码:
// File: AIS_MyShape.hxx
// Created: 2009.4.1
// Author: Z. C.
#ifndef _AIS_MyShape_HeaderFile
#define _AIS_MyShape_HeaderFile
#include <Standard_DefineHandle.hxx>
class TopoDS_Shape;
DEFINE_STANDARD_HANDLE(AIS_MyShape, AIS_Shape)
class AIS_MyShape :publicAIS_Shape
{
public:
DEFINE_STANDARD_RTTI(AIS_MyShape)
AIS_MyShape(intkey,const TopoDS_Shape& aShape);
~AIS_MyShape();
Standard_Boolean IsKind(constHandle(Standard_Type)& AType)const;
protected:
virtual void Compute(constHandle(PrsMgr_PresentationManager3d)& aPresentationManager,constHandle(Prs3d_Presentation)& aPresentation,constStandard_Integer aMode = 0) ;
int myKey;
};
inline Standard_Boolean AIS_MyShape::IsKind(constHandle(Standard_Type)& AType)const
{return(STANDARD_TYPE(AIS_MyShape) == AType || AIS_Shape::IsKind(AType)); }
#endif
// File: AIS_MyShape.cxx
// Created: 2009.4.1
// Author: Z. C.
#include"stdafx.h"
#include <Prs3d_LineAspect.hxx>
#include <StdPrs_Curve.hxx>
#include <StdPrs_ShadedShape.hxx>
#include <StdPrs_WFDeflectionShape.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <BRep_Tool.hxx>
#include <Graphic3d_Group.hxx>
#include <Graphic3d_Structure.hxx>
#include <Graphic3d_AspectLine3d.hxx>
#include <Graphic3d_Array1OfVertex.hxx>
#include"AIS_MyShape.hxx"
IMPLEMENT_STANDARD_HANDLE(AIS_MyShape,AIS_Shape)
IMPLEMENT_STANDARD_RTTI(AIS_MyShape,AIS_Shape)
//
// Foreach ancestors, we add a IMPLEMENT_STANDARD_SUPERTYPE and
// a IMPLEMENT_STANDARD_SUPERTYPE_ARRAY_ENTRY macro.
// We must respect the order: from the direct ancestor class
// to the base class.
//
IMPLEMENT_STANDARD_TYPE(AIS_MyShape)
IMPLEMENT_STANDARD_SUPERTYPE(AIS_Shape)
IMPLEMENT_STANDARD_SUPERTYPE(AIS_InteractiveObject)
IMPLEMENT_STANDARD_SUPERTYPE(SelectMgr_SelectableObject)
IMPLEMENT_STANDARD_SUPERTYPE(PrsMgr_PresentableObject)
IMPLEMENT_STANDARD_SUPERTYPE(MMgt_TShared)
IMPLEMENT_STANDARD_SUPERTYPE(Standard_Transient)
IMPLEMENT_STANDARD_SUPERTYPE_ARRAY()
IMPLEMENT_STANDARD_SUPERTYPE_ARRAY_ENTRY(AIS_Shape)
IMPLEMENT_STANDARD_SUPERTYPE_ARRAY_ENTRY(AIS_InteractiveObject)
IMPLEMENT_STANDARD_SUPERTYPE_ARRAY_ENTRY(SelectMgr_SelectableObject)
IMPLEMENT_STANDARD_SUPERTYPE_ARRAY_ENTRY(PrsMgr_PresentableObject)
IMPLEMENT_STANDARD_SUPERTYPE_ARRAY_ENTRY(MMgt_TShared)
IMPLEMENT_STANDARD_SUPERTYPE_ARRAY_ENTRY(Standard_Transient)
IMPLEMENT_STANDARD_SUPERTYPE_ARRAY_END()
IMPLEMENT_STANDARD_TYPE_END(AIS_MyShape)
AIS_MyShape::AIS_MyShape(intkey,constTopoDS_Shape& aShape) : AIS_Shape(aShape)
{ myKey = key; }
AIS_MyShape::~AIS_MyShape() { }
//=======================================================================
//function : Compute
//purpose :
//=======================================================================
void AIS_MyShape::Compute(constHandle(PrsMgr_PresentationManager3d)& aPresentationManager,constHandle(Prs3d_Presentation)& aPrs,constStandard_Integer aMode)
{
AIS_Shape::Compute(aPresentationManager, aPrs, aMode);
//Handle(Graphic3d_Group) G = Prs3d_Root::CurrentGroup(aPrs); 不能用CurrentGroup
Handle_Graphic3d_Structure theStructure = Handle_Graphic3d_Structure::DownCast(aPrs);
Handle_Graphic3d_Group G=newGraphic3d_Group(theStructure);
//Handle(AIS_Drawer) aDrawer =newAIS_Drawer();
//Quantity_Color Q;
//Aspect_TypeOfLine A;
//Standard_Real W;
//aDrawer->LineAspect()->Aspect()->Values(Q,A,W);
G->SetGroupPrimitivesAspect(newGraphic3d_AspectLine3d(Quantity_NOC_BLACK, Aspect_TOL_DASH, 0.1));
Standard_Real c_start;
Standard_Real c_end;
Graphic3d_Array1OfVertex VVV (1,2);
G->BeginPrimitives();
for(TopExp_Explorer ex(myshape,TopAbs_EDGE) ; ex.More(); ex.Next())
{
TopoDS_Edge edge =TopoDS::Edge(ex.Current());
Handle(Geom_Curve) c = BRep_Tool::Curve(edge, c_start, c_end);//一个无限的曲线
Handle(Geom_TrimmedCurve) myTrimmed =newGeom_TrimmedCurve(c, c_start, c_end);//转换成有限曲线
//这段代码只能处理直线,故注释
//VVV.SetValue(1, Graphic3d_Vertex(myTrimmed->StartPoint().X(), myTrimmed->StartPoint().Y(), myTrimmed->StartPoint().Z()));
//VVV.SetValue(2, Graphic3d_Vertex(myTrimmed->EndPoint().X(), myTrimmed->EndPoint().Y(), myTrimmed->EndPoint().Z()));
//G->Polyline(VVV);
//上面三行注释掉的代码替换为如下代码
GeomAdaptor_Curve anAdaptorCurve(myTrimmed);
Standard_Integer NbPoints = myDrawer->Discretisation();
Standard_Real V1, V2;
FindLimits(anAdaptorCurve, myDrawer->MaximalParameterValue(), V1, V2);
TColgp_SequenceOfPnt Pnts;
DrawCurve(anAdaptorCurve, G, NbPoints, V1 , V2, Pnts, Standard_True);
}
G->EndPrimitives();
}
以上代码用到的函数:
{Code}static Standard_Integer myN = -1;
static Standard_Boolean first = Standard_True;
//==================================================================
// function: FindLimits
// purpose:
//==================================================================
static void FindLimits(const Adaptor3d_Curve& aCurve,
const Standard_Real aLimit,
Standard_Real& First,
Standard_Real& Last)
{
First = aCurve.FirstParameter();
Last = aCurve.LastParameter();
Standard_Boolean firstInf = Precision::IsNegativeInfinite(First);
Standard_Boolean lastInf = Precision::IsPositiveInfinite(Last);
if (firstInf || lastInf) {
gp_Pnt P1,P2;
Standard_Real delta = 1;
if (firstInf && lastInf) {
do {
delta *= 2;
First = - delta;
Last = delta;
aCurve.D0(First,P1);
aCurve.D0(Last,P2);
} while (P1.Distance(P2) < aLimit);
}
else if (firstInf) {
aCurve.D0(Last,P2);
do {
delta *= 2;
First = Last - delta;
aCurve.D0(First,P1);
} while (P1.Distance(P2) < aLimit);
}
else if (lastInf) {
aCurve.D0(First,P1);
do {
delta *= 2;
Last = First + delta;
aCurve.D0(Last,P2);
} while (P1.Distance(P2) < aLimit);
}
}
}
//==================================================================
// function: DrawCurve
// purpose:
//==================================================================
static void DrawCurve (const Adaptor3d_Curve& aCurve,
const Handle(Graphic3d_Group) aGroup,
const Standard_Integer NbP,
const Standard_Real U1,
const Standard_Real U2,
TColgp_SequenceOfPnt& Points,
const Standard_Boolean drawCurve)
{
Standard_Integer nbintervals = 1;
if (aCurve.GetType() == GeomAbs_BSplineCurve) {
nbintervals = aCurve.NbKnots() - 1;
nbintervals = Max(1, nbintervals/3);
}
Standard_Boolean isPrimArrayEnabled = Graphic3d_ArrayOfPrimitives::IsEnable() && !drawCurve;
switch (aCurve.GetType()) {
case GeomAbs_Line:
{
#ifdef OCC64
Graphic3d_Array1OfVertex VertexArray(1, 3);
gp_Pnt p = aCurve.Value(U1);
Points.Append(p);
VertexArray(1).SetCoord(p.X(), p.Y(), p.Z());
p = aCurve.Value(0.5 * (U1 + U2));
Points.Append(p);
VertexArray(2).SetCoord(p.X(), p.Y(), p.Z());
p = aCurve.Value(U2);
Points.Append(p);
VertexArray(3).SetCoord(p.X(), p.Y(), p.Z());
if(!isPrimArrayEnabled)
aGroup->Polyline(VertexArray);
#else
static Graphic3d_Array1OfVertex VertexLine(1,2);
gp_Pnt p = aCurve.Value(U1);
Points.Append(p);
VertexLine(1).SetCoord(p.X(), p.Y(), p.Z());
p = aCurve.Value(U2);
Points.Append(p);
VertexLine(2).SetCoord(p.X(), p.Y(), p.Z());
if(!isPrimArrayEnabled)
aGroup->Polyline(VertexLine);
#endif
}
break;
default:
{
Standard_Real U;
Standard_Integer N = Max(2, NbP*nbintervals);
Standard_Real DU = (U2-U1) / (N-1);
gp_Pnt p;
if (first) {
myN = N;
first = Standard_False;
}
if (myN == N) {
static Graphic3d_Array1OfVertex VertexArray(1, N);
for (Standard_Integer i = 1; i <= N;i++) {
U = U1 + (i-1)*DU;
p = aCurve.Value(U);
Points.Append(p);
VertexArray(i).SetCoord(p.X(), p.Y(), p.Z());
}
if(!isPrimArrayEnabled)
aGroup->Polyline(VertexArray);
}
else {
Graphic3d_Array1OfVertex VertexArray2(1, N);
for (Standard_Integer i = 1; i <= N;i++) {
U = U1 + (i-1)*DU;
p = aCurve.Value(U);
Points.Append(p);
VertexArray2(i).SetCoord(p.X(), p.Y(), p.Z());
}
if(!isPrimArrayEnabled)
aGroup->Polyline(VertexArray2);
}
}
}
}
Enjoy it!
阅读全文
类别:信息技术 查看评论