MFC中使用OpenCasCade示例

目录:

一、OpenCasCade开发环境搭建

二、创建一个MFC应用程序

三、在MFC工程中添加代码

四、画个瓶子

 

一、OpenCasCade开发环境搭建

参见《OpenCasCade开发环境搭建》,这篇文章最后运行示例前所做的工作为以后开发OpenCasCade工程铺平了路,无需额外的配置,只需在新建的工程中加你的代码即可。

二、创建一个MFC应用程序

1

2

到此步,点击完成即可(注意我的配置选项)。

三、在MFC工程中添加代码

第一步: 添加头文件

 stdafx.h 头文件中添加以下内容(以后用到的OpenCasCade的头文件,都可以放到这里,这样会很方便,为什么放在这里以及为什么方便请参考《C++预编译头文件 – stdafx.h》):

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

#pragma warning (  disable : 4244 )        // Issue warning 4244

#include "Standard_ShortReal.hxx"

#pragma warning (  default : 4244 )        // Issue warning 4244

#include <Standard.hxx>

#include <Standard_PrimitiveTypes.hxx>

#include <AIS_InteractiveContext.hxx>

#include <AIS_Line.hxx>

#include <AIS_Shape.hxx>

#include <AIS_Drawer.hxx>

#include <AIS_Point.hxx>

#include <AIS_TexturedShape.hxx>

#include <Aspect_Grid.hxx>

#include <Aspect_PolygonOffsetMode.hxx>

#include <Aspect_TypeOfText.hxx>

#include <Aspect_DisplayConnection.hxx>

#include <Aspect_AspectMarker.hxx>

 

#include <BRep_Tool.hxx>

#include <BRepTools.hxx>

#include <BRepBuilderAPI_NurbsConvert.hxx>

#include <BRepPrimAPI_MakeCylinder.hxx>

#include <BRepBuilderAPI_MakeEdge.hxx>

#include <BRepBuilderAPI_MakeWire.hxx>

#include <BRepBuilderAPI_MakeFace.hxx>

#include <BRepBndLib.hxx>

#include <BRepAdaptor_HArray1OfCurve.hxx>

#include <BRepAdaptor_Curve2d.hxx>

#include <BRepBuilderAPI_MakeVertex.hxx>

 

#include <GCPnts_QuasiUniformDeflection.hxx>

 

#include <Geom2d_TrimmedCurve.hxx>

#include <GeomLib.hxx>

#include <Geom_Surface.hxx>

#include <Geom_Curve.hxx>

#include <Geom_Plane.hxx>

#include <Geom_CartesianPoint.hxx>

 

#include <Graphic3d_Group.hxx>

#include <Graphic3d_HorizontalTextAlignment.hxx>

#include <Graphic3d_VerticalTextAlignment.hxx>

#include <Graphic3d_Array1OfVertex.hxx>

#include <Graphic3d_ArrayOfPolylines.hxx>

#include <Graphic3d.hxx>

#include <Graphic3d_ExportFormat.hxx>

#include <Graphic3d_ArrayOfPolylines.hxx>

#include <Graphic3d_AspectFillArea3d.hxx>

#include <Graphic3d_AspectText3d.hxx>

#include <Graphic3d_AspectLine3d.hxx>

#include <Graphic3d_AspectMarker3d.hxx>

#include <Graphic3d_Texture1Dsegment.hxx>

 

#include <gp_Pln.hxx>

#include <gp.hxx>

#include <gp_Pnt2d.hxx>

 

#include <OpenGl_GraphicDriver.hxx>

#include <Prs3d_Root.hxx>

#include <Prs3d_Drawer.hxx>

#include <Prs3d_IsoAspect.hxx>

#include <Prs3d_ShadingAspect.hxx>

#include <Prs3d_Presentation.hxx>

#include <PrsMgr_PresentationManager3d.hxx>

#include <Prs3d_TextAspect.hxx>

#include <Prs3d_Text.hxx>

#include <Select3D_ListOfSensitive.hxx>

#include <Select3D_SensitiveBox.hxx>

#include <Select3D_SensitiveCurve.hxx>

#include <Select3D_SensitiveGroup.hxx>

#include <SelectMgr_Selection.hxx>

#include <SelectMgr_SequenceOfOwner.hxx>

#include <SelectMgr_EntityOwner.hxx>

#include <ShapeBuild_Edge.hxx>

#include <StdSelect_ViewerSelector3d.hxx>

#include <StdPrs_ShadedShape.hxx>

#include <StdPrs_HLRPolyShape.hxx>

#include <StdSelect_BRepSelectionTool.hxx>

#include <StdPrs_WFDeflectionShape.hxx>

#include <StdPrs_WFShape.hxx>

#include <StdPrs_ToolRFace.hxx>

#include <StdSelect.hxx>

