//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Revit.SDK.Samples.ObjectViewer.CS
{
///
/// Point class use to store point coordinate value
/// and get the value via (x, y ,z)property
///
public struct Vector
{
//private member
private double m_x; //x coordinate of vector
private double m_y; //y coordinate of vector
private double m_z; //z coordinate of vector
///
/// Property to get X coordinate
///
public double X
{
get
{
return m_x;
}
set
{
m_x = value;
}
}
///
/// Property to get Y coordinate
///
public double Y
{
get
{
return m_y;
}
set
{
m_y = value;
}
}
///
/// Property to get Z coordinate
///
public double Z
{
get
{
return m_z;
}
set
{
m_z = value;
}
}
///
/// Property to get x, y, z coordinate bu index 1, 2, 3
///
public double this[int index]
{
get
{
switch (index)
{
case 0:
return m_x;
case 1:
return m_y;
case 2:
return m_z;
default:
throw new ArgumentOutOfRangeException();
}
}
set
{
switch (index)
{
case 0:
m_x = value;
break;
case 1:
m_y = value;
break;
case 2:
m_z = value;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
///
/// copy constructor
///
public Vector(Vector rhs)
{
m_x = rhs.X;
m_y = rhs.Y;
m_z = rhs.Z;
}
///
/// constructor
///
/// x coordinate of point
/// y coordinate of point
/// z coordinate of point
public Vector(double x, double y, double z)
{
m_x = x;
m_y = y;
m_z = z;
}
///
/// get Normal by vector
///
public Vector GetNormal()
{
Vector direct = new Vector();
double len = GetLength();
if (len < double.Epsilon)
{
return new Vector();
}
direct.X = m_x / len;
direct.Y = m_y / len;
direct.Z = m_z / len;
return direct;
}
///
/// add two vector
///
/// first vector
/// second vector
/// add two vector
public static Vector operator +(Vector lhs, Vector rhs)
{
Vector result = new Vector(lhs);
result.X += rhs.X;
result.Y += rhs.Y;
result.Z += rhs.Z;
return result;
}
///
/// subtraction of two vector
///
/// first vector
/// second vector
/// subtraction of two vector
public static Vector operator -(Vector lhs, Vector rhs)
{
Vector result = new Vector(lhs);
result.X -= rhs.X;
result.Y -= rhs.Y;
result.Z -= rhs.Z;
return result;
}
///
/// negative of vector
///
/// vector
/// negative of vector
public static Vector operator -(Vector lhs)
{
Vector result = new Vector(lhs);
result.X = -lhs.X;
result.Y = -lhs.Y;
result.Z = -lhs.Z;
return result;
}
///
/// get normal vector of two vector
///
/// first vector
/// second vector
/// normal vector of two vector
public static Vector operator &(Vector lhs, Vector rhs)
{
double v1 = lhs.X;
double v2 = lhs.Y;
double v3 = lhs.Z;
double u1 = rhs.X;
double u2 = rhs.Y;
double u3 = rhs.Z;
double x = v2 * u3 - v3 * u2;
double y = v3 * u1 - v1 * u3;
double z = v1 * u2 - v2 * u1;
return new Vector(x, y, z);
}
///
/// get cross vector of two vector
///
/// first vector
/// second vector
/// cross vector of two vector
public static double operator *(Vector lhs, Vector rhs)
{
return lhs.X * rhs.X + lhs.Y * rhs.Y + lhs.Z * rhs.Z;
}
///
/// get vector multiply by an double value
///
/// vector
/// double value
/// vector multiply by an double value
public static Vector operator *(Vector lhs, double rhs)
{
return new Vector(lhs.X * rhs, lhs.Y * rhs, lhs.Z * rhs);
}
///
/// estimate whether two are unequal
///
/// first vector
/// second vector
/// whether two are unequal
public static bool operator !=(Vector lhs, Vector rhs)
{
return !IsEqual(lhs, rhs);
}
///
/// estimate whether two are equal
///
/// first vector
/// second vector
/// whether two are equal
public static bool operator ==(Vector lhs, Vector rhs)
{
return IsEqual(lhs, rhs);
}
///
/// get the length of vector
///
/// vector
/// length of vector
public static double operator ~(Vector lhs)
{
return lhs.GetLength();
}
///
/// get vector divided by an double value
///
/// vector
/// double value
/// vector divided by an double value
public static Vector operator /(Vector lhs, double rhs)
{
return new Vector(lhs.m_x / rhs, lhs.m_y / rhs, lhs.m_z / rhs);
}
///
/// get angle of two vector
///
/// first vector
/// second vector
///
/// indicate whether get the acute angle of two angles between two vectors
///
/// angle of two vector
public static double GetAngleOf2Vectors(Vector lhs, Vector rhs, bool acuteAngleDesired)
{
double angle = Math.Acos(lhs.GetNormal() * rhs.GetNormal());
if (acuteAngleDesired && angle > Math.PI / 2)
{
angle = Math.PI - angle;
}
return angle;
}
///
/// estimate whether two are equal
///
/// object which compare with
/// whether two are equal
public override bool Equals(object obj)
{
try
{
Vector rhs = (Vector)obj;
return IsEqual(this, rhs);
}
catch
{
}
return false;
}
///
/// Get HashCode
///
public override int GetHashCode()
{
return m_x.GetHashCode() ^ m_y.GetHashCode() ^ m_z.GetHashCode();
}
///
/// Get Length of vector
///
public double GetLength()
{
return Math.Sqrt(m_x*m_x + m_y*m_y + m_z*m_z);
}
///
/// estimate whether two vector are equal
///
/// first vector
/// second vector
/// whether two are equal
private static bool IsEqual(Vector lhs, Vector rhs)
{
if (lhs.X == rhs.X && lhs.X == rhs.X && lhs.X == rhs.X)
{
return true;
}
else
{
return false;
}
}
///
/// Cross multiply 2 3*3 Matrix
///
///
///
/// result 3*3 Matrix
public static Vector[] MultiCross3X3Matrix(Vector[] m1, Vector[] m2)
{
Vector[] result = new Vector[3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
switch (j)
{
case 0:
(result[i]).X += (m1[i])[k] * (m2[k])[j];
break;
case 1:
(result[i]).Y += (m1[i])[k] * (m2[k])[j];
break;
case 2:
(result[i]).Z += (m1[i])[k] * (m2[k])[j];
break;
default:
break;
}
}
}
}
return result;
}
}
}