Esempio n. 1
0
    def get_closest_point(self, point, iterations=_PL_consts.CURVE_CLOSEST_POINT_ITER):
        """Get's closest point on the curve to given point.

        NOTE: length of the curve must be already calculated.

        :param point: point to which closest curve point will be calculated
        :type point: mathutils.Vector
        :param iterations: number of iterastion for halving algorithm
        :type iterations: int
        :return: curve position coeficient of the closest point (0.0 - 1.0)
        :rtype: float
        """

        curve_p1, curve_t1 = self.get_start()
        curve_p2, curve_t2 = self.get_end()

        interval = (0, 0.5, 1)

        while iterations > 0:

            curr_p = _curve_utils.smooth_curve(curve_p1, curve_t1, curve_p2, curve_t2, interval[0])
            p1_distance = _math_utils.get_distance(curr_p, point)

            curr_p = _curve_utils.smooth_curve(curve_p1, curve_t1, curve_p2, curve_t2, interval[2])
            p3_distance = _math_utils.get_distance(curr_p, point)

            if p1_distance < p3_distance:
                interval = (interval[0], (interval[0] + interval[1]) / 2, interval[1])
            else:
                interval = (interval[1], (interval[1] + interval[2]) / 2, interval[2])

            iterations -= 1

        return interval[1]
Esempio n. 2
0
    def get_intersection_radius(curve1, curve2, curve1_pos_coef, curve2_pos_coef, curve1_direction=1, curve2_direction=1):
        """Get needed radius for reaching safe point when moving on curves in desired direction.
        In forst case full radius is returned which is the point where curve has no ancestors/children anymore.

        :param curve1: first curve
        :type curve1: io_scs_tools.exp.pip.curve.Curve
        :param curve2: second curve
        :type curve2: io_scs_tools.exp.pip.curve.Curve
        :param curve1_pos_coef: position coeficient of first curve for intersection point
        :type curve1_pos_coef: float
        :param curve2_pos_coef: position coeficient of second curve for intersection point
        :type curve2_pos_coef: float
        :param curve1_direction: first curve scaning direction (forward scaning: 1; backward scaning: -1)
        :type curve1_direction: int
        :param curve2_direction: second curve scaning direction (forward scaning: 1; backward scaning: -1)
        :type curve2_direction: int
        :return: radius; 0 if curves have same fork/joint, depending on their direction
        :rtype: int
        """

        steps = (0.1, 0.1)  # size of the step on curve in each iteration

        curr_c = [curve1, curve2]  # current curves
        curr_pos = [curr_c[0].get_length() * curve1_pos_coef, curr_c[1].get_length() * curve2_pos_coef]  # current curves positions

        # first point and tangent vectors for both curves
        curve_p1 = [Vector(), Vector()]
        curve_t1 = [Vector(), Vector()]

        # second point and tangent vectors for both curves
        curve_p2 = [Vector(), Vector()]
        curve_t2 = [Vector(), Vector()]

        curve_directions = (curve1_direction, curve2_direction)  # stepping directions for both curves

        # current radius and distance between curves
        radius = 0
        distance = 0

        # advance until distance is meet
        while distance <= _PL_consts.SAFE_DISTANCE:

            # get data for both curves
            for i in range(2):

                # go to next position on curve
                old_curr_pos = curr_pos[i]
                if curve_directions[i] == 1:
                    curr_pos[i] = min(curr_pos[i] + steps[i], curr_c[i].get_length())
                else:
                    curr_pos[i] = max(0, curr_pos[i] - steps[i])

                # if we reached end of the curve, try to get on next/previous one or exit
                if old_curr_pos == curr_pos[i]:

                    # step out if no next/previous possible curve
                    if len(curr_c[i].get_next_prev_curves(curve_directions[i] == 1)) < 1:
                        return radius

                    curr_c[i] = curr_c[i].get_next_prev_curves(curve_directions[i] == 1)[0]

                    if curve_directions[i] == 1:
                        curr_pos[i] = min(steps[i], curr_c[i].get_length())
                    else:
                        curr_pos[i] = max(0, curr_c[i].get_length() - steps[i])

                curve_p1[i], curve_t1[i] = curr_c[i].get_start()
                curve_p2[i], curve_t2[i] = curr_c[i].get_end()

            # extra check if curves have same fork/joint;
            # then calculated radius has to be ignored therefore return zero radius
            next_prev_c1 = curr_c[0].get_next_prev_curves(curve_directions[i] == 1)
            next_prev_c2 = curr_c[1].get_next_prev_curves(curve_directions[i] == 1)

            if len(next_prev_c1) == 1 and len(next_prev_c2) == 1:
                if next_prev_c1[0] == next_prev_c2[0]:
                    return 0

            # if everything is okay finally calculate curve points, distance and radius
            curr_p1 = _curve_utils.smooth_curve(curve_p1[0], curve_t1[0], curve_p2[0], curve_t2[0], curr_pos[0] / curr_c[0].get_length())
            curr_p2 = _curve_utils.smooth_curve(curve_p1[1], curve_t1[1], curve_p2[1], curve_t2[1], curr_pos[1] / curr_c[1].get_length())

            distance = _math_utils.get_distance(curr_p1, curr_p2)
            radius += steps[0]

        return radius
