Mercurial > projects > doodle
diff doodle/tk/geometry.d @ 28:1754cb773d41
Part-way through getting to compile with configure/builder.
author | Graham St Jack <graham.stjack@internode.on.net> |
---|---|
date | Sun, 02 Aug 2009 16:27:21 +0930 |
parents | tk/geometry.d@8f58a8f88735 |
children | 157b4ad5615d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doodle/tk/geometry.d Sun Aug 02 16:27:21 2009 +0930 @@ -0,0 +1,250 @@ +module doodle.tk.geometry; + +private { + import std.stdio; + import std.math; + import doodle.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() { + 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() { + 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; + } + + Vector size() const { + return _size; + } + + 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())); + } + } + + // TODO make these free functions + + Rectangle moved(in Vector displacement) const { + return Rectangle(_position + displacement, _size); + } + + Rectangle expanded(in Vector expand_amount) const { + return Rectangle(_position, _size + expand_amount); + } + + Rectangle feathered(double amount) const { + assert(amount >= 0.0); + return Rectangle(Point(_position.x - amount, _position.y - amount), + Vector(_size.x + 2.0 * amount, _size.y + 2.0 * amount)); + } + + Rectangle shrunk(in Vector shrink_amount) const { + return Rectangle(_position, _size - shrink_amount); + } + + Rectangle resized(in Vector new_size) const { + return Rectangle(_position, new_size); + } + + Rectangle repositioned(in Point new_position) const { + return Rectangle(new_position, _size); + } + + void get_quantised(out int x, out int y, out int w, out int h) const { + x = cast(int)floor(_position.x); + y = cast(int)floor(_position.y); + w = cast(int)ceil(_position.x + _size.x) - x; + h = cast(int)ceil(_position.y + _size.y) - y; + } + + // + + Point centre() const { + return _position + _size / 2.0; + } + + string toString() { + 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; + } +} + +/* +struct Segment { + private { + Point _begin, _end; + } +} + +struct Line { + private { + Point _point; + Vector _gradien; + } +} +*/