def recognize_face(a_face): """ Takes a TopoDS shape and tries to identify its nature whether it is a plane a cylinder a torus etc. if a plane, returns the normal if a cylinder, returns the radius """ surf = BRepAdaptor_Surface(a_face, True) surf_type = surf.GetType() if surf_type == GeomAbs_Plane: print("Identified Plane Geometry") # look for the properties of the plane # first get the related gp_Pln gp_pln = surf.Plane() location = gp_pln.Location() # a point of the plane normal = gp_pln.Axis().Direction() # the plane normal # then export location and normal to the console output print("--> Location (global coordinates)", location.X(), location.Y(), location.Z()) print("--> Normal (global coordinates)", normal.X(), normal.Y(), normal.Z()) elif surf_type == GeomAbs_Cylinder: print("Identified Cylinder Geometry") # look for the properties of the cylinder # first get the related gp_Cyl gp_cyl = surf.Cylinder() location = gp_cyl.Location() # a point of the axis axis = gp_cyl.Axis().Direction() # the cylinder axis # then export location and normal to the console output print("--> Location (global coordinates)", location.X(), location.Y(), location.Z()) print("--> Axis (global coordinates)", axis.X(), axis.Y(), axis.Z()) elif surf_type == GeomAbs_BSplineSurface: print("Identified BSplineSurface Geometry") gp_bsrf = surf.Surface() #degree = gp_bsrf.NbUKnots() else: # TODO there are plenty other type that can be checked # see documentation for the BRepAdaptor class # https://www.opencascade.com/doc/occt-6.9.1/refman/html/class_b_rep_adaptor___surface.html print(surf_type) print("not implemented")
def project_mesh_to_cad_3d(mesh, cad): from OCC.Core.BRepAdaptor import BRepAdaptor_Surface, BRepAdaptor_Curve from OCC.Core.gp import gp_Pnt from OCC.Core.GeomAPI import GeomAPI_ProjectPointOnSurf, GeomAPI_ProjectPointOnCurve coorddata = mesh.coordinates.dat.data ids = mesh.exterior_facets.unique_markers filt = lambda arr: arr[numpy.where(arr < mesh.coordinates.dof_dset.size)[0] ] boundary_nodes = { id: filt(mesh.coordinates.function_space().boundary_nodes( int(id), "topological")) for id in ids } for (id, face) in zip(ids, cad.faces()): owned_nodes = boundary_nodes[id] for other_id in ids: if id == other_id: continue owned_nodes = numpy.setdiff1d(owned_nodes, boundary_nodes[other_id]) surf = BRepAdaptor_Surface(face) for node in owned_nodes: pt = gp_Pnt(*coorddata[node, :]) proj = GeomAPI_ProjectPointOnSurf(pt, surf.Surface().Surface()) if proj.NbPoints() > 0: projpt = proj.NearestPoint() coorddata[node, :] = projpt.Coord() else: warnings.warn("Projection of point %s onto face %d failed" % (coorddata[node, :], id)) edges = set(cad.edges_from_face(face)) for (other_id, other_face) in zip(ids, cad.faces()): if other_id <= id: continue intersecting_nodes = numpy.intersect1d(boundary_nodes[id], boundary_nodes[other_id]) if len(intersecting_nodes) == 0: continue other_edges = set(cad.edges_from_face(other_face)) intersecting_edges = [] for edge in edges: s = str( edge ) # FIXME: is there a more elegant way to get the OCC id? for other_edge in other_edges: other_s = str(other_edge) if s == other_s: intersecting_edges.append(edge) if len(intersecting_edges) == 0: warnings.warn( "face: %s other_face: %s intersecting_edges: %s" % (face, other_face, intersecting_edges)) warnings.warn( "Warning: no intersecting edges in CAD, even though vertices on both faces?" ) continue for node in intersecting_nodes: pt = gp_Pnt(*coorddata[node, :]) projections = [] for edge in intersecting_edges: curve = BRepAdaptor_Curve(edge) proj = GeomAPI_ProjectPointOnCurve(pt, curve.Curve().Curve()) if proj.NbPoints() > 0: projpt = proj.NearestPoint() sqdist = projpt.SquareDistance(pt) projections.append((projpt, sqdist)) else: warnings.warn( "Projection of point %s onto curve failed" % coorddata[node, :]) (projpt, sqdist) = min(projections, key=lambda x: x[1]) coorddata[node, :] = projpt.Coord()