Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- Copyright (c) 2013, w0rp <moebiuspesona@gmail.com>
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- module geometry.Point;
- enum Axis: byte
- {
- X,
- Y,
- Z
- }
- struct Point
- {
- public real x = 0.0;
- public real y = 0.0;
- public real z = 0.0;
- /**
- @brief Compute the square of the norm.
- Compute the norm without applying the square root operation.
- @param The square of the norm.
- */
- public @property const pure nothrow
- real sq_norm()
- {
- return this.x ^^ 2 + this.y ^^ 2 + this.z ^^ 2;
- }
- /**
- @brief Compute the Euclidean norm of this point.
- @return The norm.
- */
- public @property const pure nothrow
- real norm()
- {
- return sqrt(this.sq_norm);
- }
- /**
- @brief Normalize this vector to get a unit vector.
- @return The normalized vector.
- */
- public @property const pure nothrow
- Point normalize()
- {
- return this / this.norm;
- }
- public pure const nothrow
- Point opUnary(string s)() if (s == "-")
- {
- return Point(-this.x, -this.y, -this.z);
- }
- unittest
- {
- Point p = {1, 2, 3};
- Point q = -p;
- assert(-p.x == q.x);
- assert(-p.y == q.y);
- assert(-p.z == q.z);
- }
- public pure const nothrow
- bool opEquals(in Point other)
- {
- return approxEqual(this.x, other.x)
- && approxEqual(this.y, other.y)
- && approxEqual(this.z, other.z);
- }
- unittest
- {
- Point p = {1, 2, 3};
- Point q = {1, 2, 3};
- assert(p == q);
- Point r = {2, 3, 4};
- assert (p != r);
- }
- public pure const nothrow
- Point opBinary(string s)(in Point other) if (s == "+")
- {
- return Point(this.x + other.x, this.y + other.y, this.z + other.z);
- }
- unittest
- {
- Point p = {1, 2, 3};
- Point q = {1, 2, 3};
- Point r = p + q;
- assert(r.x == 2);
- assert(r.y == 4);
- assert(r.z == 6);
- }
- public pure const nothrow
- Point opBinary(string s)(in Point other) if (s == "-")
- {
- return Point(this.x - other.x, this.y - other.y, this.z - other.z);
- }
- unittest
- {
- Point p = {1, 2, 3};
- Point q = {1, 2, 3};
- Point r = p - q;
- assert(r.x == 0);
- assert(r.y == 0);
- assert(r.z == 0);
- }
- // Scalar multiplication.
- public pure const nothrow
- Point opBinary(string s)(in real scalar) if (s == "*")
- {
- return Point(this.x * scalar, this.y * scalar, this.z * scalar);
- }
- public pure const nothrow
- Point opBinaryRight(string s)(in real scalar) if (s == "*")
- {
- return this * scalar;
- }
- unittest
- {
- Point p = {1, 2, 3};
- Point q = p * 2;
- Point r = 2 * p;
- assert(q.x == 2);
- assert(q.y == 4);
- assert(q.z == 6);
- assert(q.x == r.x);
- assert(q.y == r.y);
- assert(q.z == r.z);
- }
- // Dot product.
- public pure const nothrow
- real opBinary(string s)(in Point other) if (s == "*")
- {
- return this.x * other.x + this.y * other.y + this.z * other.z;
- }
- unittest
- {
- Point p = {1, 2, 3};
- Point q = {4, 5, 6};
- assert(p * q == 32);
- }
- // Scalar divison.
- public pure const nothrow
- Point opBinary(string s)(in real scalar) if (s == "/")
- {
- return Point(this.x / scalar, this.y / scalar, this.z / scalar);
- }
- unittest
- {
- Point p = {2, 4, 6};
- Point q = p / 2;
- assert(q.x == 1);
- assert(q.y == 2);
- assert(q.z == 3);
- }
- // Scalar exponentiation.
- public pure const nothrow
- Point opBinary(string s)(in real scalar) if (s == "^^")
- {
- return Point(this.x ^^ scalar, this.y ^^ scalar, this.z ^^ scalar);
- }
- unittest
- {
- Point p = {1, 2, 3};
- Point q = p ^^ 2;
- assert(q.x == 1);
- assert(q.y == 4);
- assert(q.z == 9);
- }
- public pure nothrow
- void opOpAssign(string s)(in real scalar) if (s == "+")
- {
- this.x += scalar;
- this.y += scalar;
- this.z += scalar;
- }
- unittest
- {
- Point p = {1, 2, 3};
- p += 1;
- assert(p.x == 2);
- assert(p.y == 3);
- assert(p.z == 4);
- }
- public pure nothrow
- void opOpAssign(string s)(in Point other) if (s == "+")
- {
- this.x += other.x;
- this.y += other.y;
- this.z += other.z;
- }
- unittest
- {
- Point p = {1, 2, 3};
- Point q = {4, 5, 6};
- p += q;
- assert(p.x == 5);
- assert(p.y == 7);
- assert(p.z == 9);
- }
- public pure nothrow
- void opOpAssign(string s)(in real scalar) if (s == "-")
- {
- this.x -= scalar;
- this.y -= scalar;
- this.z -= scalar;
- }
- unittest
- {
- Point p = {1, 2, 3};
- p -= 1;
- assert(p.x == 0);
- assert(p.y == 1);
- assert(p.z == 2);
- }
- public pure nothrow
- void opOpAssign(string s)(in Point other) if (s == "-")
- {
- this.x -= other.x;
- this.y -= other.y;
- this.z -= other.z;
- }
- unittest
- {
- Point p = {2, 4, 6};
- Point q = {1, 2, 3};
- p -= q;
- assert(p.x == 1);
- assert(p.y == 2);
- assert(p.z == 3);
- }
- public pure nothrow
- void opOpAssign(string s)(in real scalar) if (s == "*")
- {
- this.x *= scalar;
- this.y *= scalar;
- this.z *= scalar;
- }
- unittest
- {
- Point p = {1, 2, 3};
- p *= 2;
- assert(p.x == 2);
- assert(p.y == 4);
- assert(p.z == 6);
- }
- public pure nothrow
- void opOpAssign(string s)(in real scalar) if (s == "/")
- {
- this.x /= scalar;
- this.y /= scalar;
- this.z /= scalar;
- }
- unittest
- {
- Point p = {2, 4, 6};
- p /= 2;
- assert(p.x == 1);
- assert(p.y == 2);
- assert(p.z == 3);
- }
- public pure nothrow
- void opOpAssign(string s)(in real scalar) if (s == "^^")
- {
- this.x ^^= scalar;
- this.y ^^= scalar;
- this.z ^^= scalar;
- }
- unittest
- {
- Point p = {1, 2, 3};
- p ^^= 2;
- assert(p.x == 1);
- assert(p.y == 4);
- assert(p.z == 9);
- }
- }
- /**
- @brief Compute the cross product of this point and another.
- @param other The second point.
- @return The product.
- */
- pure nothrow
- Point cross(in Point left, in Point right)
- {
- Point p;
- p.x = left.y * right.z - left.z * right.y;
- p.y = left.z * right.x - left.x * right.z;
- p.z = left.x * right.y - left.y * right.x;
- return p;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement