Пишу сижу последние дни всякую простейшую математику, которая часто юзается.
В итоге вышел вот такой класс:
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'ы для векторов - тут парочка старых добрых скалярного/векторного произведения + косое произведение + тройное векторное + тройное скалярное
В подклассе Area формулы чтобы посчитать площадь фигуры
В подклассе Perimeter формулы чтобы посчитать периметр фигуры
В подклассе Volume формулы чтобы посчитать объем фигуры
В подклассе Intersect формулы чтобы посчитать пересекаются ли фигуры
В подклассе Contains формулы чтобы посчитать содержит ли фигура точку
IsConvex - проверяет выпуклый ли угол по часовой стрелке
Longitudes - возвращает массив длин по указанным точкам
Ну и собственно - к чему я пишу. Я вообще по правде туп по части математики.
Потому хочу тут услышать ваши дополнения и быстрые алгоритмы чтобы что-то посчитать.
Меня очень напрягают функции Longitudes, IsConvex для Vector3, Intersect.Straight для Vector3.
Хотелось бы знать, если у вас есть лучшие решения для этих функций.
И еще в рунете не нашел никакой инфы "для чайников" по части вычислений с тройным скалярным произведением, как я понимаю решения через них самые быстрые. Если есть знатоки - пишите формулы, расскажите хоть-что нибудь об этом.
Смотрите также:
Комментарии
- 1 (Текущая страница)
- 2
Развернутый вариант функции, проверяющей пересечения прямых в пространстве. В коде в самом ресурсе там тупо xyz перебираются циклом от 0 до 2.
public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2, out Vector3 result, out float t) { var L1StartPoint = a1; var L2StartPoint = b1; var L1Direction = (a2 - a1).normalized; var L2Direction = (b2 - b1).normalized; result = new Vector3(); t = -1; float A11 = L1Direction.x; float A12 = -L2Direction.x; float A21 = L1Direction.y; float A22 = -L2Direction.y; float B1 = L2StartPoint.x - L1StartPoint.x; float B2 = L2StartPoint.y - L1StartPoint.y; float t1, t2; float det = A11 * A22 - A12 * A21; if (Mathf.Abs(det) >= Mathf.Epsilon) // if det != 0 { float d1 = B1 * A22 - A12 * B2; float d2 = A11 * B2 - A21 * B1; t1 = d1 / det; t2 = d2 / det; float temp1 = L1StartPoint.z + L1Direction.z * t1; float temp2 = L2StartPoint.z + L2Direction.z * t2; if (Mathf.Abs(temp1 - temp2) < Mathf.Epsilon) { result = new Vector3 { x = L1StartPoint.x + L1Direction.x * t1, y = L1StartPoint.y + L1Direction.y * t1, z = L1StartPoint.z + L1Direction.z * t1 }; t = t1; return true; // if temp1 = temp2 } return false; } A21 = L1Direction.z; A22 = -L2Direction.z; B2 = L2StartPoint.z - L1StartPoint.z; det = A11 * A22 - A12 * A21; if (Mathf.Abs(det) >= Mathf.Epsilon) { float d1 = B1 * A22 - A12 * B2; float d2 = A11 * B2 - A21 * B1; t1 = d1 / det; t2 = d2 / det; float temp1 = L1StartPoint.y + L1Direction.y * t1; float temp2 = L2StartPoint.y + L2Direction.y * t2; if (Mathf.Abs(temp1 - temp2) < Mathf.Epsilon) { result = new Vector3 { x = L1StartPoint.x + L1Direction.x * t1, y = L1StartPoint.y + L1Direction.y * t1, z = L1StartPoint.z + L1Direction.z * t1 }; t = t1; return true; // if temp1 = temp2 } return false; } A11 = L1Direction.y; A12 = -L2Direction.y; B1 = L2StartPoint.y - L1StartPoint.y; det = A11 * A22 - A12 * A21; if (Mathf.Abs(det) >= Mathf.Epsilon) { float d1 = B1 * A22 - A12 * B2; float d2 = A11 * B2 - A21 * B1; t1 = d1 / det; t2 = d2 / det; float temp1 = L1StartPoint.x + L1Direction.x * t1; float temp2 = L2StartPoint.x + L2Direction.x * t2; if (Mathf.Abs(temp1 - temp2) < Mathf.Epsilon) { result = new Vector3 { x = L1StartPoint.x + L1Direction.x * t1, y = L1StartPoint.y + L1Direction.y * t1, z = L1StartPoint.z + L1Direction.z * t1 }; t = t1; return true; // if temp1 = temp2 } return false; } return false; }
Очень бы хотелось упростить эту функцию, знаю, такой способ наверняка есть. Точнее использовать более быстрый вариант нахождения такого пересечения.
Extravert, http://e-maxx.ru/algo/lines_intersection
Вроде тут понятно написано.
Находишь точку пересечений прямых, потом смотришь, лежит ли она внутри обоих из отрезков.
Во первых, это двойное скалярное и двойное векторное произведение, а не тройное)
По поводу пересечения прямых - это чтото большое) Я хоть тоже с математикой не особо в ладах, но не проще ли было сначала найти пересечение проекций на какую нибудь координатную плоскость, а затем проверить совпадение оставшейся, еще не использованной, координатой?
Для поиска точек пересечения на плоскости можно воспользоваться ссылкой Hellfirm.
У тебя даны направляющие векторы a, b прямых(по одному на каждую прямую). Например a(1,1,1) и b(1,2,3) я так понял.
Если я правильно понял входные данные, тогда все просто: если координаты векторов непропорциональны, то вектора пересекаются. В противном случае - не пересекаются.
Т.е. если (a1/b1==a2/b2==a3/b3) верно, то они не пересекутся(они паралельны или сливаются). Иначе: пересекутся.
двойное скалярное и двойное векторное произведение, а не тройное
а почему не тройное то? разницы нет никакой. Открываем гугл и узнаем что эти понятия эквиваленты. А на английском он называется Triple Product, что как бы намекает.
GeneralElConsul, сверить то можно, а вот как сделать так, чтобы узнать в какой точке это произошло? Формула выше как бы учитывает это тоже, там out параметрами возврат точки идет
GeneralElConsul,
эт понятно, я уже вписал ее. Вот так же выходит, верно?
public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2) { var a = (a2 - a1); var b = (b2 - b1); var c = new Vector3(a.x/b.x, a.y/b.y, a.z/b.z); return c.x.EqualsApprox(c.y) && c.y.EqualsApprox(c.z); }
Extravert, почему бы не
public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2) { return (a2-a1).normalize.Equals((b2-b1).normalize); }
?
Этот код сравнивает одни и тем же направляющим вектором заданы 2 отрезка, или нет.
Но здесь есть небольшая проблема. Тебе же не важно направление, поэтому лучше сравнивать так:
public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2) { var v1=(a2-a1).normalize; var v2=(b2-b1).normalize; return v1.Equals(v2) || v1.Equals(-v2); }
Hellfim, если код который я привел выше рабочий то лучше оставить его.
Потому что нормализация вектора это скрытый sqrt, магнитуда и т д. А тупо сделать три деления побыстрее. Я вот чем руководствуюсь.
В общем то проверим
Из первого поста Hellfim смекнулось, добавил пару формул вычисления детерминанта для плоскости и пространства
В общем вот такие функции вышли
public static float Determinant2x2(float a, float b, float c, float d) { return a * d - b * c; } public static float Determinant2x2(float[,] i2xj2) { var m = i2xj2; return Determinant2x2( m[0, 0], m[0, 1], m[1, 0], m[1, 1]); } public static float Determinant3x3(float a11, float a12, float a13, float a21, float a22, float a23, float a31, float a32, float a33) { return a11*Determinant2x2(a22, a23, a32, a33) - a12*Determinant2x2(a21, a23, a31, a33) + a13*Determinant2x2(a21, a22, a31, a32); } public static float Determinant3x3(float[,] i3xj3) { var m = i3xj3; return Determinant3x3( m[0, 0], m[0, 1], m[0, 2], m[1, 0], m[1, 1], m[1, 2], m[2, 0], m[2, 1], m[2, 2]); }
- 1 (Текущая страница)
- 2
CollectableItemData.cs
[CreateMenuItem(fileName = "newItem", menuName = "Data/Items/Collectable", order = 51]