def test_curve_adaptor(self): # related to issue #1057 https://github.com/tpaviot/pythonocc-core/issues/1057 p1 = gp_Pnt(5, -5, 0) p2 = gp_Pnt(5, 5, 0) ed1 = BRepBuilderAPI_MakeEdge(p2, p1).Edge() c1 = BRepAdaptor_Curve(ed1) self.assertTrue(isinstance(c1.Curve(), GeomAdaptor_Curve)) # should pass on all platforms self.assertTrue(isinstance(c1.Curve().Curve(), Geom_Curve)) c2 = BRepAdaptor_Curve(ed1).Curve() # only works on linux if sys.platform == "linux": self.assertTrue(isinstance(c2.Curve(), Geom_Curve)) self.assertTrue( isinstance(BRepAdaptor_Curve(ed1).Curve().Curve(), Geom_Curve))
def project_mesh_to_cad_2d(mesh, cad): from OCC.Core.BRepAdaptor import BRepAdaptor_Curve from OCC.Core.gp import gp_Pnt from OCC.Core.GeomAPI import 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))) for id in ids} for (id, edge) in zip(ids, cad.edges()): 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]) curve = BRepAdaptor_Curve(edge) for node in owned_nodes: pt = gp_Pnt(*coorddata[node, :], 0) proj = GeomAPI_ProjectPointOnCurve(pt, curve.Curve().Curve()) if proj.NbPoints() > 0: projpt = proj.NearestPoint() coorddata[node, :] = projpt.Coord()[0:2] else: warnings.warn("Projection of point %s onto curve failed" % coorddata[node, :])
def trimedge(lbound, ubound, occedge): """ This function trims the OCCedge according to the specified lower and upper bound. Parameters ---------- lbound : float The lower bound of the OCCedge. ubound : float The upper bound of the OCCedge. occedge : OCCedge The edge to be trimmed. Returns ------- trimmed edge : OCCedge The trimmed OCCedge. """ adaptor = BRepAdaptor_Curve(occedge) tr = Geom_TrimmedCurve(adaptor.Curve().Curve(), lbound, ubound) tr.SetTrim(lbound, ubound) bspline_handle = geomconvert_CurveToBSplineCurve(tr.BasisCurve()) tr_edge = BRepBuilderAPI_MakeEdge(bspline_handle) return tr_edge.Edge()
def other(): for (id, edge) in zip(ids, cad.edges()): 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]) curve = BRepAdaptor_Curve(edge) for node in owned_nodes: pt = gp_Pnt(*coorddata[node, :], 0) proj = GeomAPI_ProjectPointOnCurve(pt, curve.Curve().Curve()) if proj.NbPoints() > 0: projpt = proj.NearestPoint() coorddata[node, :] = projpt.Coord()[0:2] else: warnings.warn("Projection of point %s onto curve failed" % coorddata[node, :])
def project_mesh_to_cad_2d(mesh, cad): from OCC.Core.BRepAdaptor import BRepAdaptor_Curve from OCC.Core.gp import gp_Pnt from OCC.Core.GeomAPI import 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_ in ids: for node in boundary_nodes[id_]: #print(node) coords = coorddata[node, :] best_coords = coords dist_old = np.inf for edge in cad.edges(): curve = BRepAdaptor_Curve(edge) pt = gp_Pnt(*coorddata[node, :], 0) proj = GeomAPI_ProjectPointOnCurve(pt, curve.Curve().Curve()) if proj.NbPoints() > 0: projpt = proj.NearestPoint() projected_coords = np.array(projpt.Coord()[0:2]) dist = np.linalg.norm(coords - projected_coords) if dist_old > dist: best_coords = projected_coords dist_old = dist #print(coords, projected_coords, np.linalg.norm(coords-projected_coords)) #print(distances) coorddata[node, :] = best_coords return
def describe_edge(self, edge): curve_adaptor = BRepAdaptor_Curve(edge) first = curve_adaptor.FirstParameter() last = curve_adaptor.LastParameter() geom_curve = curve_adaptor.Curve() if (geom_curve.GetType() == GeomAbs_Line): return "Is line" elif (geom_curve.GetType() == GeomAbs_Circle): return "Is circle" elif (geom_curve.GetType() == GeomAbs_Ellipse): return "Is ellipse" elif (geom_curve.GetType() == GeomAbs_Hyperbola): return "Is hyperbola" elif (geom_curve.GetType() == GeomAbs_Parabola): return "Is parabola" elif (geom_curve.GetType() == GeomAbs_BezierCurve): return "Is bezier" elif (geom_curve.GetType() == GeomAbs_BSplineCurve): return "Is bspline" elif (geom_curve.GetType() == GeomAbs_OffsetCurve): return "Is offset" elif (geom_curve.GetType() == GeomAbs_OtherCurve): return "Is other"
class Edge(TopoDS_Edge, BaseObject): def __init__(self, edge): assert isinstance(edge, TopoDS_Edge), 'need a TopoDS_Edge, got a %s' % edge.__class__ assert not edge.IsNull() super(Edge, self).__init__() BaseObject.__init__(self, 'edge') # we need to copy the base shape using the following three # lines assert self.IsNull() self.TShape(edge.TShape()) self.Location(edge.Location()) self.Orientation(edge.Orientation()) assert not self.IsNull() # tracking state self._local_properties_init = False self._curvature_init = False self._geometry_lookup_init = False self._curve_handle = None self._curve = None self._adaptor = None self._adaptor_handle = None # instantiating cooperative classes # cooperative classes are distinct through CamelCaps from # normal method -> pep8 self.DiffGeom = DiffGeomCurve(self) self.Intersect = IntersectCurve(self) self.Construct = ConstructFromCurve(self) # GeomLProp object self._curvature = None def is_closed(self): return self.adaptor.IsClosed() def is_periodic(self): return self.adaptor.IsPeriodic() def is_rational(self): return self.adaptor.IsRational() def continuity(self): return self.adaptor.Continuity def degree(self): if 'line' in self.type: return 1 elif 'curve' in self.type: return self.adaptor.Degree() else: # hyperbola, parabola, circle return 2 def nb_knots(self): return self.adaptor.NbKnots() def nb_poles(self): return self.adaptor.NbPoles() @property def curve(self): if self._curve is not None and not self.is_dirty: pass else: self._curve_handle = BRep_Tool().Curve(self)[0] self._curve = self._curve_handle#.GetObject() return self._curve @property def curve_handle(self): self.curve if self._curve_handle is not None and not self.is_dirty: return self._curve_handle else: return None @property def adaptor(self): if self._adaptor is not None and not self.is_dirty: pass else: self._adaptor = BRepAdaptor_Curve(self) self._adaptor_handle = BRepAdaptor_HCurve(self._adaptor) return self._adaptor @property def adaptor_handle(self): if self._adaptor_handle is not None and not self.is_dirty: pass else: self.adaptor return self._adaptor_handle @property def geom_curve_handle(self): """ :return: Handle_Geom_Curve adapted from `self` """ if self._adaptor_handle is not None and not self.is_dirty: return self._adaptor.Curve().Curve() else: return None @property def type(self): return geom_lut[self.adaptor.Curve().GetType()] def pcurve(self, face): """ computes the 2d parametric spline that lies on the surface of the face :return: Geom2d_Curve, u, v """ crv, u, v = BRep_Tool().CurveOnSurface(self, face) return crv.GetObject(), u, v def _local_properties(self): self._lprops_curve_tool = GeomLProp_CurveTool() self._local_properties_init = True def domain(self): '''returns the u,v domain of the curve''' return self.adaptor.FirstParameter(), self.adaptor.LastParameter() #=========================================================================== # Curve.GlobalProperties #=========================================================================== def length(self, lbound=None, ubound=None, tolerance=1e-5): '''returns the curve length if either lbound | ubound | both are given, than the length of the curve will be measured over that interval ''' _min, _max = self.domain() if _min < self.adaptor.FirstParameter(): raise ValueError('the lbound argument is lower than the first parameter of the curve: %s ' % (self.adaptor.FirstParameter())) if _max > self.adaptor.LastParameter(): raise ValueError('the ubound argument is greater than the last parameter of the curve: %s ' % (self.adaptor.LastParameter())) lbound = _min if lbound is None else lbound ubound = _max if ubound is None else ubound return GCPnts_AbscissaPoint().Length(self.adaptor, lbound, ubound, tolerance) #=========================================================================== # Curve.modify #=========================================================================== def trim(self, lbound, ubound): ''' trim the curve @param lbound: @param ubound: ''' a, b = sorted([lbound, ubound]) tr = Geom_TrimmedCurve(self.adaptor.Curve().Curve(), a, b).GetHandle() return Edge(make_edge(tr)) def extend_by_point(self, pnt, degree=3, beginning=True): '''extends the curve to point does not extend if the degree of self.curve > 3 @param pnt: @param degree: @param beginning: ''' if self.degree > 3: raise ValueError('to extend you self.curve should be <= 3, is %s' % (self.degree)) return geomlib.ExtendCurveToPoint(self.curve, pnt, degree, beginning) #=========================================================================== # Curve. #=========================================================================== def closest(self, other): return minimum_distance(self, other) def project_vertex(self, pnt_or_vertex): ''' returns the closest orthogonal project on `pnt` on edge ''' if isinstance(pnt_or_vertex, TopoDS_Vertex): pnt_or_vertex = vertex2pnt(pnt_or_vertex) poc = GeomAPI_ProjectPointOnCurve(pnt_or_vertex, self.curve_handle) return poc.LowerDistanceParameter(), poc.NearestPoint() def distance_on_curve(self, distance, close_parameter, estimate_parameter): '''returns the parameter if there is a parameter on the curve with a distance length from u raises OutOfBoundary if no such parameter exists ''' gcpa = GCPnts_AbscissaPoint(self.adaptor, distance, close_parameter, estimate_parameter, 1e-5) with assert_isdone(gcpa, 'couldnt compute distance on curve'): return gcpa.Parameter() def mid_point(self): """ :return: the parameter at the mid point of the curve, and its corresponding gp_Pnt """ _min, _max = self.domain() _mid = (_min+_max) / 2. return _mid, self.adaptor.Value(_mid) def divide_by_number_of_points(self, n_pts, lbound=None, ubound=None): '''returns a nested list of parameters and points on the edge at the requested interval [(param, gp_Pnt),...] ''' _lbound, _ubound = self.domain() if lbound: _lbound = lbound elif ubound: _ubound = ubound # minimally two points or a Standard_ConstructionError is raised if n_pts <= 1: n_pts = 2 try: npts = GCPnts_UniformAbscissa(self.adaptor, n_pts, _lbound, _ubound) except: print("Warning : GCPnts_UniformAbscissa failed") if npts.IsDone(): tmp = [] for i in xrange(1, npts.NbPoints()+1): param = npts.Parameter(i) pnt = self.adaptor.Value(param) tmp.append((param, pnt)) return tmp else: return None def __eq__(self, other): if hasattr(other, 'topo'): return self.IsEqual(other) else: return self.IsEqual(other) def __ne__(self, other): return not self.__eq__(other) def first_vertex(self): return topexp.FirstVertex(self) def last_vertex(self): return topexp.LastVertex(self) def common_vertex(self, edge): vert = TopoDS_Vertex() if topexp.CommonVertex(self, edge, vert): return vert else: return False def as_vec(self): if self.is_line(): first, last = map(vertex2pnt, [self.first_vertex(), self.last_vertex()]) return gp_Vec(first, last) else: raise ValueError("edge is not a line, hence no meaningful vector can be returned") #=========================================================================== # Curve. #=========================================================================== def parameter_to_point(self, u): '''returns the coordinate at parameter u ''' return self.adaptor.Value(u) def fix_continuity(self, continuity): """ splits an edge to achieve a level of continuity :param continuity: GeomAbs_C* """ return fix_continuity(self, continuity) def continuity_from_faces(self, f1, f2): return BRep_Tool_Continuity(self, f1, f2) #=========================================================================== # Curve. #=========================================================================== def is_line(self): '''checks if the curve is planar ''' if self.nb_knots() == 2 and self.nb_poles() == 2: return True else: return False def is_seam(self, face): """ :return: True if the edge has two pcurves on one surface ( in the case of a sphere for example... ) """ sae = ShapeAnalysis_Edge() return sae.IsSeam(self, face) def is_edge_on_face(self, face): '''checks whether curve lies on a surface or a face ''' return ShapeAnalysis_Edge().HasPCurve(self, face) #=========================================================================== # Curve.graphic #=========================================================================== def show(self): ''' poles, knots, should render all slightly different. here's how... http://www.opencascade.org/org/forum/thread_1125/ ''' super(Edge, self).show()
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()
def Write(self, path): from bcad.binterpreter.scl_context import SCLProjection p = SCLProjection(None) p.hlr_project(self.shapes) shapes = [] for c in p.children: if c.shape != None: dump_topology_to_string(c.shape.get_shape()) shapes.append(c.shape.get_shape()) lines = [] for s in shapes: lines.extend(self.collect_dumpable_shapes(s)) #debug("Lines: %s"%(str(lines),)) ctr = 0 for l in lines: #debug ("l: %s"%(str(l),)) if len(l)>1: s = l[0][:2] for p in l[1:]: e = p[:2] self.msp.add_line(s, e) s = e # e = l[1][:2] # self.doc.saveas(path) return for s in shapes: exp = TopExp_Explorer() exp.Init(s, TopAbs_EDGE) while exp.More(): edge = exp.Value() if not is_edge(edge): warning("Is not an edge.") if exp.Value().IsNull(): warning("TopoDS_Edge is null") curve_adaptor = BRepAdaptor_Curve(edge) first = curve_adaptor.FirstParameter() last = curve_adaptor.LastParameter() geom_curve = curve_adaptor.Curve() #edges.append(exp.Current()) # first = topexp.FirstVertex(exp.Value()) # last = topexp.LastVertex(exp.Value()) # # Take geometrical information from vertices. # pnt_first = BRep_Tool.Pnt(first) # pnt_last = BRep_Tool.Pnt(last) # a, b = BRep_Tool.Curve(exp.Value()) exp.Next() if (geom_curve.GetType() == GeomAbs_Line): debug("Is line") elif (geom_curve.GetType() == GeomAbs_Circle): debug("Is circle") elif (geom_curve.GetType() == GeomAbs_Ellipse): debug("Is ellipse") elif (geom_curve.GetType() == GeomAbs_Hyperbola): debug("Is hyperbola") elif (geom_curve.GetType() == GeomAbs_Parabola): debug("Is parabola") elif (geom_curve.GetType() == GeomAbs_BezierCurve): debug("Is bezier") elif (geom_curve.GetType() == GeomAbs_BSplineCurve): debug("Is bspline") elif (geom_curve.GetType() == GeomAbs_OffsetCurve): debug("Is offset") elif (geom_curve.GetType() == GeomAbs_OtherCurve): #debug("Is other") continue #self.msp.add_line() pts = discretize_edge(edge) debug("Curve[%i]: %s / %s"%(ctr, str(geom_curve.GetType()),str(edge))) ctr+=1