1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| from decimal import * import math
class Circle(object): def __init__(self, g=3, start=(0, 0), end=(0, 0), offset=(0, 0), r=0) -> None: self.start = tuple(map(lambda x: Decimal(str(x)).quantize(Decimal("0.000")), start)) self.end = tuple(map(lambda n: Decimal(str(n)).quantize(Decimal("0.000")), end)) self.g = g if offset != (0, 0): self.offset = tuple(map(lambda x: Decimal(str(x)).quantize(Decimal("0.000")), offset)) else: self.r = Decimal(str(r)) self.zoom = Decimal(1000) self.delta = Decimal(1) / self.zoom self.__getCenter()
def __str__(self) -> str: return "start=({:,.3f},{:,.3f}); end=({:,.3f},{:,.3f}); center=({:,.3f},{:,.3f}); radius={:,.3f}".format( float(self.start[0]), float(self.start[1]), float(self.end[0]), float(self.end[1]), float(self.x0), float(self.y0), float(self.r), )
def __getCenter(self) -> tuple: if "offset" in dir(self): self.x0 = self.start[0] + self.offset[0] self.y0 = self.start[1] + self.offset[1] self.r = math.sqrt((self.end[0] - self.x0) ** 2 + (self.end[1] - self.y0) ** 2) self.r = Decimal(str(self.r)) else: xs, ys = self.start[0], self.start[1] xe, ye = self.end[0], self.end[1] c1 = (xs**2 - xe**2 + ys**2 - ye**2) / (2 * xs - 2 * xe) c2 = (ys - ye) / (xs - xe) a = 1 + c2**2 b = 2 * (xe - c1) * c2 - 2 * ye c = (xe - c1) ** 2 + ye**2 - self.r**2 y0 = (-b + Decimal(str(math.sqrt(b**2 - 4 * a * c)))) / (2 * a) x0 = c1 - c2 * y0 xm = (xs + xe) / 2 ym = (ys + ye) / 2 if xm > x0 and ym > y0: self.y0 = y0 self.x0 = x0 else: self.y0 = (-b - Decimal(str(math.sqrt(b**2 - 4 * a * c)))) / (2 * a) self.x0 = c1 - c2 * self.y0
def __offset(self) -> None: self.__xs = self.start[0] - self.x0 self.__ys = self.start[1] - self.y0 self.__xe = self.end[0] - self.x0 self.__ye = self.end[1] - self.y0 self.f = 0 self.step = abs(self.__xs - self.__xe) + abs(self.__ys - self.__ye) self.step = self.step * self.zoom
@staticmethod def __getQD(point) -> int: match (point[0] >= 0, point[1] >= 0): case (1, 1): return 1 case (0, 1): return 2 case (0, 0): return 3 case (1, 0): return 4
def __compensation(self) -> None: qd = Circle.__getQD((self.__x, self.__y)) match (self.g, self.f >= 0, qd): case (3, 1, 1) | (3, 0, 2) | (2, 0, 3) | (2, 1, 4): self.f = self.f - 2 * self.__x + self.delta self.__x -= self.delta case (3, 0, 1) | (3, 1, 4) | (2, 0, 2) | (2, 1, 3): self.f = self.f + 2 * self.__y + self.delta self.__y += self.delta case (3, 1, 3) | (3, 0, 4) | (2, 1, 2) | (2, 0, 1): self.f = self.f + 2 * self.__x + self.delta self.__x += self.delta case (3, 0, 3) | (3, 1, 2) | (2, 1, 1) | (2, 0, 4): self.f = self.f - 2 * self.__y + self.delta self.__y -= self.delta
def __iter__(self): self.__offset() self.__x = self.__xs self.__y = self.__ys return self
def __next__(self): if self.step: self.__compensation() self.step -= 1 return (float(self.__x + self.x0), float(self.__y + self.y0)) else: if self.__x + self.x0 != self.end[0] or self.__y + self.y0 != self.end[1]: print("圆弧错误,请检查输入代码") raise StopIteration
|