diff import/geometry.d @ 0:e907d2c54ec3

Initial import
author David Bryant <daveb@acres.com.au>
date Wed, 13 May 2009 15:42:39 +0930
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/import/geometry.d	Wed May 13 15:42:39 2009 +0930
@@ -0,0 +1,220 @@
+module interaction.geometry;
+
+private import std.math;
+
+private const double EPSILON = 1e-20;
+
+final class Point {
+    this() {
+        this(0.0, 0.0);
+    }
+
+    this(double x, double y) {
+        _x = x;
+        _y = y;
+    }
+
+    char[] toString() {
+        return "(" ~ std.string.toString(_x) ~ ", " ~ std.string.toString(_y) ~ ")";
+    }
+
+    Point opAdd(in Vector v) {
+        return new Point(_x + v._x, _y + v._y);
+    }
+
+    Vector opSub(in Point p) {
+        return new Vector(_x - p._x, _y - p._y);
+    }
+
+    double x() { return _x; }
+    double y() { return _y; }
+
+    private {
+        double _x;
+        double _y;
+    }
+}
+
+//
+
+final class Vector {
+    this() {
+        this(0.0, 0.0);
+    }
+
+    this(double x, double y) {
+        _x = x;
+        _y = y;
+    }
+
+    char[] toString() {
+        return "[" ~ std.string.toString(_x) ~ ", " ~ std.string.toString(_y) ~ "]";
+    }
+
+    Vector opAdd(in Vector v) {
+        return new Vector(_x + v._x, _y + v._y);
+    }
+
+    Vector opSub(in Vector v) {
+        return new Vector(_x - v._x, _y - v._y);
+    }
+
+    Vector opNeg() {
+        return new Vector(-_x, -_y);
+    }
+
+    Vector opMul_r(double d) {
+        return new Vector(d * _x, d * _y);
+    }
+
+    double length() {
+        return sqrt(_x * _x + _y * _y);
+    }
+
+    bool has_length() {
+        return _x * _x + _y * _y > EPSILON * EPSILON;
+    }
+
+    double x() { return _x; }
+    double y() { return _y; }
+
+    private {
+        double _x;
+        double _y;
+    }
+}
+
+//
+
+final class Segment {
+    this() {
+    }
+
+    this(Point start, Point end) {
+        _start = start;
+        _end = end;
+    }
+
+    Point start() { return _start; }
+    Point end() { return _end; }
+
+    private {
+        Point _start;
+        Point _end;
+    }
+}
+
+//
+
+final class Line {
+    this() {
+    }
+
+    this(Point point, Vector vector) {
+        assert(vector.has_length);
+        _point = point;
+        _vector = vector;
+    }
+
+    this(Point point1, Point point2) {
+        _point = point1;
+        _vector = point2 - point1;
+        assert(_vector.has_length);
+    }
+
+    private {
+        Point _point;
+        Vector _vector;
+    }
+}
+
+//
+
+final class Rectangle {
+    this() {
+        this(0.0, 0.0, 0.0, 0.0);
+    }
+
+    this(double x, double y, double w, double h) {
+        assert(w >= 0.0);
+        assert(h >= 0.0);
+        _x = x;
+        _y = y;
+        _w = w;
+        _h = h;
+    }
+
+    double x() { return _x; }
+    double y() { return _y; }
+    double w() { return _w; }
+    double h() { return _h; }
+    double xw() { return _x + _w; }
+    double yh() { return _y + _h; }
+
+    /*
+    Point corner00() { return new Point(_x,      _y     ); }
+    Point corner10() { return new Point(_x + _w, _y     ); }
+    Point corner11() { return new Point(_x + _w, _y + _h); }
+    Point corner01() { return new Point(_x,      _y + _h); }
+
+    Point centre() { return new Point(_x + _w / 2.0, _y + _h / 2.0); }
+    */
+
+    double area() {
+        return _w * _h;
+    }
+
+    bool has_area() {
+        return area > 0.0;
+    }
+
+    bool contains(Point point) {
+        return point.x > x && point.x < xw & point.y > y && point.y < xy;
+    }
+
+    bool contains(Segment segment) {
+        return contains(segment.start, segment.end);
+    }
+
+    private double _x, _y, _w, _h;
+}
+
+unittest {
+    const double absdiff = 1e-20, reldiff= 1e-20;
+
+    bool cmpdouble(in double lhs, in double rhs) {
+        double adiff = fabs(rhs - lhs);
+
+        if (adiff < absdiff && adiff > -absdiff) {
+            return true;
+        }
+
+        if (fabs(lhs) > absdiff && fabs(rhs) > absdiff) {
+            double rdiff = rhs / lhs;
+
+            if (rdiff < (1.0 + reldiff) && rdiff > 1.0 / (1.0 + reldiff)) {
+                return true;
+            }
+        }
+
+        // They must differ significantly
+
+        return false;
+    }
+
+    bool cmpvector(in Vector lhs, in Vector rhs) {
+        return cmpdouble(lhs._x, rhs._x) && cmpdouble(lhs._y, rhs._y);
+    }
+
+    bool cmppoint(in Point lhs, in Point rhs) {
+        return cmpdouble(lhs._x, rhs._x) && cmpdouble(lhs._y, rhs._y);
+    }
+
+    assert(cmpvector(new Vector(0.0, 0.0), new Vector));
+    assert(!cmpvector(new Vector(0.0, 1e-10), new Vector));
+    assert(cmpvector(new Vector(1.0, 2.0) + new Vector(3.0, 4.0), new Vector(4.0, 6.0)));
+    assert(cmpvector(new Vector(1.0, 2.0) - new Vector(3.0, 4.0), new Vector(-2.0, -2.0)));
+    assert(cmpvector(-(new Vector(1.0, 2.0)), new Vector(-1.0, -2.0)));
+    assert(cmpdouble((new Vector(3.0, 4.0)).length(), 5.0));
+    assert(cmpvector(3.0 * (new Vector(3.0, 4.0)), new Vector(9.0, 12.0)));
+}