Esempio n. 1
0
 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
Esempio n. 2
0
def poles_from_bsplinecurve_edge(occedge):
    """
    This function fetches the poles of a bspline OCCedge.
 
    Parameters
    ----------
    occedge : OCCedge
        The OCCedge to be examined. The OCCedge needs to contain a bspline curve
        
    Returns
    -------
    List of poles : pyptlist
        List of poles of the bspline curve
    """
    adaptor = BRepAdaptor_Curve(occedge)
    adaptor_handle = BRepAdaptor_HCurve(adaptor)
    handle_bspline = Handle_Geom_BSplineCurve()
    bspline = handle_bspline.DownCast(adaptor.Curve().Curve()).GetObject()

    npoles =  bspline.NbPoles()
    polelist = []
    for np in range(npoles):
        pole = bspline.Pole(np+1)
        pypole = (pole.X(), pole.Y(), pole.Z())
        polelist.append(pypole)
        
    if topods_Edge(occedge).Orientation() == TopAbs_REVERSED:
        polelist.reverse()

    return polelist
Esempio n. 3
0
def is_edge_line(occedge):
    """
    This function checks if an OCCedge contains a line.
 
    Parameters
    ----------
    occedge : OCCedge
        The OCCedge to be examined.
        
    Returns
    -------
    True or False : bool
        True or False if the edge contains a line.
    """
    adaptor = BRepAdaptor_Curve(occedge)
    
    #GeomAbs_Line 	        0
    #GeomAbs_Circle 	        1
    #GeomAbs_Ellipse         2	
    #GeomAbs_Hyperbola       3 	
    #GeomAbs_Parabola        4	
    #GeomAbs_BezierCurve     5	
    #GeomAbs_BSplineCurve    6	
    #GeomAbs_OtherCurve      7

    ctype = adaptor.GetType()
    if ctype == 0:
        return True
    else:
        return False
Esempio n. 4
0
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.GetHandle())
    tr_edge = BRepBuilderAPI_MakeEdge(bspline_handle)

    return tr_edge.Edge()
Esempio n. 5
0
def project_point_on_curve(crv: TopoDS_Edge,
                           pnt: gp_Pnt) -> Tuple[float, gp_Pnt]:
    """

    :param crv: TopoDS_Edge
    :param pnt:
    :return:
    """
    if isinstance(crv, TopoDS_Shape):
        # get the curve handle...
        adaptor = BRepAdaptor_Curve(crv)
        crv = adaptor.Curve().Curve()
        rrr = GeomAPI_ProjectPointOnCurve(pnt, crv)
        return rrr.LowerDistanceParameter(), rrr.NearestPoint()
    else:
        raise NotImplementedError('expected a TopoDS_Edge...')
Esempio n. 6
0
def is_edge_line(occedge):
    adaptor = BRepAdaptor_Curve(occedge)
    '''
    GeomAbs_Line 	        0
    GeomAbs_Circle 	        1
    GeomAbs_Ellipse         2	
    GeomAbs_Hyperbola       3 	
    GeomAbs_Parabola        4	
    GeomAbs_BezierCurve     5	
    GeomAbs_BSplineCurve    6	
    GeomAbs_OtherCurve      7
    '''
    ctype = adaptor.GetType()
    if ctype == 0:
        return True
    else:
        return False
def divide_edge_by_nr_of_points(edg, n_pts):
    '''returns a nested list of parameters and points on the edge
    at the requested interval [(param, gp_Pnt),...]
    '''
    curve_adapt = BRepAdaptor_Curve(edg)
    _lbound, _ubound = curve_adapt.FirstParameter(), curve_adapt.LastParameter(
    )

    if n_pts <= 1:
        # minimally two points or a Standard_ConstructionError is raised
        raise AssertionError("minimally 2 points required")

    npts = GCPnts_UniformAbscissa(curve_adapt, n_pts, _lbound, _ubound)
    if npts.IsDone():
        tmp = []
        for i in range(1, npts.NbPoints() + 1):
            param = npts.Parameter(i)
            pnt = curve_adapt.Value(param)
            tmp.append((param, pnt))
        return tmp
