Câu hỏi
Cho trục toạ độ Oxy. Một Tam giác hiểu là 3 toạ độ (a, b), (c, d), (m, n) trên mặt phẳng. Viết chương trình kiểm tra một điểm (x, y) có nằm trong tam giác hay không?
Bài giải
Với cách tiếp cận OOP, chúng ta cần định nghĩa class Point, Line, Triangle.
Phải xây dựng Class / Object trước, sau đó mới xây dựng Thuật toán.
<?php
class Point
{
public int $x;
public int $y;
// kiểm tra 2 Point có bằng nhau không
public function isEqual(Point $p): bool
{
return $p->x === $this->x && $p->y === $this->y;
}
}
class Line
{
public Point $p1;
public Point $p2;
/**
* Tính độ dài đoạn thẳng theo công thức khoảng cách Euclid:
* căn((x2 - x1)² + (y2 - y1)²)
*/
public function length()
{
$dx = $this->p2->x - $this->p1->x;
$dy = $this->p2->y - $this->p1->y;
return sqrt($dx ** 2 + $dy ** 2);
}
public static function create(Point $p1, Point $p2): Line
{
// kiểm tra 2 điểm không được trùng nhau
if ($p1->isEqual($p2)) {
return null;
}
$line = new Line();
$line->p1 = $p1;
$line->p2 = $p2;
return $line;
}
}
class Triangle
{
public Point $a;
public Point $b;
public Point $c;
public static function create(Point $a, Point $b, Point $c): static
{
// bổ sung kiểm tra 3 điểm không trùng nhau ở đây
$triangle = new Triangle();
$triangle->a = $a;
$triangle->b = $b;
$triangle->c = $c;
return $triangle;
}
/**
* Tính diện tích tam giác theo công thức Heron.
*/
public function area(): float
{
$ab = (new Line($this->a, $this->b))->length();
$bc = (new Line($this->b, $this->c))->length();
$ca = (new Line($this->c, $this->a))->length();
$p = ($ab + $bc + $ca) / 2; // nửa chu vi
return sqrt($p * ($p - $ab) * ($p - $bc) * ($p - $ca));
}
}
Sau khi mô tả xong các class với function tính diện tích tam giác đã có bằng công thức Heron, chúng ta có thể suy luận như sau: một điểm nằm trong tam giác khi tổng diện tích 3 tam giác con tạo ra bé hơn bằng diện tích tam giác.

như vậy ta chỉ cần bổ sung thêm code vào class Triangle
<?php
class Triangle
{
// ... các code ở trên đã có
public function isContains(Point $p): bool
{
$areaABC = $this->area();
$areaPAB = (new Triangle($p, $this->a, $this->b))->area();
$areaPBC = (new Triangle($p, $this->b, $this->c))->area();
$areaPCA = (new Triangle($p, $this->c, $this->a)->area();
$sum = $areaPAB + $areaPBC + $areaPCA;
// Sai số do số thực floating point
return abs($sum - $areaABC) < 1e-6;
}
}