Добавлен Devion,
опубликован
Пишу сижу последние дни всякую простейшую математику, которая часто юзается.
В итоге вышел вот такой класс:
using System;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
public static class CustomMath
{
//Возвращает индекс минимального элемента
public static int MinIndex(float[] values)
{
return GetABResultIndex<float>(values, (a, b) => a > b, f => true);
}
//Возвращает индекс минимального элемента, при том у элемента должно выполнять некоторое условие
public static int MinIndex(float[] values, Predicate<float> condition)
{
return GetABResultIndex<float>(values, (a, b) => a > b, condition);
}
//Возвращает индекс максимального элемента
public static int MaxIndex(float[] values)
{
return GetABResultIndex<float>(values, (a, b) => a < b, f => true);
}
//Возвращает индекс минимального элемента, при том у элемента должно выполнять некоторое условие
public static int MaxIndex(float[] values, Predicate<float> condition)
{
return GetABResultIndex<float>(values, (a, b) => a < b, condition);
}
private static int GetABResultIndex<T>(T[] values, Func<T, T, bool> conditionAB, Predicate<T> conditionElement)
{
var resultIndex = -1;
for (int i = 0; i < values.Length; i++)
{
if ((resultIndex == -1 || conditionAB(values[resultIndex], values[i])) && conditionElement(values[i]))
resultIndex = i;
}
return -1;
}
//Функции округления тупо продублированы с понятными мне именами
public static float Round(float value)
{
return Mathf.Round(value);
}
public static float RoundMin(float value)
{
return Mathf.Floor(value);
}
public static float RoundMax(float value)
{
return Mathf.Ceil(value);
}
public static float RoundToInt(float value)
{
return Mathf.RoundToInt(value);
}
public static float RoundMinToInt(float value)
{
return Mathf.FloorToInt(value);
}
public static float RoundMaxToInt(float value)
{
return Mathf.CeilToInt(value);
}
//Округление векторов, епты
public static Vector3 Round(Vector3 value)
{
return new Vector3(Mathf.Round(value.x), Mathf.Round(value.y), Mathf.Round(value.z));
}
public static Vector3 RoundMin(Vector3 value)
{
return new Vector3(Mathf.Floor(value.x), Mathf.Floor(value.y), Mathf.Floor(value.z));
}
public static Vector3 RoundMax(Vector3 value)
{
return new Vector3(Mathf.Ceil(value.x), Mathf.Ceil(value.y), Mathf.Ceil(value.z));
}
public static Vector2 Round(Vector2 value)
{
return new Vector2(Mathf.Round(value.x), Mathf.Round(value.y));
}
public static Vector2 RoundMin(Vector2 value)
{
return new Vector2(Mathf.Floor(value.x), Mathf.Floor(value.y));
}
public static Vector2 RoundMax(Vector2 value)
{
return new Vector2(Mathf.Ceil(value.x), Mathf.Ceil(value.y));
}
public static Vector3 defaultScale
{
get { return new Vector3(1, 1, 1); }
}
//Нормали в отрезке
public static int GetNormal(float value)
{
if (value > 0)
return 1;
if (value < 0)
return -1;
return 0;
}
public static int GetNormalPositive(float value)
{
if (value > 0)
return 1;
return 0;
}
public static int GetNormalNegative(float value)
{
if (value < 0)
return -1;
return 0;
}
//Поиск площади фигуры
public static class Area
{
/// <summary>
/// Формула Герона
/// </summary>
public static float TriangleFromPoints(Vector3 a, Vector3 b, Vector3 c)
{
var longitudes = Longitudes(a, b, c);
var perimeter = longitudes.Sum();
var p = perimeter/2f;
var sqrS = p*(p - longitudes[0])*(p - longitudes[1])*(p - longitudes[2]);
var s = Mathf.Sqrt(sqrS);
return s;
}
/// <summary>
///
/// </summary>
/// <param name="aSide"></param>
/// <param name="bSide"></param>
/// <param name="cSide"></param>
/// <returns></returns>
public static float TriangleFromSides(float aSide, float bSide, float cSide)
{
var perimeter = aSide + bSide + cSide;
var p = perimeter/2f;
var sqrS = p*(p - aSide)*(p - bSide)*(p - cSide);
var s = Mathf.Sqrt(sqrS);
return s;
}
public static float TriangleFromPoints_Fast(Vector3 a, Vector3 b, Vector3 c)
{
var dir1 = (a - b);
var dir2 = (c - b);
return WedgeProduct(dir1, dir2);
}
/// <summary>
///
/// </summary>
/// <param name="side">Длина одной из сторон треугольника</param>
/// <param name="h">Проведенная к этой длине высота</param>
/// <returns></returns>
public static float TriangleFromSideAndHeight(float side, float h)
{
return .5f*side*h;
}
/// <summary>
///
/// </summary>
/// <param name="perimeter"></param>
/// <param name="r">Радиус вписанной окружности</param>
/// <returns></returns>
public static float TriangleFromPerimeterAndInradius(float perimeter, float r)
{
var p = perimeter/2f;
return p*r;
}
/// <summary>
///
/// </summary>
/// <param name="aSide"></param>
/// <param name="bSide"></param>
/// <param name="cSide"></param>
/// <param name="R">Радиус описанной окружности</param>
/// <returns></returns>
public static float TriangleFromSidesAndOutradius(float aSide, float bSide, float cSide, float R)
{
return (aSide*bSide*cSide)/(4*R);
}
public static float TriangleFromSidesAndAngle(float aSide, float bSide, float angleAB)
{
return .5f * aSide * bSide * Degrees.Sin(angleAB);
}
public static float SquareFromSide(float side)
{
return side*side;
}
public static float SquareFromDiagonal(float diagonal)
{
return .5f*(diagonal*diagonal);
}
public static float RectangleFromSides(float aSide, float bSide)
{
return aSide*bSide;
}
public static float RectangleFromPoints(Vector3 a, Vector3 b, Vector3 c)
{
var aSide = Vector3.Distance(a, b);
var bSide = Vector3.Distance(b, c);
return RectangleFromSides(aSide, bSide);
}
/// <summary>
/// Формула площади параллелограмма по длине стороны и высоте.
/// Площадь параллелограмма равна произведению длины его стороны и длины опущенной на эту сторону высоты.
/// </summary>
/// <param name="aSide"></param>
/// <param name="height"></param>
/// <returns></returns>
public static float ParallelogramFromSideAndHeight(float aSide, float height)
{
return aSide*height;
}
public static float ParallelogramFromPoints(Vector3 a, Vector3 b, Vector3 c)
{
var aSide = Vector3.Distance(a, b);
var bSide = Vector3.Distance(b, c);
var dirBA = (a - b);
var dirBC = (c - b);
var angle = Vector3.Angle(dirBA, dirBC);
return ParallelogramFromSidesAndAngle(aSide, bSide, angle);
}
public static float ParallelogramFromPoints_Fast(Vector3 a, Vector3 b, Vector3 c)
{
var dir1 = (a - b);
var dir2 = (c - b);
return WedgeProduct(dir1, dir2);
}
public static float ParallelogramFromSidesAndAngle(float aSide, float bSide, float angleAB)
{
return aSide * bSide * Degrees.Sin(angleAB);
}
public static float ParallelogramFromDiagonalAndAngle(float d1, float d2, float angleD1D2)
{
return d1 * d2 * Degrees.Sin(angleD1D2);
}
public static float CircleFromRadius(float radius)
{
return Mathf.PI*(radius*radius);
}
public static float CircleFromDiameter(float diameter)
{
return .25f * Mathf.PI * (diameter * diameter);
}
public static float Ellipse(float radius1, float radius2)
{
return Mathf.PI*radius1*radius2;
}
public static float TrapezeFromSides(float a, float b, float c, float d)
{
var p = (a + b + c + d)/2f;
var n1 = a + b;
var n2 = 4 - Mathf.Abs(a - b);
var n3 = (p - a)*(p - b)*(p - a - c)*(p - a - d);
var s = (n1/n2)*Mathf.Sqrt(n3);
return s;
}
public static float TrapezeFromBasesAndHeight(float aBase, float bBase, float height)
{
return .5f*(aBase + bBase)*height;
}
public static float RhombusFromSideAndHeight(float aSide, float height)
{
return aSide*height;
}
public static float RhombusFromSideAndAngle(float aSide, float angleInDegrees)
{
return aSide*aSide*Degrees.Sin(angleInDegrees);
}
public static float RhombusFromDiagonals(float diagonal1, float diagonal2)
{
return .5f*diagonal1*diagonal2;
}
public static float SphereFromRadius(float radius)
{
return 4*Mathf.PI*(radius*radius);
}
/// <summary>
/// Все точки должны быть в одной плоскости
/// </summary>
/// <param name="points"></param>
/// <returns></returns>
public static float PolygonFromPoints_Fast(params Vector2[] points)
{
if (points.Length < 3)
throw new Exception("Need minimum 3 points");
var s = 0f;
for (int i = 0; i < points.Length; i++)
{
var iplus = (i + 1)%points.Length;
var a = points[i];
var b = points[iplus];
var c = new Vector2(b.x, 0);
var d = new Vector2(a.x, 0);
s += TrapezeFromBasesAndHeight(a.y, b.y, c.x - d.x);
}
return Mathf.Abs(s);
}
public static float PolygonFromPoints(params Vector2[] points)
{
if (points.Length < 3)
throw new Exception("Need minimum 3 points");
var min = points.Min(v => v.y);
var s = 0f;
for (int i = 0; i < points.Length; i++)
{
var iplus = (i + 1) % points.Length;
var a = points[i];
var b = points[iplus];
var c = new Vector2(b.x, min);
var d = new Vector2(a.x, min);
s += TrapezeFromBasesAndHeight(a.y - min, b.y - min, c.x - d.x);
}
return Mathf.Abs(s);
}
}
public static class Perimeter
{
public static float Points(params Vector3[] points)
{
if (points.GetCount() < 3)
throw new Exception("points.Length need value >= 3");
return Longitudes(points).Sum();
}
public static float Points(params Vector2[] points)
{
if (points.GetCount() < 3)
throw new Exception("points.Length need value >= 3");
return Longitudes(points).Sum();
}
public static float CircleFromRadius(float radius)
{
return 2*Mathf.PI * radius;
}
public static float CircleFromDiameter(float diameter)
{
return diameter * Mathf.PI;
}
public static float Sides(params float[] sides)
{
if (sides.Length < 3)
throw new Exception("sides.Length need value >= 3");
return sides.Sum();
}
public static float Rhombus(float aSide)
{
return 4*aSide;
}
public static float Square(float aSide)
{
return 4*aSide;
}
public static float Rectangle(float aSide, float bSide)
{
return 2*(aSide+bSide);
}
public static float Parallelogram(float aSide, float bSide)
{
return 2*(aSide*bSide);
}
}
public static class Volume
{
public static float Cube(float aSide)
{
return aSide*aSide*aSide;
}
public static float Prism(float sBase, float height)
{
return sBase*height;
}
public static float Parallelepiped(Vector3 a, Vector3 b, Vector3 c)
{
return Mathf.Abs(TripleScalarProduct(a,b,c));
}
public static float Parallelepiped(float sBase, float height)
{
return sBase*height;
}
public static float Cuboid(float aSide, float bSide, float height)
{
return aSide*bSide*height;
}
public static float Pyramid(float sBase, float height)
{
return (sBase*height)/3f;
}
public static float RegularTetrahedron(float aSide)
{
var n1 = aSide*aSide*aSide;
var n2 = Mathf.Sqrt(2);
return (n1*n2)/12;
}
public static float CylinderFromRadius(float radius, float height)
{
return Mathf.PI*(radius*radius)*height;
}
public static float CylinderFromS(float sBase, float height)
{
return sBase * height;
}
public static float ConeFromRadius(float radius, float height)
{
return CylinderFromRadius(radius, height)/3f;
}
public static float ConeFromS(float sBase, float height)
{
return CylinderFromS(sBase, height) / 3f;
}
public static float Sphere(float radius)
{
return 4f/3f*Mathf.PI*(radius*radius*radius);
}
}
public static class Degrees
{
public static float Sin(float value)
{
return Mathf.Sin(value*Mathf.Deg2Rad);
}
public static float Cos(float value)
{
return Mathf.Cos(value * Mathf.Deg2Rad);
}
public static float Acos(float value)
{
return Mathf.Acos(value * Mathf.Deg2Rad);
}
public static float Asin(float value)
{
return Mathf.Asin(value * Mathf.Deg2Rad);
}
public static float Atan(float value)
{
return Mathf.Atan(value * Mathf.Deg2Rad);
}
public static float Tan(float value)
{
return Mathf.Tan(value * Mathf.Deg2Rad);
}
}
public static float WedgeProduct(Vector2 lhs, Vector2 rhs)
{
return lhs.x*rhs.y - lhs.y*rhs.x;
}
public static float TripleScalarProduct(Vector3 a, Vector3 b, Vector3 c)
{
return Vector3.Dot(a, Vector3.Cross(b, c));
}
public static Vector3 TripleVectorProduct(Vector3 a, Vector3 b, Vector3 c)
{
return Vector3.Cross(a, Vector3.Cross(b, c));
}
public static Vector3 CrossProduct(Vector3 lhs, Vector3 rhs)
{
return Vector3.Cross(lhs, rhs);
}
public static float DotProduct(Vector2 lhs, Vector3 rhs)
{
return lhs.x*rhs.x + lhs.y*rhs.y;
}
public static class Intersect
{
//Отрезки 2D
public static bool Segments(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2)
{
var dirA = a2 - a1;
var dirB = b2 - b1;
var dir1 = b1 - a1;
var dirX1 = a2 - b1;
var dirX2 = b2 - a1;
var f1 = WedgeProduct(dirB, -dir1);
var f2 = WedgeProduct(dirB, dirX1);
var f3 = WedgeProduct(dirA, dir1);
var f4 = WedgeProduct(dirA, dirX2);
var result = (f1*f2 < 0) && (f3*f4 < 0);
return result;
}
//Отрезки 3D
public static bool Segments(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2, out Vector3 result)
{
result = new Vector3();
Vector3 intersect;
float t;
if (Straight(a1, a2, b1, b2, out intersect, out t))
{
result = intersect;
return t >= 0 && t <= 1;
}
return false;
}
public static bool Segments(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
{
Vector3 intersect;
float t;
if (Straight(a1, a2, b1, b2, out intersect, out t))
return t >= 0 && t <= 1;
return false;
}
public static Vector3? SegmentsNullable(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
{
Vector3 intersect;
float t;
if (Straight(a1, a2, b1, b2, out intersect, out t))
return t >= 0 && t <= 1 ? (Vector3?) intersect : null;
return null;
}
public static bool Straight(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2)
{
var a = a2 - a1;
var b = b2 - b1;
return WedgeProduct(a, b).EqualsApprox(0f);
}
//Прямая 3D
public static Vector3? StraightNullable(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
{
Vector3 intersect;
float t;
return Straight(a1, a2, b1, b2, out intersect, out t) ? (Vector3?) intersect : null;
}
public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
{
Vector3 intersect;
float t;
return Straight(a1, a2, b1, b2, out intersect, out t);
}
public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2, out Vector3 result)
{
result = new Vector3();
Vector3 intersect;
float t;
if (Straight(a1, a2, b1, b2, out intersect, out t))
{
result = intersect;
return true;
}
return false;
}
public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2, out Vector3 result, out float t)
{
var aDir = (a2 - a1).normalized;
var bDir = (b2 - b1).normalized;
result = new Vector3();
t = -1;
for (int xIndex = 0; xIndex < 3; xIndex++)
{
var yIndex = (xIndex + 1)%3;
var zIndex = (xIndex + 2)%3;
var n1 = new Vector2(aDir[xIndex], aDir[yIndex]);
var n2 = -new Vector2(bDir[xIndex], bDir[yIndex]);
var n3 = new Vector2(
b1[xIndex] - a1[xIndex],
b1[yIndex] - a1[yIndex]
);
var det = n1.x * n2.y - n2.x * n1.y;
if (Mathf.Abs(det) >= Mathf.Epsilon) // if det != 0
{
var d1 = n3.x * n2.y - n2.x * n3.y;
var d2 = n1.x * n3.y - n1.y * n3.x;
var t1 = d1 / det;
var t2 = d2 / det;
var temp1 = a1[zIndex] + aDir[zIndex] * t1;
var temp2 = b1[zIndex] + bDir[zIndex] * t2;
if (Mathf.Abs(temp1 - temp2) < Mathf.Epsilon)
{
result = a1 + aDir*t1;
t = t1;
return true; // if temp1 = temp2
}
return false;
}
}
return false;
}
}
public static class Contains
{
public static bool Rectangle(Rect rect, Vector2 point)
{
return rect.Contains(point);
}
public static bool Segment(Vector2 a1, Vector2 a2, Vector2 point)
{
var v1 = a2 - a1;
var v2 = point - a1;
return WedgeProduct(v1, v2).EqualsApprox(0f) && Vector2.Dot(a1 - point, a2 - point) <= 0;
}
public static bool Straight(Vector2 a1, Vector2 a2, Vector2 point)
{
var v1 = (a2 - a1);
var v2 = (point - a1);
var diff = WedgeProduct(v1, v2);
return diff.EqualsApprox(0f);
}
public static bool RayFromPoints(Vector2 aStart, Vector2 aFinish, Vector2 point)
{
return RayFromDir(aStart, (aFinish - aStart).normalized, point);
}
public static bool RayFromDir(Vector2 origin, Vector2 dir, Vector2 point)
{
var v1 = dir;
var v2 = (point - origin);
return WedgeProduct(v1, v2).EqualsApprox(0f) && Vector2.Dot(v1, v2) >= 0;
}
}
/// <summary>
/// Указывает, является ли угол выпуклым (по часовой стрелке)
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
/// <returns></returns>
public static bool IsConvex(Vector2 a, Vector2 b, Vector2 c)
{
var AB = -(a - b);
var BC = (c - b);
var diff = WedgeProduct(AB, BC);
return diff <= 0;
}
/// <summary>
/// Указывает, является ли угол выпуклым (по часовой стрелке)
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
/// <returns></returns>
public static bool IsConvex(Vector3 a, Vector3 b, Vector3 c)
{
var AB = -(a - b);
var BC = (c - b);
var dAB = Vector3.ProjectOnPlane(AB, new Vector3(0, 0, 1));
var dBC = Vector3.ProjectOnPlane(BC, new Vector3(0, 0, 1));
return IsConvex((Vector2)dAB, Vector2.zero, (Vector2)dBC);
}
public static Vector3 GetNormal(Vector3 a, Vector3 b, Vector3 c)
{
return Vector3.Normalize(Vector3.Cross(b - a, c - a));
}
/// <summary>
/// Возвращает длины между двумя точками.
/// Если точек больше двух, то возвращается так же длина между первой и последней точкой.
/// Минимум 2 точки.
/// </summary>
public static float[] Longitudes(params Vector3[] points)
{
if (points.Length < 2)
return new float[0];
var count = points.Length != 2 ? points.Length : (points.Length - 1);
var longitudes = new float[count];
for (int i = 0; i < count; i++)
{
longitudes[i] = Vector3.Distance(points[i], points[(i + 1) % points.Length]);
}
return longitudes;
}
/// <summary>
/// Возвращает длины между двумя точками.
/// Если точек больше двух, то возвращается так же длина между первой и последней точкой.
/// Минимум 2 точки.
/// </summary>
public static float[] Longitudes(params Vector2[] points)
{
if (points.Length < 2)
return new float[0];
var count = points.Length != 2 ? points.Length : (points.Length - 1);
var longitudes = new float[count];
for (int i = 0; i < count; i++)
{
longitudes[i] = Vector2.Distance(points[i], points[(i + 1) % points.Length]);
}
return longitudes;
}
}
Много всякой херни, но вкратце по основному:
MinIndex/MaxIndex - возвращают индекс наименьшего/наибольшего элемента в массиве. Могут еще на доп условие проверить
Функции округления в большую/меньшую/ближайшую сторону - это тупо было скопировано из библиотеки Mathf под другими именами. Так лично мне удобней.
Функции округления для векторов - ну а почему бы и нет.
vectorScale - тупо заготовленный единичный вектор для размера. Не нашел нигде.
GetNormal для числа - нормализация числа, тобиш возврат единичного отрезка. Бывает необходимо.
Разные Product'ы для векторов - тут парочка старых добрых скалярного/векторного произведения + косое произведение + тройное векторное + тройное скалярное
MinIndex/MaxIndex - возвращают индекс наименьшего/наибольшего элемента в массиве. Могут еще на доп условие проверить
Функции округления в большую/меньшую/ближайшую сторону - это тупо было скопировано из библиотеки Mathf под другими именами. Так лично мне удобней.
Функции округления для векторов - ну а почему бы и нет.
vectorScale - тупо заготовленный единичный вектор для размера. Не нашел нигде.
GetNormal для числа - нормализация числа, тобиш возврат единичного отрезка. Бывает необходимо.
Разные Product'ы для векторов - тут парочка старых добрых скалярного/векторного произведения + косое произведение + тройное векторное + тройное скалярное
В подклассе Area формулы чтобы посчитать площадь фигуры
В подклассе Perimeter формулы чтобы посчитать периметр фигуры
В подклассе Volume формулы чтобы посчитать объем фигуры
В подклассе Intersect формулы чтобы посчитать пересекаются ли фигуры
В подклассе Contains формулы чтобы посчитать содержит ли фигура точку
IsConvex - проверяет выпуклый ли угол по часовой стрелке
Longitudes - возвращает массив длин по указанным точкам
В подклассе Perimeter формулы чтобы посчитать периметр фигуры
В подклассе Volume формулы чтобы посчитать объем фигуры
В подклассе Intersect формулы чтобы посчитать пересекаются ли фигуры
В подклассе Contains формулы чтобы посчитать содержит ли фигура точку
IsConvex - проверяет выпуклый ли угол по часовой стрелке
Longitudes - возвращает массив длин по указанным точкам
Ну и собственно - к чему я пишу. Я вообще по правде туп по части математики.
Потому хочу тут услышать ваши дополнения и быстрые алгоритмы чтобы что-то посчитать.
Меня очень напрягают функции Longitudes, IsConvex для Vector3, Intersect.Straight для Vector3.
Хотелось бы знать, если у вас есть лучшие решения для этих функций.
И еще в рунете не нашел никакой инфы "для чайников" по части вычислений с тройным скалярным произведением, как я понимаю решения через них самые быстрые. Если есть знатоки - пишите формулы, расскажите хоть-что нибудь об этом.
Потому хочу тут услышать ваши дополнения и быстрые алгоритмы чтобы что-то посчитать.
Меня очень напрягают функции Longitudes, IsConvex для Vector3, Intersect.Straight для Vector3.
Хотелось бы знать, если у вас есть лучшие решения для этих функций.
И еще в рунете не нашел никакой инфы "для чайников" по части вычислений с тройным скалярным произведением, как я понимаю решения через них самые быстрые. Если есть знатоки - пишите формулы, расскажите хоть-что нибудь об этом.
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Отредактирован Devion
Вроде тут понятно написано.
Находишь точку пересечений прямых, потом смотришь, лежит ли она внутри обоих из отрезков.
По поводу пересечения прямых - это чтото большое) Я хоть тоже с математикой не особо в ладах, но не проще ли было сначала найти пересечение проекций на какую нибудь координатную плоскость, а затем проверить совпадение оставшейся, еще не использованной, координатой?
Для поиска точек пересечения на плоскости можно воспользоваться ссылкой Hellfirm.
Отредактирован AsagiriGen
Т.е. если (a1/b1==a2/b2==a3/b3) верно, то они не пересекутся(они паралельны или сливаются). Иначе: пересекутся.
Отредактирован Devion
GeneralElConsul, сверить то можно, а вот как сделать так, чтобы узнать в какой точке это произошло? Формула выше как бы учитывает это тоже, там out параметрами возврат точки идет
Extravert:
эт понятно, я уже вписал ее. Вот так же выходит, верно?
Отредактирован Hellfim
Этот код сравнивает одни и тем же направляющим вектором заданы 2 отрезка, или нет.
Потому что нормализация вектора это скрытый sqrt, магнитуда и т д. А тупо сделать три деления побыстрее. Я вот чем руководствуюсь.
В общем то проверим
В общем вот такие функции вышли
Отредактирован Devion
Вот так сделал
Просто странно. Если ты занялся оптимизацией, то зачем тогда StraightIfNull?
Отредактирован Mihahail
первая прямая: r=r1+a*t
вторая прямая: r=r2+b*t
t - параметр, в случае прямой пробегает всю числовую ось, в случае отрезка - отрезок.
Где ( a, b, c ) - смешанное произведение, (a,b) - скалярное.
Будет сделано 9 умножений, 3 вычитания и 3 сложения для смешанного произведения; и ещё 3 сложения и 3 умножения для скалярного. Если вычисления ленивые(хз как C#), то именно в таком порядке проверки.
Пусть у нас есть две прямые, лежащие "почти" в одной плоскости с точностью epsilon, и для них выполнено, что (a,b)!=0, т.е. они не параллельные. Тогда они пересекаются.
А вот и не факт. Если они лежат в двух плоскостях, лишь чуть-чуть наклонённых друг относительно друга, и ещё они разнесены( |r1-r2| велико ), то они на дальних расстояниях вообще будут далеко одна от другой. А мы их считаем пересекшимися, потому что наш метод работает только с какой-то точностью epsilon и может не почувствовать маленький угол, дающий большое расхождение на дальних дистанциях.
Так, стоп, нужно только в 2D? Тогда зря я это написал, тогда это в гугл...
Только там ещё если r1-r2 ~ 0, то точка пересечения r=r1=r2
Т.е. через расстояние между скрещивающимися прямыми, только там надо их проверить на параллельность сначала, а то на ноль поделить можно.