Esempio n. 8
0
def poles_from_bsplinecurve_edge(occedge):
    '''
    occedge: the edge to be measured
    type: occedge
    '''
    #occutil_edge = edge.Edge(occedge)
    adaptor = BRepAdaptor_Curve(occedge)
    adaptor_handle = BRepAdaptor_HCurve(adaptor)
    handle_bspline = Handle_Geom_BSplineCurve()
    bspline = handle_bspline.DownCast(adaptor.Curve().Curve()).GetObject()

    npoles = bspline.NbPoles()
    polelist = []
    for np in range(npoles):
        pole = bspline.Pole(np + 1)
        pypole = (pole.X(), pole.Y(), pole.Z())
        polelist.append(pypole)

    if topods_Edge(occedge).Orientation() == TopAbs_REVERSED:
        polelist.reverse()

    return polelist
Esempio n. 9
0
def trimedge(lbound, ubound, occedge):
    '''
    lbound: lower bound of the parameterise edge
    type: float
    
    ubound: upper bound of the parameterise edge
    type: float
    
    occedge: the edge to be trimmed
    type: occedge
    '''
    adaptor = BRepAdaptor_Curve(occedge)
    #print adaptor.Trim(adaptor.FirstParameter(), adaptor.LastParameter(), adaptor.Tolerance()).GetObject().NbPoles().Curve()
    tr = Geom_TrimmedCurve(adaptor.Curve().Curve(), lbound, ubound)
    tr.SetTrim(lbound, ubound)
    bspline_handle = geomconvert_CurveToBSplineCurve(tr.GetHandle())
    #print tr.GetHandle()
    tr_edge = BRepBuilderAPI_MakeEdge(bspline_handle)
    #occutil_edge = edge.Edge(occedge)
    #trimedge = occutil_edge.trim(lbound, ubound)

    return tr_edge.Edge()
def Uniform_Points_on_Curve(curve, NPoints):
    """Returns a list of uniformly spaced points on a curve
    Parameters
    ----------
    crv : OCC.Geom curve type
    NPoints : int
        number of sampling points along the curve"""
    try:
        adapt = GeomAdaptor_Curve(curve)
    except:
        # Allow the algorithm to deal with TopoDS_Edge and Wire shapes:
        adapt = BRepAdaptor_Curve(curve)
    absc = GCPnts_UniformAbscissa(adapt, NPoints)
    return [adapt.Value(absc.Parameter(i)) for i in range(1, NPoints + 1)]
Esempio n. 11
0
def to_adaptor_3d(curveType):
    '''
    abstract curve like type into an adaptor3d
    @param curveType:
    '''
    if isinstance(curveType, TopoDS_Wire):
        return BRepAdaptor_CompCurve(curveType)
    elif isinstance(curveType, TopoDS_Edge):
        return BRepAdaptor_Curve(curveType)
    elif issubclass(curveType.__class__, Geom_Curve):
        return GeomAdaptor_Curve(curveType.GetHandle())
    elif hasattr(curveType, 'GetObject'):
        _crv = curveType.GetObject()
        if issubclass(_crv.__class__, Geom_Curve):
            return GeomAdaptor_Curve(curveType)
    else:
        raise TypeError(
            'allowed types are Wire, Edge or a subclass of Geom_Curve\nGot a %s'
            % (curveType.__class__))
Esempio n. 12
0
class Edge(KbeObject, TopoDS_Edge):
    '''
    '''
    def __init__(self, edge):
        '''
        '''
        assert isinstance(
            edge, TopoDS_Edge), 'need a TopoDS_Edge, got a %s' % edge.__class__
        KbeObject.__init__(self, 'edge')
        TopoDS_Edge.__init__(self, edge)

        # 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)
        #self.graphic   = GraphicCurve(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):
        if self._curve_handle is not None and not self.is_dirty:
            pass
        else:
            self.curve
        return self._curve_handle

    @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:
            pass
        else:
            self.adaptor
        return self._adaptor.Curve().Curve()

    @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()

    def project(self, other):
        '''projects self with a point, curve, edge, face, solid
        method wraps dealing with the various topologies
        '''
        raise NotImplementedError