Esempio n. 3
0
    def get_intersection_radius(curve1,
                                curve2,
                                curve1_pos_coef,
                                curve2_pos_coef,
                                curve1_direction=1,
                                curve2_direction=1):
        """Get needed radius for reaching safe point when moving on curves in desired direction.
        In forst case full radius is returned which is the point where curve has no ancestors/children anymore.

        :param curve1: first curve
        :type curve1: io_scs_tools.exp.pip.curve.Curve
        :param curve2: second curve
        :type curve2: io_scs_tools.exp.pip.curve.Curve
        :param curve1_pos_coef: position coeficient of first curve for intersection point
        :type curve1_pos_coef: float
        :param curve2_pos_coef: position coeficient of second curve for intersection point
        :type curve2_pos_coef: float
        :param curve1_direction: first curve scaning direction (forward scaning: 1; backward scaning: -1)
        :type curve1_direction: int
        :param curve2_direction: second curve scaning direction (forward scaning: 1; backward scaning: -1)
        :type curve2_direction: int
        :return: radius; 0 if curves have same fork/joint, depending on their direction
        :rtype: int
        """

        steps = (0.1, 0.1)  # size of the step on curve in each iteration

        curr_c = [curve1, curve2]  # current curves
        curr_pos = [
            curr_c[0].get_length() * curve1_pos_coef,
            curr_c[1].get_length() * curve2_pos_coef
        ]  # current curves positions

        # first point and tangent vectors for both curves
        curve_p1 = [Vector(), Vector()]
        curve_t1 = [Vector(), Vector()]

        # second point and tangent vectors for both curves
        curve_p2 = [Vector(), Vector()]
        curve_t2 = [Vector(), Vector()]

        curve_directions = (curve1_direction, curve2_direction
                            )  # stepping directions for both curves

        # current radius and distance between curves
        radius = 0
        distance = 0

        # advance until distance is meet
        while distance <= _PL_consts.SAFE_DISTANCE:

            # get data for both curves
            for i in range(2):

                # go to next position on curve
                old_curr_pos = curr_pos[i]
                if curve_directions[i] == 1:
                    curr_pos[i] = min(curr_pos[i] + steps[i],
                                      curr_c[i].get_length())
                else:
                    curr_pos[i] = max(0, curr_pos[i] - steps[i])

                # if we reached end of the curve, try to get on next/previous one or exit
                if old_curr_pos == curr_pos[i]:

                    # step out if no next/previous possible curve
                    if len(curr_c[i].get_next_prev_curves(
                            curve_directions[i] == 1)) < 1:
                        return radius

                    curr_c[i] = curr_c[i].get_next_prev_curves(
                        curve_directions[i] == 1)[0]

                    if curve_directions[i] == 1:
                        curr_pos[i] = min(steps[i], curr_c[i].get_length())
                    else:
                        curr_pos[i] = max(0, curr_c[i].get_length() - steps[i])

                curve_p1[i], curve_t1[i] = curr_c[i].get_start()
                curve_p2[i], curve_t2[i] = curr_c[i].get_end()

            # extra check if curves have same fork/joint;
            # then calculated radius has to be ignored therefore return zero radius
            next_prev_c1 = curr_c[0].get_next_prev_curves(
                curve_directions[i] == 1)
            next_prev_c2 = curr_c[1].get_next_prev_curves(
                curve_directions[i] == 1)

            if len(next_prev_c1) == 1 and len(next_prev_c2) == 1:
                if next_prev_c1[0] == next_prev_c2[0]:
                    return 0

            # if everything is okay finally calculate curve points, distance and radius
            curr_p1 = _curve_utils.smooth_curve(
                curve_p1[0], curve_t1[0], curve_p2[0], curve_t2[0],
                curr_pos[0] / curr_c[0].get_length())
            curr_p2 = _curve_utils.smooth_curve(
                curve_p1[1], curve_t1[1], curve_p2[1], curve_t2[1],
                curr_pos[1] / curr_c[1].get_length())

            distance = _math_utils.get_distance(curr_p1, curr_p2)
            radius += steps[0]

        return radius