#include <StdSelect_BRepOwner.hxx>

#include <StdSelect_BRepSelectionTool.hxx>

#include <TCollection_AsciiString.hxx>

#include "TopExp.hxx"

#include <TopExp_Explorer.hxx>

 

#include <TopoDS.hxx>

#include <TopoDS_Builder.hxx>

#include <TopoDS_Compound.hxx>

#include <TopoDS_ListOfShape.hxx>

#include <TopoDS_ListIteratorOfListOfShape.hxx>

#include <TopoDS_Iterator.hxx>

#include "TopoDS_Edge.hxx"

#include "TopoDS_Vertex.hxx"

#include <TopTools_HSequenceOfShape.hxx>

#include <TopTools_IndexedMapOfShape.hxx>

#include <Visual3d_View.hxx>

#include <V3d_Viewer.hxx>

#include <V3d_View.hxx>

#include <WNT_Window.hxx>

#include <Standard_Macro.hxx>

#include <Graphic3d_GraphicDriver.hxx>

 

#include <BRepAlgoAPI_Fuse.hxx>

#include <BRepBuilderAPI_Transform.hxx>

#include <BRepFilletAPI_MakeFillet.hxx>

#include <BRepLib.hxx>

#include <BRepOffsetAPI_MakeThickSolid.hxx>

#include <BRepOffsetAPI_ThruSections.hxx>

#include <BRepPrimAPI_MakePrism.hxx>

 

#include <GC_MakeArcOfCircle.hxx>

#include <GC_MakeSegment.hxx>

#include <GCE2d_MakeSegment.hxx>

 

#include <gp_Ax1.hxx>

#include <gp_Ax2.hxx>

#include <gp_Ax2d.hxx>

#include <gp_Dir.hxx>

#include <gp_Dir2d.hxx>

#include <gp_Pnt.hxx>

#include <gp_Pnt2d.hxx>

#include <gp_Trsf.hxx>

#include <gp_Vec.hxx>

 

#include <Geom_CylindricalSurface.hxx>

#include <Geom2d_Ellipse.hxx>

 

#include <TopoDS_Face.hxx>

#include <TopoDS_Wire.hxx>

#include <TopoDS_Shape.hxx>

 

第二步:在APP类的头文件中添加设置OpenCasCade的图形设备环境变量

在APP类 头文件中添加 标准宏定义 和 图形设备 头文件

 

1

2

#include <Standard_Macro.hxx>

#include <Graphic3d_GraphicDriver.hxx>

 

Standard_Macro.hxx: This file is intended to be the first file #included to any Open CASCADE source. It defines platform-specific pre-processor macros necessary for correct compilation of Open CASCADE code.

Graphic3d_GraphicDriver.hxx:This class allows the definition of a graphic driver (currently only OpenGL driver is used).

在APP类添加以下成员变量和方法:

 

1

2

3

4

5

6

7

8

9

//头文件   注意,别把下面这几行代码放在DECLARE_MESSAGE_MAP()后面了!

Handle_Graphic3d_GraphicDriver myGraphicDriver;

Handle_Graphic3d_GraphicDriver GetGraphicDriver()const;

 

//源文件

Handle_Graphic3d_GraphicDriver CneedAVApp::GetGraphicDriver()const

{

return myGraphicDriver;

}

在APP类的构造函数中完成对设备环境生成和初始化:

 

1

2

3

4

5

6

7

8

9

10

try

{

   Handle(Aspect_DisplayConnection) aDisplayConnection;

   myGraphicDriver = new OpenGl_GraphicDriver (aDisplayConnection);

}

catch(Standard_Failure)

{

    // AfxMessageBox ("Fatal error during graphic initialization", MB_ICONSTOP);

    ExitProcess (1);

}

如图:

3

此时编译会提示如下错误:

 

1

error C2661: “Standard_Transient::operator new”: 没有重载函数接受 3 个参数

原因是因为OpenCascade对new操作符进行了重载,与VS中的定义存在冲突,屏蔽CPP文件前面的以下代码就可以解决了。

 

1

2

3

#ifdef _DEBUG

/*#define new DEBUG_NEW*/

#endif

后面OpenCascade使用new操作符的地方,都需同样的方法解决。更多请阅读:http://www.opencascade.org/org/forum/thread_14858/?forum=3

第三步:在Document类中添加OpenCasCade间接设备环境和图形接口

在Doc类的头文件中添加OpenCasCade成员变量和方法:

 

1

2

3

4

5

6

7

//几个方法的声明和定义分开写,在调用时会有LNK2019错误,原因不明(我才特么没有写错字母),知道的亲还请留言告知,(∩_∩)

public:

Handle(V3d_Viewer) myViewer;

Handle(AIS_InteractiveContext) myAISContext;

