#!/usr/bin/env python # -*- coding:utf-8 -*- ##Copyright 2009-2015 Thomas Paviot (tpaviot@gmail.com) ## ##This file is part of pythonOCC. ## ##pythonOCC is free software: you can redistribute it and/or modify ##it under the terms of the GNU Lesser General Public License as published by ##the Free Software Foundation, either version 3 of the License, or ##(at your option) any later version. ## ##pythonOCC is distributed in the hope that it will be useful, ##but WITHOUT ANY WARRANTY; without even the implied warranty of ##MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ##GNU Lesser General Public License for more details. ## ##You should have received a copy of the GNU Lesser General Public License ##along with pythonOCC. If not, see <http://www.gnu.org/licenses/>. import math from OCC.gp import gp_Pnt, gp_OX, gp_Vec, gp_Trsf, gp_DZ, gp_Ax2, gp_Ax3, gp_Pnt2d, gp_Dir2d, gp_Ax2d from OCC.GC import GC_MakeArcOfCircle, GC_MakeSegment from OCC.GCE2d import GCE2d_MakeSegment from OCC.Geom import Geom_Plane, Geom_CylindricalSurface, Handle_Geom_Plane, Handle_Geom_Surface from OCC.Geom2d import Geom2d_Ellipse, Geom2d_TrimmedCurve, Handle_Geom2d_Ellipse, Handle_Geom2d_Curve from OCC.BRepBuilderAPI import BRepBuilderAPI_MakeEdge, BRepBuilderAPI_MakeWire, BRepBuilderAPI_MakeFace, \ BRepBuilderAPI_Transform from OCC.BRepPrimAPI import BRepPrimAPI_MakePrism, BRepPrimAPI_MakeCylinder from OCC.BRepFilletAPI import BRepFilletAPI_MakeFillet from OCC.BRepAlgoAPI import BRepAlgoAPI_Fuse from OCC.BRepOffsetAPI import BRepOffsetAPI_MakeThickSolid, BRepOffsetAPI_ThruSections from OCC.BRepLib import breplib from OCC.BRep import BRep_Tool_Surface, BRep_Builder from OCC.TopoDS import topods, TopoDS_Edge, TopoDS_Compound from OCC.TopExp import TopExp_Explorer from OCC.TopAbs import TopAbs_EDGE, TopAbs_FACE from OCC.TopTools import TopTools_ListOfShape from OCC.Display.SimpleGui import * def face_is_plane(face): """ 判断 TopoDS_Shape 是不是 plane """ hs = BRep_Tool_Surface(face) downcast_result = Handle_Geom_Plane.DownCast(hs) # 不能通过Handle_Geom_Plane转换的不是平面 return not downcast_result.IsNull() def geom_plane_from_face(aFace): """ 通过 planar surface 得到 geometric plane """ return Handle_Geom_Plane.DownCast(BRep_Tool_Surface(aFace)).GetObject() height = 70 width = 50 thickness = 30 if 1: # 准备用来创建 瓶身 的点 aPnt1 = gp_Pnt(-width / 2.0, 0, 0) aPnt2 = gp_Pnt(-width / 2.0, -thickness / 4.0, 0) aPnt3 = gp_Pnt(0, -thickness / 2.0, 0) aPnt4 = gp_Pnt(width / 2.0, -thickness / 4.0, 0) aPnt5 = gp_Pnt(width / 2.0, 0, 0) # 瓶底断面线段和圆弧 aArcOfCircle = GC_MakeArcOfCircle(aPnt2, aPnt3, aPnt4) aSegment1 = GC_MakeSegment(aPnt1, aPnt2) aSegment2 = GC_MakeSegment(aPnt4, aPnt5) # 除了下面的方法, 也可以不用上面的segment,而通过点直接创建线段edges aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value()) aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value()) aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value()) # 通过edges 创建 wire aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge(), aEdge2.Edge(), aEdge3.Edge()) # 得到X轴的便捷方式 xAxis = gp_OX() # 设置镜像轴 aTrsf = gp_Trsf() aTrsf.SetMirror(xAxis) # 应用镜像变换 aBRespTrsf = BRepBuilderAPI_Transform(aWire.Wire(), aTrsf) # 得到镜像 shape aMirroredShape = aBRespTrsf.Shape() # 通过通用shape得到 wire aMirroredWire = topods.Wire(aMirroredShape) # 组合两个wire mkWire = BRepBuilderAPI_MakeWire() mkWire.Add(aWire.Wire()) mkWire.Add(aMirroredWire) myWireProfile = mkWire.Wire() # 创建用于体拉伸 sweep 的面 myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile) # 我们把面沿Z轴拉伸到指定高度 aPrismVec = gp_Vec(0, 0, height) myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face(), aPrismVec) # 通过explorer对所有边加倒角 mkFillet = BRepFilletAPI_MakeFillet(myBody.Shape()) anEdgeExplorer = TopExp_Explorer(myBody.Shape(), TopAbs_EDGE) while anEdgeExplorer.More(): anEdge = topods.Edge(anEdgeExplorer.Current()) mkFillet.Add(thickness / 12.0, anEdge) anEdgeExplorer.Next() myBody = mkFillet # 创建瓶颈 neckLocation = gp_Pnt(0, 0, height) neckAxis = gp_DZ() neckAx2 = gp_Ax2(neckLocation, neckAxis) myNeckRadius = thickness / 4.0 myNeckHeight = height / 10.0 mkCylinder = BRepPrimAPI_MakeCylinder(neckAx2, myNeckRadius, myNeckHeight) myBody = BRepAlgoAPI_Fuse(myBody.Shape(), mkCylinder.Shape()) # 下面找到Z最高的面, 并将它移除 faceToRemove = None zMax = -1 # 遍历所有的面, 查找Z最高的面 aFaceExplorer = TopExp_Explorer(myBody.Shape(), TopAbs_FACE) while aFaceExplorer.More(): aFace = topods.Face(aFaceExplorer.Current()) if face_is_plane(aFace): aPlane = geom_plane_from_face(aFace) aPnt = aPlane.Location() aZ = aPnt.Z() if aZ > zMax: zMax = aZ faceToRemove = aFace aFaceExplorer.Next() facesToRemove = TopTools_ListOfShape() facesToRemove.Append(faceToRemove) myBody = BRepOffsetAPI_MakeThickSolid(myBody.Shape(), facesToRemove, -thickness / 50.0, 0.001) # 建立需要创建螺纹的瓶颈表面 neckAx2_Ax3 = gp_Ax3(neckLocation, gp_DZ()) aCyl1 = Geom_CylindricalSurface(neckAx2_Ax3, myNeckRadius * 0.99) aCyl2 = Geom_CylindricalSurface(neckAx2_Ax3, myNeckRadius * 1.05) # 建立创建螺纹的曲线 aPnt = gp_Pnt2d(2.0 * math.pi, myNeckHeight / 2.0) aDir = gp_Dir2d(2.0 * math.pi, myNeckHeight / 4.0) anAx2d = gp_Ax2d(aPnt, aDir) aMajor = 2.0 * math.pi aMinor = myNeckHeight / 5.0 anEllipse1 = Geom2d_Ellipse(anAx2d, aMajor, aMinor) anEllipse2 = Geom2d_Ellipse(anAx2d, aMajor, aMinor / 8.0) anArc1 = Geom2d_TrimmedCurve(Handle_Geom2d_Ellipse(anEllipse1), 0, math.pi) anArc2 = Geom2d_TrimmedCurve(Handle_Geom2d_Ellipse(anEllipse2), 0, math.pi) anEllipsePnt1 = anEllipse1.Value(0) anEllipsePnt2 = anEllipse1.Value(math.pi) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2) # 构建用于螺纹的边和环 anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(Handle_Geom2d_Curve(anArc1), Handle_Geom_Surface(aCyl1)) anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment.Value(), Handle_Geom_Surface(aCyl1)) anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(Handle_Geom2d_Curve(anArc2), Handle_Geom_Surface(aCyl2)) anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment.Value(), Handle_Geom_Surface(aCyl2)) threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1.Edge(), anEdge2OnSurf1.Edge()) threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2.Edge(), anEdge2OnSurf2.Edge()) # 计算边和环的三维表现 breplib.BuildCurves3d(threadingWire1.Shape()) breplib.BuildCurves3d(threadingWire2.Shape()) # 创建螺纹的表面 aTool = BRepOffsetAPI_ThruSections(True) aTool.AddWire(threadingWire1.Wire()) aTool.AddWire(threadingWire2.Wire()) aTool.CheckCompatibility(False) myThreading = aTool.Shape() # 构建组合结果 aRes = TopoDS_Compound() aBuilder = BRep_Builder() aBuilder.MakeCompound(aRes) aBuilder.Add(aRes, myBody.Shape()) aBuilder.Add(aRes, myThreading) display, start_display, add_menu, add_function_to_menu = init_display() display.DisplayColoredShape(aRes) start_display()