/src/examples/Level1/Geometry/geomplate.py

http://pythonocc.googlecode.com/ · Python · 269 lines · 150 code · 45 blank · 74 comment · 17 complexity · ef3946c5bf858efe22c29ae8e72516dd MD5 · raw file

  1. #!/usr/bin/env python
  2. # TODO:
  3. # * need examples where the tangency to constraining faces is respected
  4. ##Copyright 2009-2011 Jelle Ferina (jelleferinga@gmail.com)
  5. ##
  6. ##This file is part of pythonOCC.
  7. ##
  8. ##pythonOCC is free software: you can redistribute it and/or modify
  9. ##it under the terms of the GNU Lesser General Public License as published by
  10. ##the Free Software Foundation, either version 3 of the License, or
  11. ##(at your option) any later version.
  12. ##
  13. ##pythonOCC is distributed in the hope that it will be useful,
  14. ##but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ##MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ##GNU Lesser General Public License for more details.
  17. ##
  18. ##You should have received a copy of the GNU Lesser General Public License
  19. ##along with pythonOCC. If not, see <http://www.gnu.org/licenses/>.
  20. import os
  21. from OCC.Utils.Construct import make_closed_polygon, make_n_sided, make_vertex, make_face, make_wire
  22. from OCC.gp import *
  23. from OCC.BRepBuilderAPI import *
  24. from OCC.Utils.Topology import WireExplorer, Topo
  25. from OCC.BRepAdaptor import *
  26. from OCC.BRep import *
  27. from OCC.ShapeAnalysis import *
  28. from OCC.GeomLProp import *
  29. import types, sys, time
  30. from OCC.Display.SimpleGui import init_display
  31. from OCC.Utils.DataExchange.IGES import IGESImporter
  32. from OCC.BRepFill import *
  33. from OCC.GeomPlate import *
  34. from OCC.GEOMAlgo import *
  35. display, start_display, add_menu, add_function_to_menu = init_display()
  36. try:
  37. from scipy import arange
  38. from scipy.optimize import fsolve
  39. except ImportError:
  40. print 'scipy not installed, will not be able to run the solve radius example'
  41. def geom_plate(event=None):
  42. display.EraseAll()
  43. p1,p2,p3,p4,p5 = gp_Pnt(0,0,0),gp_Pnt(0,10,0),gp_Pnt(0,10,10),gp_Pnt(0,0,10),gp_Pnt(5,5,5)
  44. poly = make_closed_polygon([p1,p2,p3,p4])
  45. edges = [i for i in Topo(poly).edges()]
  46. face = make_n_sided(edges, [p5])
  47. display.DisplayShape(edges)
  48. display.DisplayShape(make_vertex(p5))
  49. display.DisplayShape(face, update=True)
  50. #===============================================================================
  51. # Find a surface such that the radius at the vertex is n
  52. #===============================================================================
  53. def build_plate(polygon, points):
  54. '''
  55. build a surface from a constraining polygon(s) and point(s)
  56. @param polygon: list of polygons ( TopoDS_Shape)
  57. @param points: list of points ( gp_Pnt )
  58. '''
  59. # plate surface
  60. bpSrf = GeomPlate_BuildPlateSurface(3,15,2)
  61. # add curve constraints
  62. for poly in polygon:
  63. for edg in WireExplorer(poly).ordered_edges():
  64. c = BRepAdaptor_HCurve()
  65. c.ChangeCurve().Initialize(edg)
  66. constraint = BRepFill_CurveConstraint(c.GetHandle(), 0)
  67. bpSrf.Add(constraint.GetHandle())
  68. # add point constraint
  69. for pt in points:
  70. bpSrf.Add(GeomPlate_PointConstraint(pt, 0).GetHandle())
  71. bpSrf.Perform()
  72. maxSeg, maxDeg, critOrder = 9,8,0
  73. tol = 1e-4
  74. dmax = max([tol,10*bpSrf.G0Error()])
  75. srf = bpSrf.Surface()
  76. plate = GeomPlate_MakeApprox(srf, tol, maxSeg, maxDeg, dmax, critOrder)
  77. uMin, uMax, vMin, vMax = srf.GetObject().Bounds()
  78. return make_face(plate.Surface(), uMin, uMax, vMin, vMax)
  79. def radius_at_uv(face, u, v):
  80. '''
  81. returns the mean radius at a u,v coordinate
  82. @param face: surface input
  83. @param u,v: u,v coordinate
  84. '''
  85. h_srf = BRep_Tool().Surface(face)
  86. uv_domain = GeomLProp_SurfaceTool().Bounds(h_srf)
  87. curvature = GeomLProp_SLProps(h_srf, u, v, 1, 1e-6)
  88. try:
  89. _crv_min = 1./curvature.MinCurvature()
  90. except ZeroDivisionError:
  91. _crv_min = 0.
  92. try:
  93. _crv_max = 1./curvature.MaxCurvature()
  94. except ZeroDivisionError:
  95. _crv_max = 0.
  96. return abs((_crv_min+_crv_max)/2.)
  97. def uv_from_projected_point_on_face(face, pt):
  98. '''
  99. returns the uv coordinate from a projected point on a face
  100. '''
  101. srf = BRep_Tool().Surface(face)
  102. sas = ShapeAnalysis_Surface(srf)
  103. uv = sas.ValueOfUV(pt, 1e-2)
  104. print 'distance',sas.Value(uv).Distance(pt)
  105. return uv.Coord()
  106. class RadiusConstrainedSurface():
  107. '''
  108. returns a surface that has `radius` at `pt`
  109. '''
  110. def __init__(self, display, poly, pnt, targetRadius):
  111. self.display = display
  112. self.targetRadius = targetRadius
  113. self.poly = poly
  114. self.pnt = pnt
  115. self.plate = self.build_surface()
  116. def build_surface(self):
  117. '''
  118. builds and renders the plate
  119. '''
  120. self.plate = build_plate([self.poly], [self.pnt])
  121. self.display.EraseAll()
  122. self.display.DisplayShape(self.plate)
  123. vert = make_vertex(self.pnt)
  124. self.display.DisplayShape(vert, update=True)
  125. def radius(self, z):
  126. '''
  127. sets the height of the point constraining the plate, returns the radius at this point
  128. '''
  129. if isinstance(z, types.FloatType):
  130. self.pnt.SetX(z)
  131. else:
  132. self.pnt.SetX(float(z[0]))
  133. self.build_surface()
  134. uv = uv_from_projected_point_on_face(self.plate, self.pnt)
  135. radius = radius_at_uv(self.plate, uv[0], uv[1])
  136. print 'z:',z, 'radius:', radius
  137. self.curr_radius = radius
  138. return self.targetRadius-abs(radius)
  139. def solve(self):
  140. fsolve(self.radius, 1, maxfev=1000)
  141. return self.plate
  142. def solve_radius(event=None):
  143. display.EraseAll()
  144. p1,p2,p3,p4,p5 = gp_Pnt(0,0,0),gp_Pnt(0,10,0),gp_Pnt(0,10,10),gp_Pnt(0,0,10),gp_Pnt(5,5,5)
  145. poly = make_closed_polygon([p1,p2,p3,p4])
  146. for i in arange(0.1,3.,0.2).tolist():
  147. rcs = RadiusConstrainedSurface(display, poly, p5, i )
  148. face = rcs.solve()
  149. print 'Goal: %s radius: %s' % ( i, rcs.curr_radius )
  150. time.sleep(0.5)
  151. #===============================================================================
  152. #
  153. #===============================================================================
  154. def build_geom_plate(edges):
  155. bpSrf = GeomPlate_BuildPlateSurface(3,9,12)
  156. # add curve constraints
  157. for edg in edges:
  158. c = BRepAdaptor_HCurve()
  159. print 'edge:',edg
  160. c.ChangeCurve().Initialize(edg)
  161. constraint = BRepFill_CurveConstraint(c.GetHandle(), 0)
  162. bpSrf.Add(constraint.GetHandle())
  163. # add point constraint
  164. try:
  165. bpSrf.Perform()
  166. except RuntimeError:
  167. print 'failed to build the geom plate surface '
  168. maxSeg, maxDeg, critOrder = 9,8,0
  169. tol = 1e-4
  170. dmax = max([tol,10*bpSrf.G0Error()])
  171. srf = bpSrf.Surface()
  172. # plate = GeomPlate_MakeApprox(srf, tol, maxSeg, maxDeg, dmax, critOrder)
  173. plate = GeomPlate_MakeApprox(srf, 1e-04, 100, 9, 1e-03, 0)
  174. uMin, uMax, vMin, vMax = srf.GetObject().Bounds()
  175. face = make_face(plate.Surface(), uMin, uMax, vMin, vMax)
  176. return face
  177. def build_curve_network(event=None):
  178. '''
  179. mimic the curve network surfacing command from rhino
  180. '''
  181. print 'Importing IGES file...',
  182. pth = os.path.dirname(os.path.abspath(__file__))
  183. pth = os.path.abspath(os.path.join(pth, '../../data/IGES/curve_geom_plate.igs'))
  184. iges = IGESImporter(pth)
  185. iges.read_file()
  186. print 'done.'
  187. # GetShapes returns 36 TopoDS_Shape, while the TopoDS_Compound contains
  188. # just the 6 curves I made in rhino... hmmm...
  189. print 'Building geomplate...',
  190. topo = Topo(iges.get_compound())
  191. edges_list = list(topo.edges())
  192. face = build_geom_plate(edges_list)
  193. print 'done.'
  194. display.EraseAll()
  195. display.DisplayShape(edges_list)
  196. print 'Cutting out of edges...',
  197. # Make a wire from outer edges
  198. _edges = [edges_list[2], edges_list[3], edges_list[4], edges_list[5]]
  199. outer_wire = make_wire(_edges)
  200. ################ --- ################
  201. # for i in edges_list:
  202. # if i not in _edges:
  203. # _edges.append(i)
  204. #
  205. # import ipdb; ipdb.set_trace()
  206. # f = make_n_sided(_edges)
  207. # TODO: cut out the shape from the edges in _edges
  208. # if outer_wire:
  209. # splitter = GEOMAlgo_Splitter()
  210. # splitter.AddTool(outer_wire)
  211. # splitter.AddShape(face)
  212. # splitter.Perform()
  213. # shp = splitter.Shape()
  214. # display.DisplayShape(shp)
  215. def exit(event=None):
  216. sys.exit()
  217. if __name__ == "__main__":
  218. build_curve_network()
  219. add_menu('geom plate')
  220. add_function_to_menu('geom plate', geom_plate)
  221. add_function_to_menu('geom plate', solve_radius)
  222. add_function_to_menu('geom plate', build_curve_network)
  223. add_function_to_menu('geom plate', exit)
  224. start_display()