目录:
一、OpenCasCade开发环境搭建
二、创建一个MFC应用程序
三、在MFC工程中添加代码
四、画个瓶子
一、OpenCasCade开发环境搭建
参见《OpenCasCade开发环境搭建》,这篇文章最后运行示例前所做的工作为以后开发OpenCasCade工程铺平了路,无需额外的配置,只需在新建的工程中加你的代码即可。
二、创建一个MFC应用程序
到此步,点击完成即可(注意我的配置选项)。
三、在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); } |
如图:
此时编译会提示如下错误:
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 灰灰的窗口了,如图:
四、画个瓶子
弄好这些,我们便可以使用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; } |
添加事件响应函数,如图:
调用MakeBottle函数:
1 2 3 4 5 6 | void CneedAVView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 MakeBottle(400,240,160); CView::OnLButtonDown(nFlags, point); } |
运行程序,在窗口上点击左键便会画出一个瓶子,如图:
感谢原作者的分享。
本文转载自http://www.zyh1690.org/used-in-the-mfc-opencascade-example/
参考文章:http://blog.csdn.net/Augusdi/article/details/5642368