/*Title: mjbWorld
Copyright (c) 1998-2007 Martin John BakerThis program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.For information about the GNU General Public License see http://www.gnu.org/To discuss this program http://sourceforge.net/forum/forum.php?forum_id=122133 also see website https://www.euclideanspace.com/ */ /* for theory see: https://www.euclideanspace.com/maths/algebra/vectors/index.htm */namespace mjbModel { using System; using System.ComponentModel; using System.IO; using System.Collections; using System.Reflection; using System.Text; using System.Xml;/// <summary> /// This class can represent a 3D vector. For instance a point in 3D space, or /// a relative position or movement. /// /// The class has methods to add, subtact, (cross and dot) multiply with other /// vectors. also many other methods, including the ability to load and save /// to from VRML and x3d /// </summary> class sfvec3f : property { /// <summary> /// VRML only supports float but allow override if higher resolution required /// </summary> public static bool saveAsDouble = false ; /// <summary> /// x coordinate /// </summary> public double x; /// <summary> /// y coordinate /// </summary> public double y; /// <summary> /// z coordinate /// </summary> public double z;/// <summary> /// a constructor to set initial values of x,y and z coodinates /// </summary> /// <param name="x1">value of x coordinate</param> /// <param name="y1">value of y coordinate</param> /// <param name="z1">value of z coordinate</param> public sfvec3f(double x1,double y1,double z1) { x=x1; y=y1; z=z1; }/// <summary> /// copy constructor /// </summary> /// <param name="in1">set values to save value in1</param> public sfvec3f(sfvec3f in1) { x=(in1!=null) ? in1.x : 0; y= (in1!=null) ? in1.y : 0; z= (in1!=null) ? in1.z : 1; }/// <summary> /// construct a vector with initial value zero. /// </summary> public sfvec3f() { }/// <summary> /// static method to return sum of two vectors /// </summary> /// <param name="a">first vector to be added</param> /// <param name="b">second vector to be added</param> /// <returns>the sum</returns> public static sfvec3f add(sfvec3f a,sfvec3f b){ return new sfvec3f(a.x + b.x,a.y + b.y,a.z + b.z); }/// <summary> /// static method to return difference of two vectors /// </summary> /// <param name="a">first vector</param> /// <param name="b">subract this vector</param> /// <returns>result</returns> public static sfvec3f sub(sfvec3f a,sfvec3f b){ return new sfvec3f(a.x - b.x,a.y - b.y,a.z - b.z); }/// <summary> /// static method to give the VRML name of this vector /// </summary> /// <returns></returns> public static string vrmlType_s(){ return "SFVec3f"; }/// <summary> /// method to give the VRML name of this vector /// sometimes we cant use vrmlType_s because static methods cant be overriden /// </summary> /// <returns></returns> public override string vrmlType(){ return "SFVec3f"; }/// <summary> /// finds the type of a class which can edit this property /// </summary> /// <returns>editor</returns> public static Type getEditClass(){ return typeof(sfvec3fEditor); }/// <summary> /// overrides base clone method /// </summary> /// <returns>new instance with same value of this</returns> public override property clone() { return new sfvec3f(this); }/// <summary> /// set the value of this instance to the value of other /// this can be used to reuse an instance without the overheads of garbidge collection /// </summary> /// <param name="other">instace we want to use value of, if null then set to zero</param> public void copy(sfvec3f other){ if (other==null) { x=y=z=0; return; } x= other.x; y= other.y; z= other.z; }/// <summary> /// subtract other vector from this /// for theory see: /// https://www.euclideanspace.com/maths/algebra/vectors/index.htm /// </summary> /// <param name="other">vector to be subtracted from this</param> public void sub(sfvec3f other){ if (other==null) return; x-= other.x; y-= other.y; z-= other.z; }/// <summary> /// add other vector to this /// for theory see: /// https://www.euclideanspace.com/maths/algebra/vectors/index.htm /// </summary> /// <param name="other">vector to be added to this</param> public void add(sfvec3f other){ if (other==null) return; x+= other.x; y+= other.y; z+= other.z; }/// <summary> /// convert this vector to unit length /// for theory see: /// https://www.euclideanspace.com/maths/algebra/vectors/normals/index.htm /// </summary> public void normalize(){ double t = Math.Sqrt(x*x + y*y + z*z); x /= t; y /= t; z /= t; }/// <summary> /// scale this vector equally in all directions /// </summary> /// <param name="sc">scale factor</param> public void scale(double sc){ x *= sc; y *= sc; z *= sc; }/// <summary> /// scale this vector posibly different in x,y and z directions /// </summary> /// <param name="other">scale value</param> public void scale(sfvec3f other){ x *= other.x; y *= other.y; z *= other.z; }/// <summary> /// scale this vector by inverse of other /// </summary> /// <param name="other">scale value</param> public void scaleInv(sfvec3f other){ x /= other.x; y /= other.y; z /= other.z; }/// <summary> /// return square of distance from end of this vector to end of other /// </summary> /// <param name="other">calcules distance from this vector</param> /// <returns>square of distance from end of this vector to end of other</returns> public double distanceSquared(sfvec3f other){ double x1 = other.x - x; double y1 = other.y - y; double z1 = other.z - z; return x1*x1 + y1*y1 + z1*z1; }/// <summary> /// cross product /// for theory see: /// https://www.euclideanspace.com/maths/algebra/vectors/index.htm /// </summary> /// <param name="other">other vector to take cross product with</param> public void cross(sfvec3f other) { double xh = y * other.z - other.y * z; double yh = z * other.x - other.z * x; double zh = x * other.y - other.x * y; x = xh; y = yh; z = zh; }/// <summary> /// dot product /// for theory see: /// https://www.euclideanspace.com/maths/algebra/vectors/index.htm /// </summary> /// <param name="other">vector to take dot product with</param> /// <returns>dot product</returns> public double dot(sfvec3f other) { return (x * other.x) + (y * other.y) + (z * other.z); }/// <summary> /// create an array of the appropriate type /// with a size given by the parameter /// </summary> /// <param name="size">array size</param> /// <returns>new instance of sfvec3f array</returns> public override property[] createArray(int size){ return new sfvec3f[size]; }/// <summary> /// set the x value only without althering the other dimensions /// </summary> /// <param name="v">new value for x</param> public void setX(double v) { x=v; }/// <summary> /// set the y value only without althering the other dimensions /// </summary> /// <param name="v">new value for y</param> public void setY(double v) { y=v; }/// <summary> /// set the z value only without althering the other dimensions /// </summary> /// <param name="v">new value for z</param> public void setZ(double v) { z=v; }/// <summary> /// gets the value in the x dimension /// </summary> /// <returns>the value in the x dimension</returns> public double getx() { return x; }/// <summary> /// gets the value in the y dimension /// </summary> /// <returns>the value in the y dimension</returns> public double gety() { return y; }/// <summary> /// gets the value in the z dimension /// </summary> /// <returns>the value in the z dimension</returns> public double getz() { return z; }/// <summary> /// inverts the direction of the vector /// </summary> public void minus() { x=-x; y=-y; z=-z; }/// <summary> /// return a vector pointing on the opposite direction to this without affecting the /// value of this instance /// </summary> /// <returns></returns> public sfvec3f getMinus() { return new sfvec3f(-x,-y,-z); }/// <summary> /// return a string which represents the value which can be used in source code /// </summary> /// <returns></returns> public String toStatic() { return String.Concat(x.ToString(),"f,", y.ToString(),"f,", z.ToString(),"f"); }/// <summary> /// output the value of this vector as a string, values are separated by commas and /// enclosed in brackets /// </summary> /// <returns>a string representing the value of this</returns> public override string ToString() { return String.Concat("(",x.ToString(),",", y.ToString(),",", z.ToString(),")"); }/// <summary> /// returns true if any dimension of other vector is greater than the same dimension /// of this /// </summary> /// <param name="other">vector to compare with this</param> /// <returns>true if greater</returns> public bool greaterThan(sfvec3f other) { if (other.x > x) return true; if (other.y > y) return true; if (other.z > z) return true; return false; }/// <summary> /// returns true if any dimension of other vector is less than the same dimension /// of this /// </summary> /// <param name="other">vector to compare with this</param> /// <returns>true if less</returns> public bool lessThan(sfvec3f other) { if (other.x < x) return true; if (other.y < y) return true; if (other.z < z) return true; return false; }/// <summary> /// returns true if this vector has an equal value to other vector /// </summary> /// <param name="v2"></param> /// <returns></returns> public bool Equals(sfvec3f other) { if (other==null) return false; if (x!= other.x) return false; if (y!= other.y) return false; if (z!= other.z) return false; return true; }/// <summary> /// calcultes new translation when combining translations /// /// Rt = Ra Rb /// Ct = Cb /// Tt = Ra (Cb + Tb - Ca) + Ca + Ta - Cb /// /// for theory: /// https://www.euclideanspace.com/maths/geometry/rotations/rotationAndTranslation/nonMatrix/index.htm /// </summary> /// <param name="ta">Ta = translation of transform a in absolute coordinates</param> /// <param name="ra">Ra = rotation function of transform a in absolute coordinates</param> /// <param name="ca">Ca = centre of rotation of transform a in absolute coordinates</param> /// <param name="tb">Tb = translation of transform b in coordinates of transform a</param> /// <param name="cb">Cb = centre of rotation of transform b in coordinates of transform a</param> /// <returns>Tt total offset</returns> public sfvec3f rotationOffset(sfvec3f ta,sfrotation ra,sfvec3f ca,sfvec3f tb,sfvec3f cb) { sfvec3f result = new sfvec3f(cb); result.add(tb); result.sub(ca); if (ra != null) ra.transform(result); result.add(ca); result.add(ta); result.sub(cb); return result; }/// <summary> /// use to combine bounds /// if i=0 take minimum otherwise maximum /// </summary> /// <param name="other">vector to combine with</param> /// <param name="i">if i=0 take minimum otherwise maximum</param> public void bounds(sfvec3f other,int i){ if (i==0) { // take minimum if (other.x < x) x=other.x; if (other.y < y) y=other.y; if (other.z < z) z=other.z; } else { // take maximum if (other.x > x) x=other.x; if (other.y > y) y=other.y; if (other.z > z) z=other.z; } }/// <summary> /// used when reading XML /// called by sfparam which is called by mfparam which is called by filter_x3d /// </summary> /// <param name="val">expects val to be in following format (1.0 2.0 3.0)</param> /// <param name="type">not used</param> public override void setAttribute(string val,string type){ try { string[] tokens=val.Split("() \t\n\r\f".ToCharArray()); //Console.WriteLine("sfvec3f.setAttribute({0},{1}) x={2} y={3} z={4}",val,type,tokens[0],tokens[1],tokens[2]); int offset=0; while (tokens[offset].Equals("")) offset++; /* for (int t=0;t<tokens.Length;t++) { char[] c=tokens[t].ToCharArray(); Console.Write("sfrotation.setAttribute("+val+","+type+") offset"+offset+" t="+t); for (int p=0;p<c.Length;p++){ int i0 =(int)c[p]; Console.Write(" "+i0); } Console.WriteLine(""); }*/ x = Double.Parse(tokens[offset]); y = Double.Parse(tokens[offset+1]); z = Double.Parse(tokens[offset+2]); } catch (Exception e){ Console.WriteLine("sfvec3f.setAttribute("+val+","+type+") " + e); } }/// <summary> /// output as a string /// </summary> /// <param name="format">mode values /// 0 - output modified values /// 1 - output original values /// 2 - output attribute /// 3 - output attribute in brackets /// 4 - output with f prefix</param> /// <returns>string result</returns> public override string outstring(int format) { if (format == 3) { if (saveAsDouble) return String.Concat("(",x.ToString()," ", y.ToString()," ", z.ToString(),")"); else return String.Concat("(",((float)x).ToString()," ", ((float)y).ToString()," ", ((float)z).ToString(),")"); } else if (format == 4) { return String.Concat(((float)x).ToString(),"f,", ((float)y).ToString() , "f," , ((float)z).ToString() , "f"); } else { if (saveAsDouble) return String.Concat(x.ToString()," ", y.ToString()," ", z.ToString()); else return String.Concat(((float)x).ToString()," ", ((float)y).ToString()," ", ((float)z).ToString()); } }/// <summary> /// write to file /// </summary> /// <param name="f">filter = information about output</param> /// <param name="mode">mode values /// 0 - output VRML97 modified values /// 1 - output VRML97 original values /// 2 - output xml (x3d) /// 3 - output attribute in brackets /// 4 - output with f prefix</param> /// <param name="indent"></param> public override void write(filter f,int mode,int indent){ if (mode == 3) { if (saveAsDouble) { f.write(String.Concat("(",x.ToString()," ", y.ToString()," ", z.ToString(),")")); return; } else { f.write(String.Concat("(",((float)x).ToString()," ", ((float)y).ToString()," ", ((float)z).ToString(),")")); return; } } else if (mode == 4) { f.write(String.Concat(x.ToString(),"f,", y.ToString(),"f,", z.ToString(),"f")); return; } else { if (saveAsDouble) { f.write(String.Concat(x.ToString()," ", y.ToString()," ", z.ToString())); return; } else f.write(String.Concat(((float)x).ToString()," ", ((float)y).ToString()," ", ((float)z).ToString())); } // f->write(outstring(mode)); }/// <summary> /// read SFVec3f value from VRML file /// used by mfparam.vrml2par /// </summary> /// <param name="f"></param> /// <param name="sfp"></param> /// <param name="n"></param> /// <param name="mode"></param> /// <returns></returns> public override bool instring(filter f,sfparam sfp,nodeBean n,int mode) { String s; s=f.nextToken(); if (s!=null) if (s.Equals("IS")) { s=f.nextToken(); if (sfp!=null) sfp.setIs(s); return true; } x = Single.Parse(s); s=f.nextToken(); y = Single.Parse(s); s=f.nextToken(); z = Single.Parse(s); return true; }/// <summary> /// read from a string /// used by mfvec3f.instring /// </summary> /// <param name="f"></param> /// <param name="s1"></param> /// <returns></returns> public bool instring(filter f,String s1) { String s; x = Single.Parse(s1); s=f.nextToken(); y = Single.Parse(s); s=f.nextToken(); z = Single.Parse(s); return true; } } // class } //namespace mjbModel
metadata block |
|
see also: |
|
Correspondence about this page | |
Book Shop - Further reading. Where I can, I have put links to Amazon for books that are relevant to the subject, click on the appropriate country flag to get more details of the book or to buy it from them. |
Mathematics for 3D game Programming - Includes introduction to Vectors, Matrices, Transforms and Trigonometry. (But no euler angles or quaternions). Also includes ray tracing and some linear & rotational physics also collision detection (but not collision response). |
Terminology and Notation Specific to this page here: |
|
This site may have errors. Don't use for critical systems.
Copyright (c) 1998-2023 Martin John Baker - All rights reserved - privacy policy.