def getDirection(self, a): p0 = self.AO.getPoint(a) p1 = self.OQ.getPoint(a) p2 = self.QB.getPoint(a) r0 = (Segment(p0, p1)).getPoint(a) r1 = (Segment(p1, p2)).getPoint(a) return (Segment(r0, r1)).direction
def _legalize_segment(self, triangle, segment): changes = [] if self._is_legal_segment(triangle, segment): return changes point_i = segment.start point_j = segment.end near_triangle = triangle.get_near_triangle_by_segment(segment) point_k = near_triangle.last_points([point_i, point_j])[0] self._events.append(Event(ev_type=event.DELETE_SEGMENT, data=segment)) new_triangle_a, new_triangle_b = Triangle.change_common_segment(triangle, near_triangle) new_common_segment = new_triangle_a.get_common_segment(new_triangle_b) self._events.append(Event(ev_type=event.ADD_SEGMENT, data=new_common_segment)) changes.append([triangle, [new_triangle_a, new_triangle_b]]) changes.append([near_triangle, [new_triangle_a, new_triangle_b]]) if point_i in new_triangle_a.points: next_changes = self._legalize_segment(new_triangle_a, Segment(point_i, point_k)) else: next_changes = self._legalize_segment(new_triangle_b, Segment(point_i, point_k)) changes.extend(next_changes) if point_j in new_triangle_a.points: next_changes = self._legalize_segment(new_triangle_a, Segment(point_j, point_k)) else: next_changes = self._legalize_segment(new_triangle_b, Segment(point_j, point_k)) changes.extend(next_changes) return changes
def __init__(self, p1, p2, p3): self.points = [p1, p2, p3] self.sides = [ Segment(p1, p2).length(), Segment(p2, p3).length(), Segment(p3, p1).length() ]
def test_is_intersect(self): segments = self.get_segments() self.assertTrue(Segment.is_intersects(segments[0], segments[1])) self.assertFalse(Segment.is_intersects(segments[0], segments[2])) self.assertTrue(Segment.is_intersects(segments[5], segments[3])) self.assertFalse(Segment.is_intersects(segments[4], segments[6]))
def _init_base_triangle(self): left_bound = self._points[0].x - 1 right_bound = self._points[0].x + 1 top_bound = self._points[0].y + 1 down_bound = self._points[0].y - 1 higher_point = self._points[0] for point in self._points: if point.x >= right_bound: right_bound = point.x + 1 if point.x <= left_bound: left_bound = point.x - 1 if point.y >= top_bound: top_bound = point.y + 1 higher_point = point if point.y <= down_bound: down_bound = point.y - 1 self._higher_point = higher_point self._events.append(Event(ev_type=event.SELECT_BASE_POINT, data=higher_point)) down_base_point = self._find_down_base_point(right_bound, down_bound) self._down_base_point = down_base_point self._events.append(Event(ev_type=event.SELECT_BASE_POINT, data=down_base_point)) top_base_point = self._find_top_base_point(left_bound, top_bound, down_base_point) self._top_base_point = top_base_point self._events.append(Event(ev_type=event.SELECT_BASE_POINT, data=top_base_point)) self._base_triangle = Triangle(down_base_point, top_base_point, higher_point) self._events.append(Event(ev_type=event.ADD_BASE_SEGMENT, data=Segment(down_base_point, top_base_point))) self._events.append(Event(ev_type=event.ADD_BASE_SEGMENT, data=Segment(down_base_point, higher_point))) self._events.append(Event(ev_type=event.ADD_BASE_SEGMENT, data=Segment(higher_point, top_base_point)))
def get_segments(self): return [ Segment(Point(5, 5), Point(1, 1)), Segment(Point(1, 1), Point(1, 6)), Segment(Point(0, -1), Point(7, -1)), Segment(Point(-2, 6), Point(-2, -4)), Segment(Point(-4, 4), Point(4, -4)), Segment(Point(-8, -1), Point(5, 1)), Segment(Point(1, 2), Point(6, 0)), Segment(Point(-5, 0), Point(5, 0)), Segment(Point(0, 5), Point(0, -5)), Segment(Point(-5, 5), Point(-1, 1)) ]
def get_intersect(c1, c2): length = Segment(c1.center, c2.center).length() points = [] if length == 0 and c1.radius == c2.radius: return {"orientation": CircleOrientation.EQUAL, "points": points} if c1.radius + c2.radius < length: return { "orientation": CircleOrientation.NOT_INTERSECT, "points": points } if fabs(c1.radius - c2.radius) > length: return { "orientation": CircleOrientation.NOT_INTERSECT, "points": points } b = (c2.radius**2 - c1.radius**2 + length**2) / (2 * length) a = length - b h = sqrt(c1.radius**2 - a**2) p0 = Point(c1.center.x + a / length * (c2.center.x - c1.center.x), c1.center.y + a / length * (c2.center.y - c1.center.y)) points.append( Point(p0.x + h / length * (c2.center.y - c1.center.y), p0.y - h / length * (c2.center.x - c1.center.x))) points.append( Point(p0.x - h / length * (c2.center.y - c1.center.y), p0.y + h / length * (c2.center.x - c1.center.x))) return {"orientation": CircleOrientation.INTERSECT, "points": points}
def get_tangents(self, point: Point): point_position = self.substitute(point) if point_position < 0: return None if point_position == 0: return LineBuilder.from_points(self.center, point).get_orthogonal() catheter = Segment(point, self.center).length() hypotenuse = sqrt(self.radius**2 + catheter**2) c = self.center.x - point.x d = self.center.y - point.y b = [ hypotenuse * (c * self.radius - d) / (c**2 - d**2), hypotenuse * (-c * self.radius - d) / (c**2 - d**2) ] a = [hypotenuse**2 - d * b[0] / c, hypotenuse**2 - d * b[1] / c] tangent_points = [ Point(point.x - a[0], point.y - b[0]), Point(point.x - a[1], point.y - b[1]) ] return [ LineBuilder.from_points(point, tangent_points[0]), LineBuilder.from_points(point, tangent_points[1]) ]
def _find_top_base_point(self, left_bound, top_bound, down_base_point): points_a = copy.deepcopy(self._points + [down_base_point]) points_b = copy.deepcopy(self._points + [down_base_point]) left = -1e9 right = left_bound res_point = None while right - left >= 0: middle = left + (right - left) // 2 base.BASE_POINT = Point(x=middle, y=top_bound) points_a = sort_point(points_a, lexicographical_comparator) points_b = sort_point(points_b, ccw_comparator) equal_point_sets = True for i in range(len(points_a)): if points_a[i] != points_b[i]: equal_point_sets = False if points_a[i] != self._down_base_point: if Segment(base.BASE_POINT, self._down_base_point).contains_point(points_a[i]): equal_point_sets = False if equal_point_sets: left = middle + 1 res_point = base.BASE_POINT else: right = middle - 1 return res_point
def get_segments(self): segments = [] points = self.points length = len(points) for i in range(0, length): j = (i + 1) % length segments.append(Segment(points[i], points[j])) return segments
def is_simple(self): segments = self.get_segments() length = len(segments) for i in range(0, length): for j in range(i + 2, i + length - 1): if Segment.is_intersects(segments[i], segments[j % length]): return False return True
def __init__(self, A: Point, B: Point, O: Point, Q: Point): self.A = A self.B = B self.O = O self.Q = Q self.AB = Segment(self.A, self.B) self.AO = Segment(self.A, self.O) self.OQ = Segment(self.O, self.Q) self.QB = Segment(self.Q, self.B) self._length = None
def test_contain_point(self): segment = Segment(Point(1, 1), Point(4, 4)) self.assertTrue(segment.contain_point(Point(2, 2))) self.assertTrue(segment.contain_point(Point(1, 1))) self.assertTrue(segment.contain_point(Point(4, 4))) self.assertFalse(segment.contain_point(Point(0, 0))) self.assertFalse(segment.contain_point(Point(-5, 88))) self.assertFalse(segment.contain_point(Point(-1, 0.5)))
def get_optimal_point(points): """ Returns the point the sum of the distances from which to other points is minimal """ min_length = inf point = None for i in range(0, len(points)): length = 0 for j in range(0, len(points)): if i == j: continue length += Segment(points[i], points[j]).length() if min_length > length: min_length = length point = points[i] return point
class Curve(): def __init__(self, A: Point, B: Point, O: Point, Q: Point): self.A = A self.B = B self.O = O self.Q = Q self.AB = Segment(self.A, self.B) self.AO = Segment(self.A, self.O) self.OQ = Segment(self.O, self.Q) self.QB = Segment(self.Q, self.B) self._length = None @property def length(self): if self._length is None: pointsNumber = 10 previousPoint = None self._length = 0 for i in range(pointsNumber): point = self.getPoint(i / pointsNumber) if previousPoint is not None: self._length += (point - previousPoint).length previousPoint = point return self._length def getPoint(self, a): p0 = self.AO.getPoint(a) p1 = self.OQ.getPoint(a) p2 = self.QB.getPoint(a) r0 = (Segment(p0, p1)).getPoint(a) r1 = (Segment(p1, p2)).getPoint(a) return (Segment(r0, r1)).getPoint(a) def getDirection(self, a): p0 = self.AO.getPoint(a) p1 = self.OQ.getPoint(a) p2 = self.QB.getPoint(a) r0 = (Segment(p0, p1)).getPoint(a) r1 = (Segment(p1, p2)).getPoint(a) return (Segment(r0, r1)).direction
def getSides(self): return [ Segment(source, target) for source, target in zip(self.pointList, [self.pointList[-1]]. extend(self.pointList[0:-1])) ]
def getSide(self, i) -> Segment: vertices = self.getVertices() return Segment(vertices[i], vertices[(i + 1) % 4])
def _insert_point(self, point): base_triangle = self._locator.point_location(point) res_triangles, changes = base_triangle.split_by_point(point) for key in changes: self._locator.add_triangle_children(key, changes[key]) next_changes = [] used_triangles = [] for triangle in changes: # inside triangle if len(changes[triangle]) == 3: self._events.append(Event(ev_type=event.ADD_SEGMENT, data=Segment(point, base_triangle.point_a))) self._events.append(Event(ev_type=event.ADD_SEGMENT, data=Segment(point, base_triangle.point_b))) self._events.append(Event(ev_type=event.ADD_SEGMENT, data=Segment(point, base_triangle.point_c))) segment_a = Segment(base_triangle.point_a, base_triangle.point_b) temp_changes = self._legalize_by_segment(changes[triangle], segment_a) next_changes.extend(temp_changes) segment_b = Segment(base_triangle.point_b, base_triangle.point_c) temp_changes = self._legalize_by_segment(changes[triangle], segment_b) next_changes.extend(temp_changes) segment_c = Segment(base_triangle.point_c, base_triangle.point_a) temp_changes = self._legalize_by_segment(changes[triangle], segment_c) next_changes.extend(temp_changes) # on segment else: triangle_a, triangle_b = changes[triangle] common_segment = triangle_a.get_common_segment(triangle_b) self._events.append(Event(ev_type=event.ADD_SEGMENT, data=common_segment)) point_i = triangle_a.last_points([common_segment.start, common_segment.end])[0] point_j = triangle_b.last_points([common_segment.start, common_segment.end])[0] base_segment = Segment(point_i, point_j) if base_segment.contains_point(common_segment.start): start_point = common_segment.end else: start_point = common_segment.start segment_a = Segment(point_i, start_point) next_changes = self._legalize_segment(triangle_a, segment_a) segment_b = Segment(point_j, start_point) temp_changes = self._legalize_segment(triangle_b, segment_b) next_changes.extend(temp_changes) for base_triangle, new_triangles in next_changes: self._locator.add_triangle_children(base_triangle, new_triangles) next_changes.clear() used_triangles.append(triangle) for triangle in used_triangles: self._locator.clear_leaf(triangle)