// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// Bounding box for positioning
pub struct Box {
x : Double
y : Double
width : Double
height : Double
} derive(Eq, Debug)
///|
/// A 2D point
pub struct Point {
x : Double
y : Double
} derive(Eq, Debug)
///|
pub impl Show for Box with fn output(self, logger) {
logger.write_string("{x: ")
logger.write_object(self.x)
logger.write_string(", y: ")
logger.write_object(self.y)
logger.write_string(", width: ")
logger.write_object(self.width)
logger.write_string(", height: ")
logger.write_object(self.height)
logger.write_char('}')
}
///|
pub impl Show for Point with fn output(self, logger) {
logger.write_string("{x: ")
logger.write_object(self.x)
logger.write_string(", y: ")
logger.write_object(self.y)
logger.write_char('}')
}
///|
pub fn Box::new(x : Double, y : Double, width : Double, height : Double) -> Box {
{ x, y, width, height }
}
///|
pub fn Box::zero() -> Box {
{ x: 0.0, y: 0.0, width: 0.0, height: 0.0 }
}
///|
pub fn Point::new(x : Double, y : Double) -> Point {
{ x, y }
}
///|
pub fn Point::zero() -> Point {
{ x: 0.0, y: 0.0 }
}
///|
/// Get the center point of the box
pub fn Box::center(self : Box) -> Point {
Point::new(self.x + self.width / 2.0, self.y + self.height / 2.0)
}
///|
/// Get the top-left corner
pub fn Box::top_left(self : Box) -> Point {
Point::new(self.x, self.y)
}
///|
/// Get the top-right corner
pub fn Box::top_right(self : Box) -> Point {
Point::new(self.x + self.width, self.y)
}
///|
/// Get the bottom-left corner
pub fn Box::bottom_left(self : Box) -> Point {
Point::new(self.x, self.y + self.height)
}
///|
/// Get the bottom-right corner
pub fn Box::bottom_right(self : Box) -> Point {
Point::new(self.x + self.width, self.y + self.height)
}
///|
/// Check if a point is inside the box
pub fn Box::contains(self : Box, p : Point) -> Bool {
p.x >= self.x &&
p.x <= self.x + self.width &&
p.y >= self.y &&
p.y <= self.y + self.height
}
///|
/// Check if this box intersects another
pub fn Box::intersects(self : Box, other : Box) -> Bool {
!(self.x + self.width < other.x ||
other.x + other.width < self.x ||
self.y + self.height < other.y ||
other.y + other.height < self.y)
}
///|
/// Get x coordinate
pub fn Box::get_x(self : Box) -> Double {
self.x
}
///|
/// Get y coordinate
pub fn Box::get_y(self : Box) -> Double {
self.y
}
///|
/// Get width
pub fn Box::get_width(self : Box) -> Double {
self.width
}
///|
/// Get height
pub fn Box::get_height(self : Box) -> Double {
self.height
}
///|
/// Get x coordinate
pub fn Point::get_x(self : Point) -> Double {
self.x
}
///|
/// Get y coordinate
pub fn Point::get_y(self : Point) -> Double {
self.y
}
///|
/// Calculate distance to another point
pub fn Point::distance(self : Point, other : Point) -> Double {
let dx = self.x - other.x
let dy = self.y - other.y
(dx * dx + dy * dy).sqrt()
}
///|
/// Add two points
pub fn Point::add(self : Point, other : Point) -> Point {
Point::new(self.x + other.x, self.y + other.y)
}
///|
/// Subtract another point
pub fn Point::sub(self : Point, other : Point) -> Point {
Point::new(self.x - other.x, self.y - other.y)
}
///|
/// Scale by a factor
pub fn Point::scale(self : Point, factor : Double) -> Point {
Point::new(self.x * factor, self.y * factor)
}