# HG changeset patch # User David Bryant # Date 1247205367 -34200 # Node ID 58a8ad20b22892c0d4cf68c05fad5b08241941cc # Parent 7d57cae108057b95e98de0a1eb1e356d914269ca Ooops, this got left out of previous commit diff -r 7d57cae10805 -r 58a8ad20b228 tk/geometry.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tk/geometry.d Fri Jul 10 15:26:07 2009 +0930 @@ -0,0 +1,198 @@ +module tk.geometry; + +private import std.stdio; +private import std.math; +private import tk.misc; + +struct Point { + static immutable Point DEFAULT; + + static this() { + DEFAULT = Point(0.0, 0.0); + } + + this(in double x, in double y) { + _x = x; + _y = y; + } + + Point opAdd(in Vector v) const { + return Point(_x + v._x, _y + v._y); + } + + Point opSub(in Vector v) const { + return Point(_x - v._x, _y - v._y); + } + + Vector opSub(in Point p) const { + return Vector(_x - p._x, _y - p._y); + } + + string toString() /* const */ { + return std.string.format("(%f, %f)", _x, _y); + } + + double x() const { return _x; } + double y() const { return _y; } + + private { + double _x, _y; + } +} + +Point min_extents(in Point a, in Point b) { + return Point(min(a.x, b.x), min(a.y, b.y)); +} + +Point max_extents(in Point a, in Point b) { + return Point(max(a.x, b.x), max(a.y, b.y)); +} + +struct Vector { + static Vector DEFAULT; + + static this() { + DEFAULT = Vector(0.0, 0.0); + } + + this(in double x, in double y) { + _x = x; + _y = y; + } + + Vector opAdd(in Vector v) const { + return Vector(_x + v._x, _y + v._y); + } + + Vector opSub(in Vector v) const { + return Vector(_x - v._x, _y - v._y); + } + + Vector opNeg() const { + return Vector(-_x, -_y); + } + + Vector opMul_r(in double d) const { + return Vector(d * _x, d * _y); + } + + Vector opDiv(in double d) const { + return Vector(_x / d, _y / d); + } + + double length() const { + return sqrt(_x * _x + _y * _y); + } + + string toString() /* const */ { + return std.string.format("[%f, %f]", _x, _y); + } + + double x() const { return _x; } + double y() const { return _y; } + + private { + double _x, _y; + } +} + +struct Rectangle { + static Rectangle DEFAULT; + + static this() { + DEFAULT = Rectangle(Point.DEFAULT, Vector.DEFAULT); + } + + /* + static Rectangle from_arbitrary_corners(in Point corner1, in Point corner) { + } + */ + + this(in Point position, in Vector size) { + this(position.x, position.y, size.x, size.y); + } + + this(in Point corner1, in Point corner) { + this(corner1.x, corner1.y, corner.x - corner1.x, corner.y - corner1.y); + } + + Point position() const { + return _position; + } + + alias position min_corner; + + Point max_corner() const { + return _position + _size; + } + + bool valid() const { + return _size.x > 0.0 & _size.y > 0.0; + } + + bool invalid() const { + return !valid(); + } + + double area() const { + return _size.x * _size.y; + } + + // Intersection + Rectangle opAnd(in Rectangle r) const { + if (invalid() || r.invalid()) { + return DEFAULT; + } + else { + Point max = min_extents(max_corner(), r.max_corner()); + Point min = max_extents(min_corner(), r.min_corner()); + + if (max.x < min.x || max.y < min.y) { + return DEFAULT; + } + else { + return Rectangle(min, max); + } + } + } + + // Union + Rectangle opOr(in Rectangle r) const { + if (invalid()) { + return r; + } + else if (r.invalid()) { + return this; + } + else { + return Rectangle(min_extents(min_corner(), r.min_corner()), + max_extents(max_corner(), r.max_corner())); + } + } + + /* + Rectangle moved(in Vector displacement) { + return Rectangle( + } + Rectangle resized(in Vector new_size) { + } + Rectangle repositioned(in Point new_position) { + } + */ + + string toString() /* const */ { + return std.string.format("{%s, %s}", _position, _size); + } + + private { + this(double x, double y, double w, double h) { + if (w < 0.0) { x += w; w = -w; } + if (h < 0.0) { y += h; h = -h; } + _position = Point(x, y); + _size = Vector(w, h); + } + + Point _position; + Vector _size; + } +}