1 /* 2 * Copyright (c) 2016 Martin Davis. 3 * 4 * All rights reserved. This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * and Eclipse Distribution License v. 1.0 which accompanies this distribution. 7 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html 8 * and the Eclipse Distribution License is available at 9 * 10 * http://www.eclipse.org/org/documents/edl-v10.php. 11 */ 12 13 package org.locationtech.jts.math; 14 15 import org.locationtech.jts.geom.Coordinate; 16 17 /** 18 * Represents a vector in 3-dimensional Cartesian space. 19 * 20 * @author mdavis 21 * 22 */ 23 public class Vector3D { 24 25 /** 26 * Computes the dot product of the 3D vectors AB and CD. 27 * 28 * @param A the start point of the first vector 29 * @param B the end point of the first vector 30 * @param C the start point of the second vector 31 * @param D the end point of the second vector 32 * @return the dot product 33 */ dot(Coordinate A, Coordinate B, Coordinate C, Coordinate D)34 public static double dot(Coordinate A, Coordinate B, Coordinate C, Coordinate D) 35 { 36 double ABx = B.x - A.x; 37 double ABy = B.y - A.y; 38 double ABz = B.getZ() - A.getZ(); 39 double CDx = D.x - C.x; 40 double CDy = D.y - C.y; 41 double CDz = D.getZ() - C.getZ(); 42 return ABx*CDx + ABy*CDy + ABz*CDz; 43 } 44 45 /** 46 * Creates a new vector with given X, Y and Z components. 47 * 48 * @param x the X component 49 * @param y the Y component 50 * @param z the Z component 51 * @return a new vector 52 */ create(double x, double y, double z)53 public static Vector3D create(double x, double y, double z) { 54 return new Vector3D(x, y, z); 55 } 56 57 /** 58 * Creates a vector from a 3D {@link Coordinate}. 59 * The coordinate should have the 60 * X,Y and Z ordinates specified. 61 * 62 * @param coord the Coordinate to copy 63 * @return a new vector 64 */ create(Coordinate coord)65 public static Vector3D create(Coordinate coord) { 66 return new Vector3D(coord); 67 } 68 69 /** 70 * Computes the 3D dot-product of two {@link Coordinate}s. 71 * 72 * @param v1 the first vector 73 * @param v2 the second vector 74 * @return the dot product of the vectors 75 */ dot(Coordinate v1, Coordinate v2)76 public static double dot(Coordinate v1, Coordinate v2) { 77 return v1.x * v2.x + v1.y * v2.y + v1.getZ() * v2.getZ(); 78 } 79 80 private double x; 81 private double y; 82 private double z; 83 84 /** 85 * Creates a new 3D vector from a {@link Coordinate}. The coordinate should have 86 * the X,Y and Z ordinates specified. 87 * 88 * @param coord the Coordinate to copy 89 * @return a new vector 90 */ Vector3D(Coordinate v)91 public Vector3D(Coordinate v) { 92 x = v.x; 93 y = v.y; 94 z = v.getZ(); 95 } 96 97 /** 98 * Creates a vector with the direction and magnitude 99 * of the difference between the 100 * <tt>to</tt> and <tt>from</tt> {@link Coordinate}s. 101 * 102 * @param from the origin Coordinate 103 * @param to the destination Coordinate 104 * @return a new vector 105 */ Vector3D(Coordinate from, Coordinate to)106 public Vector3D(Coordinate from, Coordinate to) { 107 x = to.x - from.x; 108 y = to.y - from.y; 109 z = to.getZ() - from.getZ(); 110 } 111 112 /** 113 * Creates a vector with the givne components. 114 * 115 * @param x the X component 116 * @param y the Y component 117 * @param z the Z component 118 */ Vector3D(double x, double y, double z)119 public Vector3D(double x, double y, double z) { 120 this.x = x; 121 this.y = y; 122 this.z = z; 123 } 124 125 /** 126 * Gets the X component of this vector. 127 * 128 * @return the value of the X component 129 */ getX()130 public double getX() { 131 return x; 132 } 133 134 /** 135 * Gets the Y component of this vector. 136 * 137 * @return the value of the Y component 138 */ getY()139 public double getY() { 140 return y; 141 } 142 143 /** 144 * Gets the Z component of this vector. 145 * 146 * @return the value of the Z component 147 */ getZ()148 public double getZ() { 149 return z; 150 } 151 152 /** 153 * Computes a vector which is the sum 154 * of this vector and the given vector. 155 * 156 * @param v the vector to add 157 * @return the sum of this and <code>v</code> 158 */ add(Vector3D v)159 public Vector3D add(Vector3D v) { 160 return create(x + v.x, y + v.y, z + v.z); 161 } 162 163 /** 164 * Computes a vector which is the difference 165 * of this vector and the given vector. 166 * 167 * @param v the vector to subtract 168 * @return the difference of this and <code>v</code> 169 */ subtract(Vector3D v)170 public Vector3D subtract(Vector3D v) { 171 return create(x - v.x, y - v.y, z - v.z); 172 } 173 174 /** 175 * Creates a new vector which has the same direction 176 * and with length equals to the length of this vector 177 * divided by the scalar value <code>d</code>. 178 * 179 * @param d the scalar divisor 180 * @return a new vector with divided length 181 */ divide(double d)182 public Vector3D divide(double d) { 183 return create(x / d, y / d, z / d); 184 } 185 186 /** 187 * Computes the dot-product of two vectors 188 * 189 * @param v a vector 190 * @return the dot product of the vectors 191 */ dot(Vector3D v)192 public double dot(Vector3D v) { 193 return x * v.x + y * v.y + z * v.z; 194 } 195 196 /** 197 * Computes the length of this vector. 198 * 199 * @return the length of the vector 200 */ length()201 public double length() { 202 return Math.sqrt(x * x + y * y + z * z); 203 } 204 205 /** 206 * Computes the length of a vector. 207 * 208 * @param v a coordinate representing a 3D vector 209 * @return the length of the vector 210 */ length(Coordinate v)211 public static double length(Coordinate v) { 212 return Math.sqrt(v.x * v.x + v.y * v.y + v.getZ() * v.getZ()); 213 } 214 215 /** 216 * Computes a vector having identical direction 217 * but normalized to have length 1. 218 * 219 * @return a new normalized vector 220 */ normalize()221 public Vector3D normalize() { 222 double length = length(); 223 if (length > 0.0) 224 return divide(length()); 225 return create(0.0, 0.0, 0.0); 226 } 227 228 /** 229 * Computes a vector having identical direction 230 * but normalized to have length 1. 231 * 232 * @param v a coordinate representing a 3D vector 233 * @return a coordinate representing the normalized vector 234 */ normalize(Coordinate v)235 public static Coordinate normalize(Coordinate v) { 236 double len = length(v); 237 return new Coordinate(v.x / len, v.y / len, v.getZ() / len); 238 } 239 240 /** 241 * Gets a string representation of this vector 242 * 243 * @return a string representing this vector 244 */ toString()245 public String toString() { 246 return "[" + x + ", " + y + ", " + z + "]"; 247 } 248 249 /** 250 * Tests if a vector <tt>o</tt> has the same values for the components. 251 * 252 * @param o a <tt>Vector3D</tt> with which to do the comparison. 253 * @return true if <tt>other</tt> is a <tt>Vector3D</tt> with the same values 254 * for the x and y components. 255 */ equals(Object o)256 public boolean equals(Object o) { 257 if ( !(o instanceof Vector3D) ) { 258 return false; 259 } 260 Vector3D v = (Vector3D) o; 261 return x == v.x && y == v.y && z == v.z; 262 } 263 264 /** 265 * Gets a hashcode for this vector. 266 * 267 * @return a hashcode for this vector 268 */ hashCode()269 public int hashCode() { 270 // Algorithm from Effective Java by Joshua Bloch 271 int result = 17; 272 result = 37 * result + Coordinate.hashCode(x); 273 result = 37 * result + Coordinate.hashCode(y); 274 result = 37 * result + Coordinate.hashCode(z); 275 return result; 276 } 277 278 } 279