#===============================================================================
#    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 lenght 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, periodic=False):
        '''
        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.brep, 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,
                          check_seam=True):
        '''returns the parameter if there is a parameter
        on the curve with a distance length from u
        raises OutOfBoundary if no such parameter exists
        '''
        ccc = GCPnts_AbscissaPoint(self.adaptor, distance, close_parameter,
                                   estimate_parameter, 1e-5)
        with assert_isdone(ccc, 'couldnt compute distance on curve'):
            return ccc.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:
            #import ipdb; ipdb.set_trace()
            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

    @property
    def color(self, indx=None):
        '''sets or gets the color of self, possible also on a specified controlPoint index
        '''
        raise NotImplementedError

    @property
    def weight(self, indx):
        '''descriptor sets or gets the weight of a control point at the index
        '''
        #TODO self.curve has to be generalized to a bspline for this...
        raise NotImplementedError

    def control_pt_coord(self, indx):
        #TODO confused; vertices != control points
        '''descriptor setting or getting the coordinate of a control point at indx'''
        raise NotImplementedError

    def greville_points(self):
        #TODO confused; vertices != greville points
        '''descriptor setting or getting the coordinate of a control point at indx'''
        raise NotImplementedError

    def control_point(self, indx, pt=None):
        '''gets or sets the coordinate of the control point
        '''
        raise NotImplementedError

    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):
        # TODO: should return Vertex, not TopoDS_Vertex
        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 point_to_parameter(self, coord):
        '''returns the parameters / pnt on edge at world coordinate `coord`
        '''
        return self.project_pnt_on_edge(coord)

    def transform(self, transform):
        '''affine transform
        '''
        raise NotImplementedError

    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_to_another_curve(self, other):
        '''returns continuity between self and another curve
        '''
        return self._lprops_curve_tool(self.curve)

    def continuity_from_faces(self, f1, f2):
        return BRep_Tool_Continuity(self, f1, f2)

#===============================================================================
#    Curve.loop
#===============================================================================

    def iter_control_points(self):
        '''iterator over the control points
        '''
        raise NotImplementedError

    def iter_weights(self):
        '''iterator over the weights
        '''
        raise NotImplementedError

#===============================================================================
#    Curve.
#===============================================================================

    def is_trimmed(self):
        '''checks if curve is trimmed

        check if the underlying geom type is trimmed

        '''
        raise NotImplementedError

    def is_line(self, tolerance=None):
        '''checks if the curve is planar within a tolerance
        '''
        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)

    def on_edge(self, edge):
        '''checks if the curve lies on an edge or a border
        '''
        raise NotImplementedError

#===============================================================================
#    Curve.graphic
#===============================================================================

    def show(self, poles=False, vertices=False, knots=False):
        '''
        poles, knots, should render all slightly different.
        here's how...

        http://www.opencascade.org/org/forum/thread_1125/
        '''
        show = super(Edge, self).show()

    def update(self, context):
        '''updates the graphic presentation when called
        '''
        raise NotImplementedError

    @property
    def color(self, *rgb):
        '''color descriptor for the curve
        '''
        raise NotImplementedError
Esempio n. 13
0
 def _geomAdaptor(self):
     """
     Return the underlying geometry
     """
     return BRepAdaptor_Curve(self.wrapped)
Esempio n. 14
0
def EdgeOnSurface(edge, section_plane, lim_coord1, lim_coord2, XYZ):

    section_face = BRepBuilderAPI_MakeFace(section_plane, lim_coord1[0],
                                           lim_coord1[1], lim_coord2[0],
                                           lim_coord2[1]).Face()
    curve_handle, first, last = BRep_Tool.CurveOnSurface(edge, section_face)

    plane = Geom_Plane(section_plane)
    edge_on_surface = BRepBuilderAPI_MakeEdge(curve_handle, plane.GetHandle(),
                                              first, last).Edge()
    curve_adaptor = BRepAdaptor_Curve(edge_on_surface)

    if curve_adaptor.GetType() == GeomAbs_Line:

        v = list(Topo(edge_on_surface).vertices())
        v1 = BRep_Tool.Pnt(v[0]).X(), BRep_Tool.Pnt(v[0]).Y(), BRep_Tool.Pnt(
            v[0]).Z()
        v2 = BRep_Tool.Pnt(v[-1]).X(), BRep_Tool.Pnt(v[-1]).Y(), BRep_Tool.Pnt(
            v[-1]).Z()

        obj = Line3D(v1, v2)

    elif curve_adaptor.GetType() == GeomAbs_Circle:
        v = list(Topo(edge_on_surface).vertices())
        v1 = BRep_Tool.Pnt(v[0]).X(), BRep_Tool.Pnt(v[0]).Y(), BRep_Tool.Pnt(
            v[0]).Z()
        v2 = BRep_Tool.Pnt(v[-1]).X(), BRep_Tool.Pnt(v[-1]).Y(), BRep_Tool.Pnt(
            v[-1]).Z()

        start = [v1[i] for i in range(len(XYZ)) if XYZ[i]]
        end = [v2[i] for i in range(len(XYZ)) if XYZ[i]]

        circle = curve_adaptor.Circle()
        center = []
        for i in range(len(XYZ)):
            if XYZ[i] and i == 0:
                center.append(circle.Location().X())
            elif XYZ[i] and i == 1:
                center.append(circle.Location().Y())
            elif XYZ[i] and i == 2:
                center.append(circle.Location().Z())
            else:
                center.append(0.5 * (v1[i] + v2[i]))
        radius = circle.Radius()

        vec_start = (start[0] - center[0], start[1] - center[1])
        vec_end = (end[0] - center[0], end[1] - center[1])

        t1 = angle360(vec_start)
        t2 = angle360(vec_end)

        if not XYZ[0]:
            axis = circle.Axis().Direction().X()
        elif not XYZ[1]:
            axis = circle.Axis().Direction().Y()
        elif not XYZ[2]:
            axis = circle.Axis().Direction().Z()

        if axis < 0:
            t1, t2 = t2, t1

        obj = Arc3D(v1, v2, t1, t2, center, radius)

    elif curve_adaptor.GetType() == GeomAbs_BSplineCurve:

        bspline = curve_adaptor.BSpline().GetObject()
        degree = bspline.Degree()
        knots = [
            bspline.Knot(index) for index in range(1,
                                                   bspline.NbKnots() + 1)
        ]
        mults = [
            bspline.Multiplicity(index)
            for index in range(1,
                               bspline.NbKnots() + 1)
        ]
        poles = [(bspline.Pole(index).X(), bspline.Pole(index).Y(),
                  bspline.Pole(index).Z())
                 for index in range(1,
                                    bspline.NbPoles() + 1)]
        periodic = bspline.IsPeriodic()
        obj = BSpline3D(poles, mults, knots, degree, periodic)

    else:

        print(curve_adaptor.GetType())
        warnings.warn("Not recognized curve!")

    return obj
Esempio n. 15
0
def adapt_edge_to_curve(edg):
    '''
    returns a curve adaptor from an edge
    @param edg: TopoDS_Edge
    '''
    return BRepAdaptor_Curve(edg)
def length_from_edge(edg):
    curve_adapt = BRepAdaptor_Curve(edg)
    length = GCPnts_AbscissaPoint().Length(curve_adapt,
                                           curve_adapt.FirstParameter(),
                                           curve_adapt.LastParameter(), 1e-6)
    return length
while exp.More():
    s = exp.Current()

    tp = Topo(s)
    for face in tp.faces():
        ifcopenshell.geom.utils.display_shape(face)
        for edge in list(Topo(face).edges()):

            curve_handle, first, last = BRep_Tool.CurveOnSurface(
                edge, section_face)

            plane = Geom_Plane(section_plane)
            e = BRepBuilderAPI_MakeEdge(curve_handle, plane.GetHandle(), first,
                                        last).Edge()
            #            handle_adaptor = Geom2dAdaptor_Curve(curve_handle)
            curve_adapt = BRepAdaptor_Curve(e)

            if curve_adapt.GetType() == GeomAbs_Line:
                v = list(Topo(e).vertices())
                y1, z1 = BRep_Tool.Pnt(v[0]).Y(), BRep_Tool.Pnt(v[0]).Z()
                y2, z2 = BRep_Tool.Pnt(v[-1]).Y(), BRep_Tool.Pnt(v[-1]).Z()

                plt.plot([y1, y2], [z1, z2], color="red", alpha=0.2)
                ifcopenshell.geom.utils.display_shape(e, clr=RED)

#                line = curve_adapt.Line()
##                r = GCPnts_AbscissaPoint(handle_adaptor)
##                length = r.Parameter()
#                curve_adapt = BRepAdaptor_Curve(e)
#                length = GCPnts_AbscissaPoint().Length(curve_adapt, curve_adapt.FirstParameter(),
#                                              curve_adapt.LastParameter(), 1e-6)
Esempio n. 18
0
class Edge(TopoDS_Edge, BaseObject):
    def __init__(self, edge, data=None):
        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', data=data)
        # 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 Shape(self):
        return list(Topo(self).edges()).pop()

    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):
        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 range(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) -> TopoDS_Vertex:
        return topexp.FirstVertex(self)

    def last_vertex(self) -> TopoDS_Vertex:
        return topexp.LastVertex(self)

    def get_common_vertex(self,
                          edge: TopoDS_Edge) -> Union[TopoDS_Vertex, None]:
        return self.common_vertex(self, edge)

    @classmethod
    def common_vertex(cls, edge1, edge2):
        vert = TopoDS_Vertex()
        if topexp.CommonVertex(edge1, edge2, vert):
            return vert
        else:
            return None

    def as_vec(self) -> gp_Vec:
        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"
            )

    @classmethod
    def create(cls, *args):
        """
        https://www.opencascade.com/doc/occt-7.3.0/refman/html/class_b_rep_builder_a_p_i___make_edge.html
        :type V1: TopoDS_Vertex &
        :type V2: TopoDS_Vertex &

        :type P1: gp_Pnt
        :type P2: gp_Pnt

        :type L: gp_Lin
        :type p1: (Optional) float or gp_Pnt or TopoDS_Vertex
        :type p2: (Optional) float or gp_Pnt or TopoDS_Vertex

        :type L: gp_Circ
        :type p1: (Optional) float or gp_Pnt or TopoDS_Vertex
        :type p2: (Optional) float or gp_Pnt or TopoDS_Vertex

        :type L: gp_Elips
        :type p1: (Optional) float or gp_Pnt or TopoDS_Vertex
        :type p2: (Optional) float or gp_Pnt or TopoDS_Vertex

        :type L: gp_Hypr
        :type p1: (Optional) float or gp_Pnt or TopoDS_Vertex
        :type p2: (Optional) float or gp_Pnt or TopoDS_Vertex

        :type L: gp_Parab
        :type p1: (Optional) float or gp_Pnt or TopoDS_Vertex
        :type p2: (Optional) float or gp_Pnt or TopoDS_Vertex

        :type L: Handle_Geom_Curve &
        :type p1: (Optional) float or gp_Pnt or TopoDS_Vertex
        :type p2: (Optional) float or gp_Pnt or TopoDS_Vertex

        :type L: Handle_Geom_Curve &
        :type p1: (Optional) gp_Pnt or TopoDS_Vertex
        :type p2: (Optional) gp_Pnt or TopoDS_Vertex
        :type p1: (Optional) float
        :type p2: (Optional) float

        :type L: Handle_Geom2d_Curve &
        :type S: Handle_Geom_Surface &
        :type p1: (Optional) float or gp_Pnt or TopoDS_Vertex
        :type p2: (Optional) float or gp_Pnt or TopoDS_Vertex

        :type L: Handle_Geom2d_Curve
        :type S: Handle_Geom_Surface &
        :type P1: (Optional) gp_Pnt or TopoDS_Vertex
        :type P2: (Optional) gp_Pnt or TopoDS_Vertex
        :type p1: (Optional) float
        :type p2: (Optional) float

        * The general method to directly create an edge is to give -
        a 3D curve C as the support (geometric domain) of the edge, -
        two vertices V1 and V2 to limit the curve
        (definition of the restriction of the edge),
        and - two real values p1 and p2 which are the
        parameters for the vertices V1 and V2 on the curve.
        The curve may be defined as a 2d curve in the parametric
        space of a surface: a pcurve.
        The surface on which the edge is built is then kept at the level
        of the edge.
        The default tolerance will be associated with this edge.
        """
        edge = BRepBuilderAPI_MakeEdge(*args)
        with assert_isdone(edge, 'failed to produce edge'):
            result = edge.Edge()
            edge.Delete()
            return result

    # ===========================================================================
    #  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)

    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 'self' lies on a surface or a face
        """
        shp = ShapeAnalysis_Edge()
        return shp.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()