def check(y, x1, x2): result = circle.get_x(y) self.assertTrue(result) # order of results unknown v1 = equals_almost(result[0], x1, 4) and equals_almost(result[1], x2, 4) v2 = equals_almost(result[0], x2, 4) and equals_almost(result[1], x1, 4) return v1 or v2
def check(x, y1, y2): result = circle.get_y(x) self.assertTrue(result) # order of results unknown v1 = equals_almost(result[0], y1, 4) and equals_almost(result[1], y2, 4) v2 = equals_almost(result[0], y2, 4) and equals_almost(result[1], y1, 4) return v1 or v2
def goes_through(self, point): """ returns True if ray goes through point, else False""" if self.is_vertical: return equals_almost(point[XCOORD], self._x, self.places) else: return equals_almost(point[YCOORD], self.get_y(point[XCOORD]), self.places)
def intersect_ray(self, ray, places=7): """ calculates the intersection points for circle with ray returns a list of Point2D places: significant decimal places for tests (e.g. test for tangents) list contains: 0 points .. no intersection 1 point .. ray is a tangent on the circle 2 points .. ray intersects with the circle """ def get_angle(point): dx = point[0] - self.center_point[0] dy = point[1] - self.center_point[1] return math.atan2(dy, dx) normal_ray = ray.normal_through(self.center_point) cross_point = ray.intersect(normal_ray) dist = distance(self.center_point, cross_point) result = list() if dist < self.radius: # intersect in two points if equals_almost(dist, 0., places): # if ray goes through midpoint angle = normal_ray.angle alpha = HALF_PI else: # the exact direction of angle (all 4 quadrants Q1-Q4) is important: # normal_ray.angle is only at the center point correct angle = get_angle(cross_point) alpha = math.acos( distance(cross_point, self.center_point) / self.radius) result.append(self.get_point(angle + alpha)) result.append(self.get_point(angle - alpha)) elif equals_almost(dist, self.radius, places): # ray is a tangent of circle result.append(cross_point) # else no intersection return result
def goes_through(self, point): """ returns True if ray goes through point, else False""" if self.is_vertical: return equals_almost(point[XCOORD], self._x, self.places) else : return equals_almost(point[YCOORD], self.get_y(point[XCOORD]), self.places)
def intersect_circle(self, other_circle, places=7): """ calculates the intersection points for circle with other_circle places: significant decimal places for tests (e.g. test for circle touch point) returns a list of Point2D list contains: 0 points .. no intersection 1 point .. circle touches the other_circle in one point 2 points .. circle intersects with the other_circle """ def get_angle_through_center_points(): dx = other_circle.center_point[0] - self.center_point[0] dy = other_circle.center_point[1] - self.center_point[1] return math.atan2(dy, dx) R1 = self.radius R2 = other_circle.radius dist = distance(self.center_point, other_circle.center_point) max_dist = R1 + R2 min_dist = math.fabs(R1 - R2) result = list() if min_dist <= dist <= max_dist: if equals_almost(dist, max_dist, places) or equals_almost( dist, min_dist, places): #circles touches in one point angle = get_angle_through_center_points() result.append(self.get_point(angle)) else: # circles intersect in two points alpha = math.acos((R2**2 - R1**2 - dist**2) / (-2. * R1 * dist)) # 'Cosinus-Satz' angle = get_angle_through_center_points() result.append(self.get_point(angle + alpha)) result.append(self.get_point(angle - alpha)) return result
def intersect_circle(self, other_circle, places=7): """ calculates the intersection points for circle with other_circle places: significant decimal places for tests (e.g. test for circle touch point) returns a list of Point2D list contains: 0 points .. no intersection 1 point .. circle touches the other_circle in one point 2 points .. circle intersects with the other_circle """ def get_angle_through_center_points(): dx = other_circle.center_point[0] - self.center_point[0] dy = other_circle.center_point[1] - self.center_point[1] return math.atan2(dy, dx) R1 = self.radius R2 = other_circle.radius dist = distance(self.center_point, other_circle.center_point) max_dist = R1 + R2 min_dist = math.fabs(R1 - R2) result = list() if min_dist <= dist <= max_dist: if equals_almost(dist, max_dist, places) or equals_almost(dist, min_dist, places): #circles touches in one point angle = get_angle_through_center_points() result.append(self.get_point(angle)) else : # circles intersect in two points alpha = math.acos((R2**2 - R1**2 - dist**2) / (-2. * R1 * dist)) # 'Cosinus-Satz' angle = get_angle_through_center_points() result.append(self.get_point(angle+alpha)) result.append(self.get_point(angle-alpha)) return result
def intersect_ray(self, ray, places=7): """ calculates the intersection points for circle with ray returns a list of Point2D places: significant decimal places for tests (e.g. test for tangents) list contains: 0 points .. no intersection 1 point .. ray is a tangent on the circle 2 points .. ray intersects with the circle """ def get_angle(point): dx = point[0] - self.center_point[0] dy = point[1] - self.center_point[1] return math.atan2(dy, dx) normal_ray = ray.normal_through(self.center_point) cross_point = ray.intersect(normal_ray) dist = distance(self.center_point, cross_point) result = list() if dist < self.radius : # intersect in two points if equals_almost(dist, 0., places) : # if ray goes through midpoint angle = normal_ray.angle alpha = HALF_PI else: # the exact direction of angle (all 4 quadrants Q1-Q4) is important: # normal_ray.angle is only at the center point correct angle = get_angle(cross_point) alpha = math.acos(distance(cross_point, self.center_point)/self.radius) result.append(self.get_point(angle+alpha)) result.append(self.get_point(angle-alpha)) elif equals_almost(dist, self.radius, places): # ray is a tangent of circle result.append(cross_point) # else no intersection return result
def test_touch(testnum, x, y, _angle, places=7): result = True ray = Ray2D((x, y), angle=_angle) points = circle.intersect_ray(ray, places) if len(points) != 1 : result = False else: point = points[0] if not equals_almost(point[0], x, 4) : result = False if not equals_almost(point[1], y, 4) : result = False return result
def _build_curve(self): def curve_point(alpha): alpha = radians(alpha) point = (cos(alpha) * self.rx, sin(alpha) * self.ry) point = rotate_2d(point, radians(self.rotation)) x, y = vadd(self.center, point) return (x, y, zaxis) def normalize_angle(angle): angle = fmod(angle, 360.0) if angle < 0: angle += 360.0 return angle zaxis = 0.0 if len(self.center) < 3 else self.center[2] points = [] delta = (self.endangle - self.startangle) / self.segments for segment in xrange(self.segments): alpha = self.startangle + delta * segment points.append(curve_point(alpha)) polyline = Polyline(points, color=self.color, layer=self.layer, linetype=self.linetype) if equals_almost(self.startangle, normalize_angle(self.endangle)): polyline.close() return polyline
def __dxftags__(self): def curve_point(alpha): alpha = radians(alpha) point = (cos(alpha) * self.rx, sin(alpha) * self.ry) point = rotate_2d(point, radians(self.rotation)) x, y = vadd(self.center, point) return (x, y, zaxis) def normalize_angle(angle): angle = fmod(angle, 360.) if angle < 0: angle += 360. return angle zaxis = 0. if len(self.center) < 3 else self.center[2] points = [] delta = (self.endangle - self.startangle) / self.segments for segment in xrange(self.segments): alpha = self.startangle + delta * segment points.append(curve_point(alpha)) polyline = Polyline(points, color=self.color, layer=self.layer, linetype=self.linetype) if equals_almost(self.startangle, normalize_angle(self.endangle)): polyline.close() return polyline.__dxftags__()
def is_parallel(self, ray): """ return True if the rays are parallel, else False""" if self.is_vertical: return ray.is_vertical else: return equals_almost(self.slope, ray.slope, self.places)
def is_horizontal(self): return equals_almost(self.slope, 0., self.places)
def equal_points_almost(p1, p2, places=7): return equals_almost(p1[0], p2[0], places) and equals_almost(p1[1], p2[1], places)