Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

ตรวจสอบจุดอยู่ใน/นอกวงกลมที่กำหนดโดย 3 จุด ใน C++

กำหนดวงกลมด้วย 3 จุดที่ไม่一直線 (non-collinear) แล้วตรวจสอบว่าจุดที่ 4 อยู่ภายใน นอก หรือบนวงกลม

หลักการทางเรขาคณิต

สมการวงกลมทั่วไป: (x - h)² + (y - k)² = r²

โดยจุดศูนย์กลาง (h, k) และรัศมี r สามารถคำนวณจาก 3 จุดได้

สำหรับจุดทดสอบ (x, y) คำนวณค่า:

s = (x - h)² + (y - k)² - r²
  • s < 0 → จุดอยู่ ภายใน วงกลม
  • s = 0 → จุดอยู่ บน วงกลม
  • s > 0 → จุดอยู่ นอก วงกลม

การหาจุดศูนย์กลางจาก 3 จุด

กำหนด 3 จุด: A(x₁,y₁), B(x₂,y₂), C(x₃,y₃)

จุดศูนย์กลางเป็นจุดตัดของเส้นแบ่งมุมตั้งฉากของ AB และ BC

ตัวอย่างโค้ด (ปรับปรุงจากต้นฉบับ)

#include <iostream>
#include <cmath>
#include <limits>

using namespace std;

struct Point {
    double x, y;
};

struct Circle {
    Point center;
    double radius;
    bool valid;
};

// คำนวณวงกลมจาก 3 จุด
Circle circleFrom3Points(const Point& A, const Point& B, const Point& C) {
    Circle result = {{0, 0}, 0, false};
    
    // ตรวจสอบ collinearity
    double d = 2 * (A.x * (B.y - C.y) + B.x * (C.y - A.y) + C.x * (A.y - B.y));
    if (fabs(d) < 1e-10) return result; // จุดอยู่บนเส้นตรงเดียวกัน
    
    double ux = ((A.x*A.x + A.y*A.y) * (B.y - C.y) +
                 (B.x*B.x + B.y*B.y) * (C.y - A.y) +
                 (C.x*C.x + C.y*C.y) * (A.y - B.y)) / d;
    
    double uy = ((A.x*A.x + A.y*A.y) * (C.x - B.x) +
                 (B.x*B.x + B.y*B.y) * (A.x - C.x) +
                 (C.x*C.x + C.y*C.y) * (B.x - A.x)) / d;
    
    result.center = {ux, uy};
    result.radius = sqrt((ux - A.x)*(ux - A.x) + (uy - A.y)*(uy - A.y));
    result.valid = true;
    return result;
}

// ตรวจสอบตำแหน่งจุดเทียบวงกลม
int pointInCircle(const Point& p, const Circle& c) {
    if (!c.valid) return -2; // error
    
    double dx = p.x - c.center.x;
    double dy = p.y - c.center.y;
    double distSq = dx*dx + dy*dy;
    double rSq = c.radius * c.radius;
    double diff = distSq - rSq;
    
    const double EPS = 1e-10;
    if (fabs(diff) < EPS) return 0;      // บนวงกลม
    return (diff < 0) ? -1 : 1;          // -1: ใน, 1: นอก
}

int main() {
    // จุดกำหนดวงกลม
    Point A = {0, 0}, B = {4, 0}, C = {2, 3};
    
    Circle circle = circleFrom3Points(A, B, C);
    
    if (!circle.valid) {
        cout << "3 จุดอยู่บนเส้นตรงเดียวกัน ไม่สามารถสร้างวงกลมได้" << endl;
        return 1;
    }
    
    cout << "วงกลมจากจุด A(" << A.x << "," << A.y << ") "
         << "B(" << B.x << "," << B.y << ") "
         << "C(" << C.x << "," << C.y << ")" << endl;
    cout << "ศูนย์กลาง: (" << circle.center.x << ", " << circle.center.y << ")" << endl;
    cout << "รัศมี: " << circle.radius << endl;
    
    // ทดสอบจุดต่างๆ
    Point testPoints[] = {
        {2, 1},   // ภายใน
        {2, 3},   // บนวงกลม (จุด C)
        {10, 10}, // นอก
        {0, 0}    // บนวงกลม (จุด A)
    };
    
    cout << "\nการทดสอบ:" << endl;
    for (const auto& p : testPoints) {
        int pos = pointInCircle(p, circle);
        string posStr = (pos == -1) ? "ภายใน" : (pos == 0) ? "บนวงกลม" : "นอก";
        cout << "จุด (" << p.x << ", " << p.y << ") -> " << posStr << endl;
    }
    
    // รับจากผู้ใช้
    Point userPt;
    cout << "\nป้อนจุดทดสอบ (x y): ";
    if (cin >> userPt.x >> userPt.y) {
        int pos = pointInCircle(userPt, circle);
        string posStr = (pos == -1) ? "ภายใน" : (pos == 0) ? "บนวงกลม" : "นอก";
        cout << "จุด (" << userPt.x << ", " << userPt.y << ") -> " << posStr << endl;
    }
    
    return 0;
}

ผลลัพธ์ตัวอย่าง

วงกลมจากจุด A(0,0) B(4,0) C(2,3)
ศูนย์กลาง: (2, 1.33333)
รัศมี: 2.4037

การทดสอบ:
จุด (2, 1) -> ภายใน
จุด (2, 3) -> บนวงกลม
จุด (10, 10) -> นอก
จุด (0, 0) -> บนวงกลม

ข้อควรระวัง

  • ความแม่นยำ floating-point: ใช้ epsilon ในการเปรียบเทียบ
  • 3 จุดต้องไม่一直線 (collinear) มิฉะนั้นไม่มีวงกลมที่ผ่านทั้ง 3 จุด
  • สำหรับ integer coordinates ใหญ่ ควรใช้ exact arithmetic หรือ arbitrary precision