def compute_minimal_distance_between_cubes():
    """ compute the minimal distance between 2 cubes

    the line between the 2 points is rendered in cyan

    """
    b1 = BRepPrimAPI_MakeBox(gp_Pnt(100, 0, 0), 10., 10., 10.).Shape()
    b2 = BRepPrimAPI_MakeBox(gp_Pnt(45, 45, 45), 10., 10., 10.).Shape()
    display.DisplayShape([b1, b2])

    dss = BRepExtrema_DistShapeShape()
    dss.LoadS1(b1)
    dss.LoadS2(b2)
    dss.Perform()

    assert dss.IsDone()

    edg = make_edge(dss.PointOnShape1(1), dss.PointOnShape2(1))
    display.DisplayColoredShape([edg], color="CYAN")
Exemplo n.º 2
0
class DistanceShapeToShape(object):
    """
    Calculate minimum distance between two shapes. If geometry is provided
    it will be converted to a shape.

    :param shape1: The first shape or geometry.
    :type shape1: afem.topology.entities.Shape or
        afem.geometry.entities.Geometry
    :param shape2: The second or geometry.
    :type shape2: afem.topology.entities.Shape or
        afem.geometry.entities.Geometry

    Usage:

    >>> from afem.topology import *
    >>> v1 = VertexByPoint((0., 0., 0.)).vertex
    >>> v2 = VertexByPoint((10., 0., 0.)).vertex
    >>> tool = DistanceShapeToShape(v1, v2)
    >>> tool.nsol
    1
    >>> tool.dmin
    10.0
    """
    def __init__(self, shape1, shape2, deflection=1.0e-7):
        shape1 = Shape.to_shape(shape1)
        shape2 = Shape.to_shape(shape2)
        self._tool = BRepExtrema_DistShapeShape(shape1.object, shape2.object,
                                                deflection,
                                                Extrema_ExtFlag_MIN)

    @property
    def is_done(self):
        """
        :return: *True* if algorithm is done, *False* if not.
        :rtype: bool
        """
        return self._tool.IsDone()

    @property
    def nsol(self):
        """
        :return: The number of solutions satisfying the minimum distance.
        :rtype:
        """
        return self._tool.NbSolution()

    @property
    def dmin(self):
        """
        :return: The minimum distance.
        :rtype: float
        """
        return self._tool.Value()

    @property
    def inner_solution(self):
        """
        :return: *True* if one of the shapes is a solid and the other is
            completely or partially inside the solid.
        :rtype: bool
        """
        return self._tool.InnerSolution()

    def point_on_shape1(self, n=1):
        """
        The point for the *n-th* solution on the first shape.

        :param int n: The index.

        :return: The point.
        :rtype: afem.geometry.entities.Point
        """
        gp_pnt = self._tool.PointOnShape1(n)
        return Point(gp_pnt.X(), gp_pnt.Y(), gp_pnt.Z())

    def point_on_shape2(self, n=1):
        """
        The point for the *n-th* solution on the second shape.

        :param int n: The index.

        :return: The point.
        :rtype: afem.geometry.entities.Point
        """
        gp_pnt = self._tool.PointOnShape2(n)
        return Point(gp_pnt.X(), gp_pnt.Y(), gp_pnt.Z())

    def support_type_shape1(self, n=1):
        """
        The type of support for the *n-th* solution on the first shape.

        :param int n: The index.

        :return: The support type.
        :rtype: OCCT.BRepExtrema.BRepExtrema_SupportType
        """
        return self._tool.SupportTypeShape1(n)

    def is_vertex_shape1(self, n=1):
        """
        Check if support type is a vertex for the first shape.

        :param int n: The index.

        :return: *True* if a vertex, *False* otherwise.
        :rtype: bool
        """
        return self.support_type_shape1(n) == BRepExtrema_IsVertex

    def is_on_edge_shape1(self, n=1):
        """
        Check if support type is on an edge for the first shape.

        :param int n: The index.

        :return: *True* if on an edge, *False* otherwise.
        :rtype: bool
        """
        return self.support_type_shape1(n) == BRepExtrema_IsOnEdge

    def is_in_face_shape1(self, n=1):
        """
        Check if support type is in a face for the first shape.

        :param int n: The index.

        :return: *True* if in a face, *False* otherwise.
        :rtype: bool
        """
        return self.support_type_shape1(n) == BRepExtrema_IsInFace

    def support_type_shape2(self, n=1):
        """
        The type of support for the *n-th* solution on the second shape.

        :param int n: The index.

        :return: The support type.
        :rtype: OCCT.BRepExtrema.BRepExtrema_SupportType
        """
        return self._tool.SupportTypeShape2(n)

    def is_vertex_shape2(self, n=1):
        """
        Check if support type is a vertex for the second shape.

        :param int n: The index.

        :return: *True* if a vertex, *False* otherwise.
        :rtype: bool
        """
        return self.support_type_shape2(n) == BRepExtrema_IsVertex

    def is_on_edge_shape2(self, n=1):
        """
        Check if support type is on an edge for the second shape.

        :param int n: The index.

        :return: *True* if on an edge, *False* otherwise.
        :rtype: bool
        """
        return self.support_type_shape2(n) == BRepExtrema_IsOnEdge

    def is_in_face_shape2(self, n=1):
        """
        Check if support type is in a face for the second shape.

        :param int n: The index.

        :return: *True* if in a face, *False* otherwise.
        :rtype: bool
        """
        return self.support_type_shape2(n) == BRepExtrema_IsInFace

    def support_on_shape1(self, n=1):
        """
        Get the shape where the *n-th* solution is on the first shape.

        :param int n: The index.

        :return: The support shape.
        :rtype: afem.topology.entities.Shape
        """
        return Shape.wrap(self._tool.SupportOnShape1(n))

    def support_on_shape2(self, n=1):
        """
        Get the shape where the *n-th* solution is on the second shape.

        :param int n: The index.

        :return: The support shape.
        :rtype: afem.topology.entities.Shape
        """
        return Shape.wrap(self._tool.SupportOnShape2(n))

    def par_on_edge_shape1(self, n=1):
        """
        Get the parameter of the *n-th* solution if it is on an edge of the
        first shape.

        :param int n: The index.

        :return: The parameter.
        :rtype: float
        """
        return self._tool.ParOnEdgeS1(n, 0.)

    def par_on_edge_shape2(self, n=1):
        """
        Get the parameter of the *n-th* solution if it is on an edge of the
        second shape.

        :param int n: The index.

        :return: The parameter.
        :rtype: float
        """
        return self._tool.ParOnEdgeS2(n, 0.)

    def par_on_face_shape1(self, n=1):
        """
        Get the parameters of the *n-th* solution if it is in a face of the
        first shape.

        :param int n: The index.

        :return: The parameters.
        :rtype: tuple(float, float)
        """
        return self._tool.ParOnFaceS1(n, 0., 0.)

    def par_on_face_shape2(self, n=1):
        """
        Get the parameters of the *n-th* solution if it is in a face of the
        second shape.

        :param int n: The index.

        :return: The parameters.
        :rtype: tuple(float, float)
        """
        return self._tool.ParOnFaceS2(n, 0., 0.)

    def normal_on_shape1(self, n=1):
        """
        Get a unit normal on the first shape where the *n-th* solution is
        located if it is in a face.

        :param int n: The index.

        :return: The unit normal.
        :rtype: afem.geometry.entities.Direction

        :raise ValueError: If the solution is not in a face.
        """
        if not self.is_in_face_shape1(n):
            raise ValueError('The solution is not in a face.')

        face = self.support_on_shape1(n)
        u, v = self.par_on_face_shape1(n)

        adp_srf = FaceAdaptorSurface.by_face(face)
        return Direction.by_vector(adp_srf.norm(u, v))

    def normal_on_shape2(self, n=1):
        """
        Get a unit normal on the second shape where the *n-th* solution is
        located if it is in a face.

        :param int n: The index.

        :return: The unit normal.
        :rtype: afem.geometry.entities.Direction

        :raise ValueError: If the solution is not in a face.
        """
        if not self.is_in_face_shape2(n):
            raise ValueError('The solution is not in a face.')

        face = self.support_on_shape2(n)
        u, v = self.par_on_face_shape2(n)

        adp_srf = FaceAdaptorSurface.by_face(face)
        return Direction.by_vector(adp_srf.norm(u, v))