-
Notifications
You must be signed in to change notification settings - Fork 0
/
Line.cs
95 lines (80 loc) · 2.54 KB
/
Line.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using System;
using LeoDeg.Math.Matrices;
using LeoDeg.Math.Vectors;
using LeoDeg.Math;
namespace LeoDeg.Math.Geometry
{
public class Line
{
public enum LineType { Line, Segment, Ray }
public Line ()
{
StartPoint = Vector3.Zero;
EndPoint = Vector3.Zero;
}
public Line (Vector3 startPoint, Vector3 endPoint)
{
if (startPoint == null || endPoint == null)
throw new ArgumentNullException (nameof (startPoint));
this.StartPoint = startPoint;
this.EndPoint = endPoint;
this.Type = LineType.Segment;
}
public Line (Vector3 startPoint, Vector3 endPoint, LineType lineType)
{
this.StartPoint = startPoint;
this.EndPoint = endPoint;
this.Type = lineType;
}
public Vector3 StartPoint { get; set; }
public Vector3 EndPoint { get; set; }
public LineType Type { get; set; }
public Vector3 Direction { get { return Vector3.Direction (StartPoint, EndPoint); } }
/// <summary>
/// If lines is parallel to each other return float.Nan, otherwise return position at the current line.
/// </summary>
public float IntersectAt (Line other)
{
if (Vector3.Dot (Vector3.Perp (other.Direction), this.Direction) == 0)
return float.NaN;
Vector3 directionToOtherStart = Vector3.Direction (this.StartPoint, other.StartPoint);
float dotToDirectionBetweenStarts = Vector3.Dot (Vector3.Perp (other.Direction), directionToOtherStart);
float dotToCurrentDirection = Vector3.Dot (Vector3.Perp (other.Direction), Direction);
float position = dotToDirectionBetweenStarts / dotToCurrentDirection;
if ((position < 0 || position > 1) && Type == LineType.Segment)
return float.NaN;
return position;
}
public Vector3 Reflect (Vector3 normal)
{
Vector3 directionNormal = Direction.normalized;
float dot = Vector3.Dot (directionNormal, normal);
if (dot == 0) return this.Direction;
return directionNormal - (2.0f * Vector3.Dot (directionNormal, normal) * normal);
}
/// <summary>
/// Get point position at a time on the current line.
/// </summary>
public Vector3 Lerp (float time)
{
time = ClampTime (time);
return new Vector3 (
StartPoint.x + Direction.x * time,
StartPoint.y + Direction.y * time,
StartPoint.z + Direction.z * time
);
}
private float ClampTime (float time)
{
switch (Type)
{
case LineType.Line: return time;
case LineType.Segment: return LeoMath.Clamp (time, 0, 1);
case LineType.Ray:
if (time < 0) return 0;
return time;
default: throw new ArgumentOutOfRangeException ("Line::Error::Invalid line type.");
}
}
}
}