def by3Points(cls, p1, p2, p3, epsilon=1e-8): """Create a CADCircle with 3 points ABC /------\ | | A C | | \--B---/ """ if not all(isinstance(p, (QgsPoint, CADPoint)) for p in [p1, p2, p3]): raise AttributeError p1 = CADPoint(p1) p2 = CADPoint(p2) p3 = CADPoint(p3) # Paul Bourke's algorithm m_Center = CADPoint() m_dRadius = -1 yDelta_a = p2.y - p1.y xDelta_a = p2.x - p1.x yDelta_b = p3.y - p2.y xDelta_b = p3.x - p2.x try: aSlope = yDelta_a / xDelta_a except ZeroDivisionError: return None try: bSlope = yDelta_b / xDelta_b except ZeroDivisionError: return None if (math.fabs(xDelta_a) <= epsilon and math.fabs(yDelta_b) <= epsilon): m_Center.x = (0.5 * (p2.x + p3.x)) m_Center.y = (0.5 * (p1.y + p2.y)) m_dRadius = m_Center.distance(p1) return cls(m_Center, m_dRadius) if math.fabs(aSlope-bSlope) <= epsilon: return None m_Center.x = ( (aSlope * bSlope * (p1.y - p3.y) + bSlope * (p1.x + p2.x) - aSlope * (p2.x + p3.x)) / (2.0 * (bSlope - aSlope)) ) m_Center.y = ( -1.0 * (m_Center.x - (p1.x + p2.x) / 2.0) / aSlope + (p1.y + p2.y) / 2.0 ) m_dRadius = m_Center.distance(p1) return cls(m_Center, m_dRadius)
def intersection(self, other): if not isinstance(other, CADLine): raise AttributeError # public domain function by Darel Rex Finley, 2006 # http://alienryderflex.com/intersect/ pt_inter = CADPoint() Ax, Ay, Bx, By = self.pointsXY Cx, Cy, Dx, Dy = other.pointsXY if ((Ax == Bx and Ay == By) or (Cx == Dx and Cy == Dy)): return None # (1) Translate the system so that point A is on the origin. Bx -= Ax By -= Ay Cx -= Ax Cy -= Ay Dx -= Ax Dy -= Ay # Discover the length of segment A-B. distAB = math.sqrt(Bx * Bx + By * By) # (2) Rotate the system so that point B is on the positive X axis. theCos = Bx / distAB theSin = By / distAB newX = Cx * theCos + Cy * theSin Cy = Cy * theCos - Cx * theSin Cx = newX newX = Dx * theCos + Dy * theSin Dy = Dy * theCos - Dx * theSin Dx = newX # Fail if the lines are parallel. if (Cy == Dy): return None # (3) Discover the position of the intersection point along line A-B. ABpos = Dx + (Cx - Dx) * Dy / (Dy - Cy) # (4) Apply the discovered position to line A-B # in the original coordinate system. pt_inter.x = Ax + ABpos * theCos pt_inter.y = Ay + ABpos * theSin # Success. return pt_inter