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;
+    }
+}
+*/