AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
LineUtility.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 using System;
5 using System.Collections.Generic;
6 using UnityEngine;
7 
8 namespace HoloToolkit.Unity.UX
9 {
10  public enum InterpolationEnum
11  {
12  Bezeir,
13  CatmullRom,
14  Hermite,
15  }
16 
20  public enum RotationTypeEnum
21  {
22  None, // Don't rotate
23  Velocity, // Use velocity
24  RelativeToOrigin, // Rotate relative to direction from origin point
25  }
26 
31  {
32  None, // Don't adjust placement
33  Auto, // Adjust placement automatically (default)
34  DistanceSingleValue, // Place based on distance
35  DistanceCurveValue, // Place based on curve
36  }
37 
41  public enum StepModeEnum
42  {
43  Interpolated, // Draw points based on NumLineSteps
44  FromSource, // Draw only the points available in the source - use this for hard edges
45  }
46 
51  {
52  FromNumSteps, // Specify the number of interpolation steps manually
53  FromLength, // Create steps based on total length of line + manually specified length
54  FromCurve // Create steps based on total length of line + animation curve
55  }
56 
57  public enum DistortionTypeEnum
58  {
59  NormalizedLength, // Use the normalized length of the line plus its distortion strength curve to determine distortion strength
60  Uniform, // Use a single value to determine distortion strength
61  }
62 
63  public static class LineUtils
64  {
65  #region offset and rotation functions
66 
67  public static readonly Vector3 DefaultUpVector = Vector3.up;
68 
76  public static float GetDistanceSingleValue(int step, float offsetValue, bool repeat)
77  {
78  float value = step * offsetValue;
79  return repeat ? Mathf.Repeat(value, 1f) : Mathf.Clamp01(value);
80  }
81 
90  public static float GetDistanceCurveValue(int step, int numSteps, AnimationCurve offsetCurve, bool repeat)
91  {
92  float value = offsetCurve.Evaluate((float)step / numSteps);
93  return repeat ? Mathf.Repeat(value, 1f) : Mathf.Clamp01(value);
94  }
95 
102  public static Vector3 GetVectorCollectionBlend(Vector3[] vectorCollection, float normalizedLength, bool repeat)
103  {
104  if (vectorCollection.Length == 0)
105  {
106  return Vector3.zero;
107  }
108  else if (vectorCollection.Length == 1)
109  {
110  return vectorCollection[0];
111  }
112 
113  float arrayValueLength = 1f / vectorCollection.Length;
114  int indexA = Mathf.FloorToInt(normalizedLength * vectorCollection.Length);
115  if (indexA >= vectorCollection.Length)
116  {
117  indexA = repeat ? 0 : vectorCollection.Length - 1;
118  }
119 
120  int indexB = indexA + 1;
121  if (indexB >= vectorCollection.Length)
122  {
123  indexB = repeat ? 0 : vectorCollection.Length - 1;
124  }
125 
126  float blendAmount = (normalizedLength - (arrayValueLength * indexA)) / arrayValueLength;
127  Vector3 blendedVector = Vector3.Lerp(vectorCollection[indexA], vectorCollection[indexB], blendAmount);
128  return blendedVector;
129  }
130 
131  public static float ClosestTo(this IEnumerable<float> collection, float target)
132  {
133  // NB Method will return float.MaxValue for a sequence containing no elements.
134  // Apply any defensive coding here as necessary.
135  var closest = float.MaxValue;
136  var minDifference = float.MaxValue;
137  foreach (var element in collection)
138  {
139  var difference = Mathf.Abs(element - target);
140  if (minDifference > difference)
141  {
142  minDifference = difference;
143  closest = element;
144  }
145  }
146 
147  return closest;
148  }
149 
150  #endregion
151 
152  #region line drawing functions
153 
154  public static Vector3 GetPointAlongParabola(Vector3 start, Vector3 end, Vector3 up, float height, float normalizedLength)
155  {
156  float parabolaTime = normalizedLength * 2 - 1;
157  Vector3 direction = end - start;
158  Vector3 pos = start + normalizedLength * direction;
159  pos += ((-parabolaTime * parabolaTime + 1) * height) * up.normalized;
160  return pos;
161  }
162 
163  public static Vector3 GetPointAlongSpline(SplinePoint[] points, float normalizedLength, InterpolationEnum interpolation = InterpolationEnum.Bezeir)
164  {
165  int pointIndex = (Mathf.RoundToInt(normalizedLength * points.Length));
166  float subnormalizedLength = normalizedLength - ((float)pointIndex / points.Length);
167 
168  if (pointIndex + 3 >= points.Length)
169  {
170  return points[points.Length - 1].Point;
171  }
172  if (pointIndex < 0)
173  {
174  return points[0].Point;
175  }
176 
177  Vector3 point1 = points[pointIndex].Point;
178  Vector3 point2 = points[pointIndex + 1].Point;
179  Vector3 point3 = points[pointIndex + 2].Point;
180  Vector3 point4 = points[pointIndex + 3].Point;
181 
182  switch (interpolation)
183  {
184  case InterpolationEnum.Bezeir:
185  default:
186  return InterpolateBezeirPoints(point1, point2, point3, point4, subnormalizedLength);
187 
188  case InterpolationEnum.CatmullRom:
189  return InterpolateCatmullRomPoints(point1, point2, point3, point4, subnormalizedLength);
190  }
191  }
192 
193  public static Vector3 InterpolateVectorArray(Vector3[] points, float normalizedLength)
194  {
195  float arrayValueLength = 1f / points.Length;
196  int indexA = Mathf.FloorToInt(normalizedLength * points.Length);
197  if (indexA >= points.Length)
198  {
199  indexA = 0;
200  }
201 
202  int indexB = indexA + 1;
203  if (indexB >= points.Length)
204  {
205  indexB = 0;
206  }
207 
208  float blendAmount = (normalizedLength - (arrayValueLength * indexA)) / arrayValueLength;
209 
210  return Vector3.Lerp(points[indexA], points[indexB], blendAmount);
211  }
212 
213  public static Vector3 InterpolateCatmullRomPoints(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, float normalizedLength)
214  {
215  Vector3 p1 = 2f * point2;
216  Vector3 p2 = point3 - point1;
217  Vector3 p3 = 2f * point1 - 5f * point2 + 4f * point3 - point4;
218  Vector3 p4 = -point1 + 3f * point2 - 3f * point3 + point4;
219 
220  Vector3 point = 0.5f * (p1 + (p2 * normalizedLength) + (p3 * normalizedLength * normalizedLength) + (p4 * normalizedLength * normalizedLength * normalizedLength));
221 
222  return point;
223  }
224 
225  public static Vector3 InterpolateBezeirPoints(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, float normalizedLength)
226  {
227  float invertedDistance = 1f - normalizedLength;
228  return
229  invertedDistance * invertedDistance * invertedDistance * point1 +
230  3f * invertedDistance * invertedDistance * normalizedLength * point2 +
231  3f * invertedDistance * normalizedLength * normalizedLength * point3 +
232  normalizedLength * normalizedLength * normalizedLength * point4;
233  }
234 
235  public static Vector3 InterpolateHermitePoints(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, float normalizedLength)
236  {
237  float invertedDistance = 1f - normalizedLength;
238  return
239  invertedDistance * invertedDistance * invertedDistance * point1 +
240  3f * invertedDistance * invertedDistance * normalizedLength * point2 +
241  3f * invertedDistance * normalizedLength * normalizedLength * point3 +
242  normalizedLength * normalizedLength * normalizedLength * point4;
243  }
244 
245  public static Vector3 GetEllipsePoint(float radiusX, float radiusY, float angle)
246  {
247  return new Vector3(radiusX * Mathf.Cos(angle), radiusY * Mathf.Sin(angle), 0.0f);
248  }
249 
250  #endregion
251  }
252 }
StepModeEnum
Default options for how to generate points in a line renderer
Definition: LineUtility.cs:41
static Vector3 InterpolateCatmullRomPoints(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, float normalizedLength)
Definition: LineUtility.cs:213
RotationTypeEnum
Default options for getting a rotation along a line
Definition: LineUtility.cs:20
static float GetDistanceCurveValue(int step, int numSteps, AnimationCurve offsetCurve, bool repeat)
Returns normalized length for OffsetModeEnum.CurveNormalized
Definition: LineUtility.cs:90
static Vector3 InterpolateBezeirPoints(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, float normalizedLength)
Definition: LineUtility.cs:225
static Vector3 InterpolateHermitePoints(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, float normalizedLength)
Definition: LineUtility.cs:235
static float ClosestTo(this IEnumerable< float > collection, float target)
Definition: LineUtility.cs:131
static Vector3 GetEllipsePoint(float radiusX, float radiusY, float angle)
Definition: LineUtility.cs:245
static Vector3 InterpolateVectorArray(Vector3[] points, float normalizedLength)
Definition: LineUtility.cs:193
InterpolationModeEnum
Default options for how to distribute interpolated points in a line renderer
Definition: LineUtility.cs:50
PointDistributionTypeEnum
Default options for getting an interpolated point along a line
Definition: LineUtility.cs:30
static float GetDistanceSingleValue(int step, float offsetValue, bool repeat)
Returns normalized length for OffsetModeEnum.Manual
Definition: LineUtility.cs:76
static Vector3 GetPointAlongParabola(Vector3 start, Vector3 end, Vector3 up, float height, float normalizedLength)
Definition: LineUtility.cs:154
static Vector3 GetPointAlongSpline(SplinePoint[] points, float normalizedLength, InterpolationEnum interpolation=InterpolationEnum.Bezeir)
Definition: LineUtility.cs:163
static Vector3 GetVectorCollectionBlend(Vector3[] vectorCollection, float normalizedLength, bool repeat)
Returns a blended value from a collection of vectors
Definition: LineUtility.cs:102