def test_radians(self): """test_radians doc...""" for i in range(100): value = random.uniform(-2000.0, 5000.0) a = angle.Angle(radians=value) self.assertAlmostEqual(a.radians, value) for i in range(100): value = random.uniform(-2000.0, 5000.0) a = angle.Angle() a.radians = value self.assertAlmostEqual(a.radians, value)
def test_differenceBetween(self): """test_differenceBetween doc...""" for i in range(1000): value = random.uniform(-2000.0, 5000.0) a = angle.Angle(degrees=value) a.constrain_to_revolution() value = random.uniform(-2000.0, 5000.0) b = angle.Angle(degrees=value) b.constrain_to_revolution() self.assertLessEqual(abs(a.difference_between(b).degrees), 180.0)
def test_degrees(self): """ doc... """ for i in range(100): value = random.uniform(-2000.0, 5000.0) a = angle.Angle(degrees=value) self.assertAlmostEqual(a.degrees, value) for i in range(100): value = random.uniform(-2000.0, 5000.0) a = angle.Angle() a.degrees = value self.assertAlmostEqual(a.degrees, value)
def test_constrainToRevolution(self): """test_revolvePositive doc...""" for i in range(100): value = random.uniform(-2000.0, 5000.0) a = angle.Angle(degrees=value) a.constrain_to_revolution() self.assertLessEqual(a.degrees, 360.0) self.assertGreaterEqual(a.degrees, 0.0)
def test_rotate(self): tests = [(90.0, 0.0, 1.0), (-90.0, 0.0, -1.0), (180.0, -1.0, 0.0), (-180.0, -1.0, 0.0), (270.0, 0.0, -1.0), (-270.0, 0.0, 1.0), (360.0, 1.0, 0.0), (-360.0, 1.0, 0.0), (45.0, HALF_SQRT_2, HALF_SQRT_2), (-45.0, HALF_SQRT_2, -HALF_SQRT_2), (315.0, HALF_SQRT_2, -HALF_SQRT_2), (-315.0, HALF_SQRT_2, HALF_SQRT_2), (30.0, HALF_SQRT_3, 0.5), (-30.0, HALF_SQRT_3, -0.5), (330.0, HALF_SQRT_3, -0.5), (-330.0, HALF_SQRT_3, 0.5)] for test in tests: radius = random.uniform(0.001, 1000.0) p = value2D.Point2D(value.ValueUncertainty(radius, 0.25), value.ValueUncertainty(0.0, 0.25)) p.rotate(angle.Angle(degrees=test[0])) self.assertAlmostEqual(p.x.raw, radius * test[1], 2) self.assertAlmostEqual(p.y.raw, radius * test[2], 2)
def angle_between(self, point): """ :param point: :return: """ my_length = self.length pos_length = point.length numerator = self.x*point.x + self.y*point.y denominator = my_length * pos_length if value.equivalent(denominator.value, 0.0, 1e-6): return angle.Angle(radians=0.0, uncertainty=0.5*math.pi) result = numerator/denominator if value.equivalent(result.value, 1.0, 1e-5): return angle.Angle() try: if value.equivalent(result.value, -1.0, 1e-5): a = math.pi else: a = math.acos(result.raw) except Exception: print('[ERROR]: Unable to calculate angle between', result) return angle.Angle() if value.equivalent(a, math.pi, 1e-5): return angle.Angle(radians=a, uncertainty_degrees=180.0) try: aUnc = abs(1.0 / (1.0 - result.raw * result.raw) ** 0.5) * \ result.raw_uncertainty except Exception as err: print('[ERROR]: Unable to calculate angle between uncertainty', result, a) return angle.Angle() return angle.Angle(radians=a, uncertainty=aUnc)
def closest_point_on_line(point, line_start, line_end, contained=True): """ Finds the closest point on a line to the specified point using the formulae discussed in the "another formula" section of: wikipedia.org/wiki/Distance_from_a_point_to_a_line#Another_formula """ length = line_start.distance_from(line_end) if not length: raise ValueError('Cannot calculate point. Invalid line segment.') s = line_start e = line_end delta_x = e.x.raw - s.x.raw delta_y = e.y.raw - s.y.raw rotate = False slope = 0.0 slope_unc = 0.0 try: slope = delta_y / delta_x slope_unc = ( abs(1.0 / delta_x) * ( s.y.raw_uncertainty + e.y.raw_uncertainty ) + abs( slope / delta_x ) * ( s.x.raw_uncertainty + e.x.raw_uncertainty ) ) except Exception: rotate = True raise if rotate or (abs(slope) > 1.0 and abs(slope_unc / slope) > 0.5): a = angle.Angle(degrees=20.0) e2 = e.clone().rotate(a, s) p2 = point.clone().rotate(a, s) print(point, p2) print(e, e2) result = closest_point_on_line(p2, s, e2, contained) if result is None: return result a.degrees = -20.0 result.rotate(a, s) return result intercept = s.y.raw - slope * s.x.raw denom = slope * slope + 1.0 numer = point.x.raw + slope * (point.y.raw - intercept) x = numer / denom y = (slope * numer) / denom + intercept if contained: # Check to see if point is between start and end values x_range = sorted([s.x.raw, e.x.raw]) y_range = sorted([s.y.raw, e.y.raw]) eps = 1e-8 x_min = x - eps x_max = x + eps y_min = y - eps y_max = y + eps out_of_bounds = ( x_range[1] < x_min or x_max < x_range[0] or y_range[1] < y_min or y_max < y_range[0] ) if out_of_bounds: return None start_dist = ops.sqrt_sum_of_squares(s.x.raw - x, s.y.raw - y) end_dist = ops.sqrt_sum_of_squares(e.x.raw - x, e.y.raw - y) x_unc = ( start_dist / length.raw * s.x.raw_uncertainty + end_dist / length.raw * e.x.raw_uncertainty ) x_unc = math.sqrt(x_unc ** 2 + point.x.raw_uncertainty ** 2) y_unc = ( start_dist / length.raw * s.y.raw_uncertainty + end_dist / length.raw * e.y.raw_uncertainty ) y_unc = math.sqrt(y_unc ** 2 + point.y.raw_uncertainty ** 2) return create_point(x=x, y=y, x_unc=x_unc, y_unc=y_unc)