Handle(AIS_InteractiveContext)& GetAISContext(){ return myAISContext;}

Handle(V3d_Viewer) GetViewer(){ return myViewer;}

Handle(AIS_InteractiveContext)& GetInteractiveContext(){ return myAISContext;}

接着在Doc类的构造函数中完成对OpenCasCade变量初始化设置:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

CneedAVDoc::CneedAVDoc()

{

// TODO: 在此添加一次性构造代码

Handle(Graphic3d_GraphicDriver) aGraphicDriver = ((CTest2App*)AfxGetApp())->GetGraphicDriver();

 

TCollection_ExtendedString a3DName("Visu3D");

myViewer = new V3d_Viewer(aGraphicDriver,a3DName.ToExtString());

 

myViewer->SetDefaultLights();

myViewer->SetLightOn();

//myViewer->SetDefaultBackgroundColor(Quantity_NOC_BLUE1);//改变背景颜色

 

myAISContext =new AIS_InteractiveContext(myViewer);  //创建一个交互文档

myAISContext->DefaultDrawer()->UIsoAspect()->SetNumber(11);

myAISContext->DefaultDrawer()->VIsoAspect()->SetNumber(11);

 

//这里设置实体的显示模式

myAISContext->SetDisplayMode(AIS_Shaded,Standard_False);

}

 

第四步:View类中的OpenCasCade变量设置以及图形显示设置

添加变量:

 

1

2

3

private:

Handle_V3d_View myView;

Standard_Boolean myHlrModeIsOn;

重写 OnInitialUpdate() 函数,添加如下代码:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

void CneedAVView::OnInitialUpdate()

{

CView::OnInitialUpdate();

 

myView =((CneedAVDoc*)GetDocument())->GetViewer()->CreateView();

myHlrModeIsOn = Standard_False;

myView -> SetComputedMode(myHlrModeIsOn);

Handle(Graphic3d_GraphicDriver) aGraphicDriver = ((CneedAVApp*)AfxGetApp())->GetGraphicDriver();

Handle(WNT_Window) aWNTWindow = new WNT_Window(GetSafeHwnd());  

myView->SetWindow(aWNTWindow);

 

if (!aWNTWindow->IsMapped()) aWNTWindow->Map();

aWNTWindow->SetBackground(Quantity_NOC_SLATEBLUE2);

// TODO: 在此添加专用代码和/或调用基类

}

在OnDraw函数中添加OpenCasCade的重绘代码:

 

1

2

3

4

5

6

7

8

9

10

void CneedAVView::OnDraw(CDC* /*pDC*/)

{

CneedAVDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!pDoc)

return;

 

myView->Redraw();

// TODO: 在此处为本机数据添加绘制代码

}

至此,运行程序,你便可以看到 OpenCasCade 灰灰的窗口了,如图:

5

四、画个瓶子

弄好这些,我们便可以使用OpenCasCade工作了。为方便,我们就直接用官方给的画瓶子的函数代码即可(给View类添加MakeBottle方法,很多人因为这个出错,请大家仔细看教程哈),MakeBottle函数代码如下(所需的头文件,已全部扔进stdafx.h):

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

TopoDS_Shape

MakeBottle(const Standard_Real myWidth, const Standard_Real myHeight,

           const Standard_Real myThickness)

