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]
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
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