view tk/geometry.d @ 4:58a8ad20b228

Ooops, this got left out of previous commit
author David Bryant <daveb@acres.com.au>
date Fri, 10 Jul 2009 15:26:07 +0930
parents
children 71ca82e0eb76
line wrap: on
line source

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;
    }
}