001/*
002 * Renderer 4. The MIT License.
003 * Copyright (c) 2022 rlkraft@pnw.edu
004 * See LICENSE for details.
005*/
006
007package renderer.scene;
008
009/**
010   A {@code Vector} object holds three doubles, which makes it a vector
011   in 3-dimensional space.
012*/
013public final class Vector
014{
015   public final double x, y, z;
016
017   /**
018      Construct a new {@code Vector} using the given x, y, and z coordinates.
019
020      @param x  x-coordinate of the new {@code Vector}
021      @param y  y-coordinate of the new {@code Vector}
022      @param z  z-coordinate of the new {@code Vector}
023   */
024   public Vector(final double x, final double y, final double z)
025   {
026      this.x = x;
027      this.y = y;
028      this.z = z;
029   }
030
031
032   /**
033      Construct a new {@code Vector} from a {@link Vertex}.
034
035      @param v  {@link Vertex} object to convert into a {@code Vector}
036   */
037   public Vector(final Vertex v)
038   {
039      this(v.x, v.y, v.z);
040   }
041
042
043   /**
044      The dot-product of two {@code Vector}s returns a scalar.
045
046      @param v  {@code Vector} object to multiply with this {@code Vector}
047      @return a double that is the dot-product of this {@code Vector} and {@code v}
048   */
049   public double dotProduct(final Vector v)
050   {
051      return (x * v.x) + (y * v.y) + (z * v.z);
052   }
053
054
055   /**
056      The cross-product of two {@code Vector}s returns a (new) {@code Vector}.
057
058      @param v  {@code Vector} object to multiply with this {@code Vector}
059      @return a new {@code Vector} object that is the cross-product of this {@code Vector} and {@code v}
060   */
061   public Vector crossProduct(final Vector v)
062   {
063      return new Vector(y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x);
064   }
065
066
067   /**
068      A scalar times a {@code Vector} returns a (new) {@code Vector}.
069
070      @param s  number to multiply this {@code Vector} by
071      @return a new {@code Vector} object that is the scalar times this {@code Vector}
072   */
073   public Vector times(final double s) // return s * this
074   {
075      return new Vector(s*x, s*y, s*z);
076   }
077
078
079   /**
080      A {@code Vector} plus a {@code Vector} returns a (new) {@code Vector}.
081
082      @param v  {@code Vector} object to add to this {@code Vector}
083      @return a new {@code Vector} object that is the sum of this {@code Vector} and {@code v}
084   */
085   public Vector plus(final Vector v) // return this + v
086   {
087      return new Vector(x + v.x, y + v.y, z + v.z);
088   }
089
090
091   /**
092      A {@code Vector} minus a {@code Vector} returns a (new) {@code Vector}.
093
094      @param v  {@code Vector} object to subtract from this {@code Vector}
095      @return a new {@code Vector} object that is this {@code Vector} minus {@code v}
096   */
097   public Vector minus(final Vector v) // return this - v
098   {
099      return new Vector(x - v.x, y - v.y, z - v.z);
100   }
101
102
103   /**
104      Return the normalized version of this {@code Vector}.
105      <p>
106      That is, return the {@code Vector} with length 1 that
107      points in the same direction as this {@code Vector}.
108
109      @return a new {@code Vector} that has length one and has the same direction as this {@code Vector}
110   */
111   public Vector normalize() // return this / |this|
112   {
113      final double norm = Math.sqrt( x*x + y*y + z*z );
114      return new Vector(x/norm, y/norm, z/norm);
115   }
116
117
118   /**
119      A {@code Vector} plus a {@link Vertex} returns a (new) {@link Vertex}.
120      <p>
121      The vector translates the vertex to a new location.
122
123      @param v  {@link Vertex} object to add to this {@code Vector}
124      @return a new {@link Vertex} object that is the translation of {@code v} by this {@code Vector}
125   */
126   public Vertex plus(final Vertex v)
127   {
128      return new Vertex(x + v.x, y + v.y, z + v.z);
129   }
130
131
132   /**
133      For debugging.
134
135      @return {@link String} representation of this {@code Vector} object
136   */
137   @Override
138   public String toString()
139   {
140      final int precision = 5;  // the default precision for the format string
141      return toString(precision);
142   }
143
144
145   /**
146      For debugging.
147      <p>
148      Allow the precision of the formatted output to be specified.
149
150      @param precision  precision value for the format string
151      @return {@link String} representation of this {@code Vector} object
152   */
153   public String toString(final int precision)
154   {
155      final int iWidth = 3; // default width of integer part of the format string
156      return toString(precision, iWidth);
157   }
158
159
160   /**
161      For debugging.
162      <p>
163      Allow the precision and width of the formatted output to be specified.
164      By width, we mean the width of the integer part of each number.
165
166      @param precision  precision value for the format string
167      @param iWidth     width of the integer part of the format string
168      @return {@link String} representation of this {@code Vector} object
169   */
170   public String toString(final int precision, final int iWidth)
171   {
172      // Here is one way to get programmable precision and width.
173      final int p = precision;      // the precision for the following format string
174      final int t = p + iWidth + 2; // the width for the following format string
175      final String format = "[x,y,z] = [% "+t+"."+p+"f  % "+t+"."+p+"f  % "+t+"."+p+"f]";
176      return String.format(format, x, y, z);
177   }
178}