{

  // Profile : Define Support Points

  gp_Pnt aPnt1(-myWidth / 2., 0, 0);        

  gp_Pnt aPnt2(-myWidth / 2., -myThickness / 4., 0);

  gp_Pnt aPnt3(0, -myThickness / 2., 0);

  gp_Pnt aPnt4(myWidth / 2., -myThickness / 4., 0);

  gp_Pnt aPnt5(myWidth / 2., 0, 0);

 

  // Profile : Define the Geometry

  Handle(Geom_TrimmedCurve) anArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3,aPnt4);

  Handle(Geom_TrimmedCurve) aSegment1 = GC_MakeSegment(aPnt1, aPnt2);

  Handle(Geom_TrimmedCurve) aSegment2 = GC_MakeSegment(aPnt4, aPnt5);

 

  // Profile : Define the Topology

  TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aSegment1);

  TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(anArcOfCircle);

  TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(aSegment2);

  TopoDS_Wire aWire  = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3);

 

  // Complete Profile

  gp_Ax1 xAxis = gp::OX();

  gp_Trsf aTrsf;

 

  aTrsf.SetMirror(xAxis);

  BRepBuilderAPI_Transform aBRepTrsf(aWire, aTrsf);

  TopoDS_Shape aMirroredShape = aBRepTrsf.Shape();

  TopoDS_Wire aMirroredWire = TopoDS::Wire(aMirroredShape);

 

  BRepBuilderAPI_MakeWire mkWire;

  mkWire.Add(aWire);

  mkWire.Add(aMirroredWire);

  TopoDS_Wire myWireProfile = mkWire.Wire();

 

  // Body : Prism the Profile

  TopoDS_Face myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile);

  gp_Vec aPrismVec(0, 0, myHeight);

  TopoDS_Shape myBody = BRepPrimAPI_MakePrism(myFaceProfile, aPrismVec);

 

  // Body : Apply Fillets

  BRepFilletAPI_MakeFillet mkFillet(myBody);

  TopExp_Explorer anEdgeExplorer(myBody, TopAbs_EDGE);

  while(anEdgeExplorer.More()){

    TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExplorer.Current());

    //Add edge to fillet algorithm

    mkFillet.Add(myThickness / 12., anEdge);

    anEdgeExplorer.Next();

  }

 

  myBody = mkFillet.Shape();

 

  // Body : Add the Neck

  gp_Pnt neckLocation(0, 0, myHeight);

  gp_Dir neckAxis = gp::DZ();

  gp_Ax2 neckAx2(neckLocation, neckAxis);

 

  Standard_Real myNeckRadius = myThickness / 4.;

  Standard_Real myNeckHeight = myHeight / 10.;

 

  BRepPrimAPI_MakeCylinder MKCylinder(neckAx2, myNeckRadius, myNeckHeight);

  TopoDS_Shape myNeck = MKCylinder.Shape();

 

  myBody = BRepAlgoAPI_Fuse(myBody, myNeck);

 

  // Body : Create a Hollowed Solid

  TopoDS_Face   faceToRemove;

  Standard_Real zMax = -1;

 

  for(TopExp_Explorer aFaceExplorer(myBody, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next()){

    TopoDS_Face aFace = TopoDS::Face(aFaceExplorer.Current());

    // Check if <aFace> is the top face of the bottle抯 neck

    Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);

    if(aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane)){

      Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface);

      gp_Pnt aPnt = aPlane->Location();

      Standard_Real aZ   = aPnt.Z();

      if(aZ > zMax){

        zMax = aZ;

        faceToRemove = aFace;

      }

    }

  }

 

  TopTools_ListOfShape facesToRemove;

  facesToRemove.Append(faceToRemove);

  myBody = BRepOffsetAPI_MakeThickSolid(myBody, facesToRemove, -myThickness / 50, 1.e-3);

  // Threading : Create Surfaces

  Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);

  Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);

 

  // Threading : Define 2D Curves

  gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.);

  gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.);

  gp_Ax2d anAx2d(aPnt, aDir);

 

  Standard_Real aMajor = 2. * M_PI;

  Standard_Real aMinor = myNeckHeight / 10;

 

  Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);

  Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4);

  Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI);

  Handle(Geom2d_TrimmedCurve) anArc2 = new Geom2d_TrimmedCurve(anEllipse2, 0, M_PI);

  gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0);

  gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI);

 

  Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2);

  // Threading : Build Edges and Wires

  TopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1);

  TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1);

  TopoDS_Edge anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2);

  TopoDS_Edge anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment, aCyl2);

  TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1);

  TopoDS_Wire threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2, anEdge2OnSurf2);

  BRepLib::BuildCurves3d(threadingWire1);

  BRepLib::BuildCurves3d(threadingWire2);

 

  // Create Threading

  BRepOffsetAPI_ThruSections aTool(Standard_True);

  aTool.AddWire(threadingWire1);

  aTool.AddWire(threadingWire2);

  aTool.CheckCompatibility(Standard_False);

 

  TopoDS_Shape myThreading = aTool.Shape();

 

  // Building the Resulting Compound

  TopoDS_Compound aRes;

  BRep_Builder aBuilder;

  aBuilder.MakeCompound (aRes);

  aBuilder.Add (aRes, myBody);

  aBuilder.Add (aRes, myThreading);

 

  Handle(AIS_Shape) ais2 = new AIS_Shape(aRes);

  GetDocument()->GetAISContext()->SetColor(ais2,Quantity_NOC_BROWN,Standard_False);

  GetDocument()->GetAISContext()->SetMaterial(ais2,Graphic3d_NOM_GOLD,Standard_False);

  GetDocument()->GetAISContext()->Display(ais2,Standard_True);

 

  return aRes;

}

添加事件响应函数,如图:

6

调用MakeBottle函数:

 

1

2

3

4

5

6

void CneedAVView::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: 在此添加消息处理程序代码和/或调用默认值

MakeBottle(400,240,160);

CView::OnLButtonDown(nFlags, point);

}

运行程序,在窗口上点击左键便会画出一个瓶子,如图:

needAV

 

 

感谢原作者的分享。

本文转载自http://www.zyh1690.org/used-in-the-mfc-opencascade-example/

参考文章:http://blog.csdn.net/Augusdi/article/details/5642368

©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页