Net.Like.Xue.Tokyo/Assets/Plugins/Draw XXL/scripts/internal utilities/InternalDXXL_Plane.cs

288 lines
13 KiB
C#

namespace DrawXXL
{
using UnityEngine;
public class InternalDXXL_Plane
{
///plane equation: a*x + b*y + c*z = d
///meaning of the parameters:
/// x-axisInterception = d / a
/// y-axisInterception = d / b
/// z-axisInterception = d / c
/// a, b und c define the planes normal vector as (a,b,c)
/// a = inverse of x-axisInterception * d
/// b = inverse of y-axisInterception * d
/// c = inverse of z-axisInterception * d
/// d = perpendicular distance to origin?
public float a;
public float b;
public float c;
public float d;
public Vector3 normalDir; //not necessarily normalized
//not defined for every plane:
Vector3 triangleMountingPoint;
Vector3 triangleMountingPoint_toFirstTriangleCorner;
Vector3 triangleMountingPoint_toSecondTriangleCorner;
//saving GC.Alloc:
public static InternalDXXL_Plane horizPlane_throughZeroOrigin = new InternalDXXL_Plane(Vector3.zero, Vector3.up);
public static InternalDXXL_Plane xyPlane_throughZeroOrigin = new InternalDXXL_Plane(Vector3.zero, Vector3.forward);
public static InternalDXXL_Plane zyPlane_throughZeroOrigin = new InternalDXXL_Plane(Vector3.zero, Vector3.right);
public void Recreate(Vector3 point1, Vector3 point2, Vector3 point3)
{
triangleMountingPoint = point1;
triangleMountingPoint_toFirstTriangleCorner = point2 - point1;
triangleMountingPoint_toSecondTriangleCorner = point3 - point1;
normalDir = Vector3.Cross(triangleMountingPoint_toFirstTriangleCorner, triangleMountingPoint_toSecondTriangleCorner);
normalDir = UtilitiesDXXL_Math.ScaleNonZeroVectorIntoRegionOfFloatPrecision(normalDir);
a = normalDir.x;
b = normalDir.y;
c = normalDir.z;
d = triangleMountingPoint.x * a + triangleMountingPoint.y * b + triangleMountingPoint.z * c;
ErrorLogForInvalidPlanes();
}
public void Recreate(Vector3 point1, Vector3 point2, Vector3 point3, bool skipErrorOfNonValidPlane)
{
triangleMountingPoint = point1;
triangleMountingPoint_toFirstTriangleCorner = point2 - point1;
triangleMountingPoint_toSecondTriangleCorner = point3 - point1;
normalDir = Vector3.Cross(triangleMountingPoint_toFirstTriangleCorner, triangleMountingPoint_toSecondTriangleCorner);
normalDir = UtilitiesDXXL_Math.ScaleNonZeroVectorIntoRegionOfFloatPrecision(normalDir);
a = normalDir.x;
b = normalDir.y;
c = normalDir.z;
d = triangleMountingPoint.x * a + triangleMountingPoint.y * b + triangleMountingPoint.z * c;
if (skipErrorOfNonValidPlane == false) { ErrorLogForInvalidPlanes(); }
}
void ErrorLogForInvalidPlanes()
{
if (CheckIfPlaneIsValid() == false)
{
Debug.LogError("All plane parameters are zero. Seems like you wanted to create a plane with three points that lie on a line and therefore don't describe a plane.");
}
}
public bool CheckIfPlaneIsValid()
{
if (UtilitiesDXXL_Math.ApproximatelyZero(a))
{
if (UtilitiesDXXL_Math.ApproximatelyZero(b))
{
if (UtilitiesDXXL_Math.ApproximatelyZero(c))
{
return false;
}
}
}
return true;
}
public bool CheckIfPlaneIsValid(float floatCalculationErrorTolerancePadding)
{
if (UtilitiesDXXL_Math.CheckIfValueLiesInsideDistanceNearAnotherValue(0.0f, a, floatCalculationErrorTolerancePadding))
{
if (UtilitiesDXXL_Math.CheckIfValueLiesInsideDistanceNearAnotherValue(0.0f, b, floatCalculationErrorTolerancePadding))
{
if (UtilitiesDXXL_Math.CheckIfValueLiesInsideDistanceNearAnotherValue(0.0f, c, floatCalculationErrorTolerancePadding))
{
return false;
}
}
}
return true;
}
public InternalDXXL_Plane(Vector3 aPointOnThePlane, Vector3 normalOfThePlane_notNecessarilyNormalized)
{
normalDir = normalOfThePlane_notNecessarilyNormalized;
normalDir = UtilitiesDXXL_Math.ScaleNonZeroVectorIntoRegionOfFloatPrecision(normalDir);
if (UtilitiesDXXL_Math.ApproximatelyZero(normalDir))
{
Debug.LogError("Cannot create a plane with normal that has 0 lenght: " + UtilitiesDXXL_Log.Get_vectorComponentsAsString(normalDir));
}
a = normalDir.x;
b = normalDir.y;
c = normalDir.z;
d = a * aPointOnThePlane.x + b * aPointOnThePlane.y + c * aPointOnThePlane.z;
}
public void Recreate(Vector3 aPointOnThePlane, Vector3 normalOfThePlane_notNecessarilyNormalized)
{
normalDir = normalOfThePlane_notNecessarilyNormalized;
normalDir = UtilitiesDXXL_Math.ScaleNonZeroVectorIntoRegionOfFloatPrecision(normalDir);
if (UtilitiesDXXL_Math.ApproximatelyZero(normalDir))
{
Debug.LogError("Cannot create a plane with normal that has 0 lenght: " + UtilitiesDXXL_Log.Get_vectorComponentsAsString(normalDir));
}
a = normalDir.x;
b = normalDir.y;
c = normalDir.z;
d = a * aPointOnThePlane.x + b * aPointOnThePlane.y + c * aPointOnThePlane.z;
}
public InternalDXXL_Plane()
{
//default: xy-plane through origin
normalDir = new Vector3(0.0f, 0.0f, 1.0f);
a = normalDir.x;
b = normalDir.y;
c = normalDir.z;
d = 0.0f;
}
public void TryRecreateAsCopyOfOther(InternalDXXL_Plane planeToCopyFieldsFrom)
{
if (planeToCopyFieldsFrom != null)
{
normalDir = planeToCopyFieldsFrom.normalDir;
a = planeToCopyFieldsFrom.a;
b = planeToCopyFieldsFrom.b;
c = planeToCopyFieldsFrom.c;
d = planeToCopyFieldsFrom.d;
}
}
public bool CheckIfLineIsParallel(InternalDXXL_Line line3D)
{
return UtilitiesDXXL_Math.Check_ifVectors_arePerp(normalDir, line3D.direction_normalized);
}
public static void Calc_intersectionLine_ofTwoPlanes(ref InternalDXXL_Line alreadyConstructedLineToFill, InternalDXXL_Plane plane1, InternalDXXL_Plane plane2)
{
Vector3 directionOfLine3D = Vector3.Cross(plane1.normalDir, plane2.normalDir);
directionOfLine3D = UtilitiesDXXL_Math.ScaleNonZeroVectorIntoRegionOfFloatPrecision(directionOfLine3D);
Vector3 aValidPointOnTheLine3D = default;
bool lineIsParallelTo_yzPlane = UtilitiesDXXL_Math.ApproximatelyZero(directionOfLine3D.x);
if (lineIsParallelTo_yzPlane == false)
{
aValidPointOnTheLine3D.x = 0.0f;
aValidPointOnTheLine3D.z = (((plane2.d * plane1.b) - (plane1.d * plane2.b)) / ((plane2.c * plane1.b) - (plane1.c * plane2.b)));
if (plane1.b != 0.0f)
{
aValidPointOnTheLine3D.y = ((plane1.d - plane1.c * aValidPointOnTheLine3D.z) / plane1.b);
}
else
{
aValidPointOnTheLine3D.y = ((plane2.d - plane2.c * aValidPointOnTheLine3D.z) / plane2.b);
}
}
else
{
bool lineIsParallelTo_xzPlane = UtilitiesDXXL_Math.ApproximatelyZero(directionOfLine3D.y);
if (lineIsParallelTo_xzPlane == false)
{
aValidPointOnTheLine3D.y = 0.0f;
aValidPointOnTheLine3D.x = (((plane2.c * plane1.d) - (plane1.c * plane2.d)) / ((plane2.c * plane1.a) - (plane1.c * plane2.a)));
if (plane1.c != 0.0f)
{
aValidPointOnTheLine3D.z = ((plane1.d - plane1.a * aValidPointOnTheLine3D.x) / plane1.c);
}
else
{
aValidPointOnTheLine3D.z = ((plane2.d - plane2.a * aValidPointOnTheLine3D.x) / plane2.c);
}
}
else
{
bool lineIsParallelTo_xyPlane = UtilitiesDXXL_Math.ApproximatelyZero(directionOfLine3D.z);
if (lineIsParallelTo_xyPlane == false)
{
aValidPointOnTheLine3D.z = 0.0f;
aValidPointOnTheLine3D.y = (((plane2.a * plane1.d) - (plane1.a * plane2.d)) / ((plane2.a * plane1.b) - (plane1.a * plane2.b)));
if (plane1.a != 0.0f)
{
aValidPointOnTheLine3D.x = ((plane1.d - plane1.b * aValidPointOnTheLine3D.y) / plane1.a);
}
else
{
aValidPointOnTheLine3D.x = ((plane2.d - plane2.b * aValidPointOnTheLine3D.y) / plane2.a);
}
}
else
{
//-> "directionOfLine3D" is zero
//-> the two planes are parallel
//-> "aValidPointOnTheLine3D" is undefined (=left at default of 0/0/0)
//-> "alreadyConstructedLineToFill.Recreate" will notify this via ErrorCode-Log
}
}
}
alreadyConstructedLineToFill.Recreate(aValidPointOnTheLine3D, directionOfLine3D, false);
}
public Vector3 GetIntersectionWithLine(InternalDXXL_Line intersectingLine)
{
return intersectingLine.Get_intersectionPoint_withPlane_withoutParallelCheck(this);
}
static InternalDXXL_Line perpLine = new InternalDXXL_Line();
public Vector3 Get_perpProjectionOfPointOnPlane(Vector3 pointToProjectOntoPlane)
{
if (UtilitiesDXXL_Math.ApproximatelyZero(normalDir))
{
Debug.LogError("not allowed: normal is zero: " + UtilitiesDXXL_Log.Get_vectorComponentsAsString(normalDir));
normalDir = Vector3.forward;
}
perpLine.Recreate(pointToProjectOntoPlane, normalDir, false);
return perpLine.Get_intersectionPoint_withPlane_withoutParallelCheck(this);
}
public Vector3 Get_perpVector_fromPlaneToPoint(Vector3 point_toWhichResultingVectorWillPoint)
{
Vector3 perpProjection_ofPointOnPlane = Get_perpProjectionOfPointOnPlane(point_toWhichResultingVectorWillPoint);
return (point_toWhichResultingVectorWillPoint - perpProjection_ofPointOnPlane);
}
static InternalDXXL_Line customProjectionDirLine = new InternalDXXL_Line();
public Vector3 Get_projectionOfPointOnPlane_alongCustomDir(Vector3 pointToProjectOntoPlane, Vector3 dir_alongWhichToProject)
{
customProjectionDirLine.Recreate(pointToProjectOntoPlane, dir_alongWhichToProject, false);
return customProjectionDirLine.Get_intersectionPoint_withPlane_withoutParallelCheck(this);
}
public bool CheckIf_twoPoints_lieOnDifferentSidesOfThePlane_returnsFalseIfAGivenPointIsONplane(Vector3 point1, Vector3 point2)
{
return UtilitiesDXXL_Math.Check_ifVectorsPointAwayFromEachOther_perpCountsAsPointingInSameDir(Get_perpVector_fromPlaneToPoint(point1), Get_perpVector_fromPlaneToPoint(point2));
}
public Vector3 Get_projectionOfVectorOntoPlane(Vector3 vector_toProject)
{
return (Get_perpProjectionOfPointOnPlane(vector_toProject) - Get_perpProjectionOfPointOnPlane(Vector3.zero));
}
public Vector3 Get_projectionOfVectorOntoPlane_alongCustomDir(Vector3 vector_toProject, Vector3 dir_alongWhichToProject)
{
//-> doesn't contain parallel-check. Caller has to ensure that "dir_alongWhichToProject" is not parallel to plane
return (Get_projectionOfPointOnPlane_alongCustomDir(vector_toProject, dir_alongWhichToProject) - Get_projectionOfPointOnPlane_alongCustomDir(Vector3.zero, dir_alongWhichToProject));
}
public static bool IsHorizontal(InternalDXXL_Plane planeToCheckIfItIsHorizontal)
{
return (UtilitiesDXXL_Math.ApproximatelyZero(planeToCheckIfItIsHorizontal.normalDir.x) && UtilitiesDXXL_Math.ApproximatelyZero(planeToCheckIfItIsHorizontal.normalDir.z));
}
}
}