AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
PolygonManager.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 UnityEngine;
5 using HoloToolkit.Unity;
6 using System.Collections.Generic;
8 
9 namespace HoloToolkit.Examples.GazeRuler
10 {
14  public class PolygonManager : Singleton<PolygonManager>, IGeometry, IPolygonClosable
15  {
16  // save all geometries
17  public Stack<Polygon> Polygons = new Stack<Polygon>();
19 
26  public void AddPoint(GameObject LinePrefab, GameObject PointPrefab, GameObject TextPrefab)
27  {
28  var hitPoint = GazeManager.Instance.HitPosition;
29  var point = (GameObject)Instantiate(PointPrefab, hitPoint, Quaternion.identity);
30  var newPoint = new Point
31  {
32  Position = hitPoint,
33  Root = point
34  };
35  if (CurrentPolygon.IsFinished)
36  {
37  CurrentPolygon = new Polygon()
38  {
39  IsFinished = false,
40  Root = new GameObject(),
41  Points = new List<Vector3>()
42  };
43 
44  CurrentPolygon.Points.Add(newPoint.Position);
45  newPoint.Root.transform.parent = CurrentPolygon.Root.transform;
46  }
47  else
48  {
49  CurrentPolygon.Points.Add(newPoint.Position);
50  newPoint.Root.transform.parent = CurrentPolygon.Root.transform;
51  if (CurrentPolygon.Points.Count > 1)
52  {
53  var index = CurrentPolygon.Points.Count - 1;
54  var centerPos = (CurrentPolygon.Points[index] + CurrentPolygon.Points[index - 1]) * 0.5f;
55  var direction = CurrentPolygon.Points[index] - CurrentPolygon.Points[index - 1];
56  var distance = Vector3.Distance(CurrentPolygon.Points[index], CurrentPolygon.Points[index - 1]);
57  var line = (GameObject)Instantiate(LinePrefab, centerPos, Quaternion.LookRotation(direction));
58  line.transform.localScale = new Vector3(distance, 0.005f, 0.005f);
59  line.transform.Rotate(Vector3.down, 90f);
60  line.transform.parent = CurrentPolygon.Root.transform;
61  }
62 
63  }
64 
65  }
66 
72  public void ClosePolygon(GameObject LinePrefab, GameObject TextPrefab)
73  {
74  if (CurrentPolygon != null)
75  {
76  CurrentPolygon.IsFinished = true;
77  var area = CalculatePolygonArea(CurrentPolygon);
78  var index = CurrentPolygon.Points.Count - 1;
79  var centerPos = (CurrentPolygon.Points[index] + CurrentPolygon.Points[0]) * 0.5f;
80  var direction = CurrentPolygon.Points[index] - CurrentPolygon.Points[0];
81  var distance = Vector3.Distance(CurrentPolygon.Points[index], CurrentPolygon.Points[0]);
82  var line = (GameObject)Instantiate(LinePrefab, centerPos, Quaternion.LookRotation(direction));
83  line.transform.localScale = new Vector3(distance, 0.005f, 0.005f);
84  line.transform.Rotate(Vector3.down, 90f);
85  line.transform.parent = CurrentPolygon.Root.transform;
86 
87  var vect = new Vector3(0, 0, 0);
88  foreach (var point in CurrentPolygon.Points)
89  {
90  vect += point;
91  }
92  var centerPoint = vect / (index + 1);
93  var direction1 = CurrentPolygon.Points[1] - CurrentPolygon.Points[0];
94  var directionF = Vector3.Cross(direction, direction1);
95  var tip = (GameObject)Instantiate(TextPrefab, centerPoint, Quaternion.LookRotation(directionF));//anchor.x + anchor.y + anchor.z < 0 ? -1 * anchor : anchor));
96 
97  // unit is ㎡
98  tip.GetComponent<TextMesh>().text = area + "㎡";
99  tip.transform.parent = CurrentPolygon.Root.transform;
100  Polygons.Push(CurrentPolygon);
101  }
102  }
103 
107  public void Clear()
108  {
109  if (Polygons != null && Polygons.Count > 0)
110  {
111  while (Polygons.Count > 0)
112  {
113  var lastLine = Polygons.Pop();
114  Destroy(lastLine.Root);
115  }
116  }
117  }
118 
119  // delete latest geometry
120  public void Delete()
121  {
122  if (Polygons != null && Polygons.Count > 0)
123  {
124  var lastLine = Polygons.Pop();
125  Destroy(lastLine.Root);
126  }
127  }
128 
136  private float CalculateTriangleArea(Vector3 p1, Vector3 p2, Vector3 p3)
137  {
138  var a = Vector3.Distance(p1, p2);
139  var b = Vector3.Distance(p1, p3);
140  var c = Vector3.Distance(p3, p2);
141  var p = (a + b + c) / 2f;
142  var s = Mathf.Sqrt(p * (p - a) * (p - b) * (p - c));
143 
144  return s;
145  }
151  private float CalculatePolygonArea(Polygon polygon)
152  {
153  var s = 0.0f;
154  var i = 1;
155  var n = polygon.Points.Count;
156  for (; i < n - 1; i++)
157  s += CalculateTriangleArea(polygon.Points[0], polygon.Points[i], polygon.Points[i + 1]);
158  return 0.5f * Mathf.Abs(s);
159  }
160 
161  // Use this for initialization
162  private void Start()
163  {
164  CurrentPolygon = new Polygon()
165  {
166  IsFinished = false,
167  Root = new GameObject(),
168  Points = new List<Vector3>()
169  };
170  }
171 
172 
176  public void Reset()
177  {
178  if (CurrentPolygon != null && !CurrentPolygon.IsFinished)
179  {
180  Destroy(CurrentPolygon.Root);
181  CurrentPolygon = new Polygon()
182  {
183  IsFinished = false,
184  Root = new GameObject(),
185  Points = new List<Vector3>()
186  };
187  }
188  }
189  }
190 
191 
192  public class Polygon
193  {
194  public float Area { get; set; }
195 
196  public List<Vector3> Points { get; set; }
197 
198  public GameObject Root { get; set; }
199 
200  public bool IsFinished { get; set; }
201 
202  }
203 }
The gaze manager manages everything related to a gaze ray that can interact with other objects...
Definition: GazeManager.cs:13
void Clear()
clear all geometries in the scene
void AddPoint(GameObject LinePrefab, GameObject PointPrefab, GameObject TextPrefab)
handle new point users place
void ClosePolygon(GameObject LinePrefab, GameObject TextPrefab)
finish current geometry
static T Instance
Returns the Singleton instance of the classes type. If no instance is found, then we search for an in...
Definition: Singleton.cs:26
interface for geometry class
Definition: IGeometry.cs:12
manager all geometries in the scene
void Reset()
reset current unfinished geometry
any geometry class inherit this interface should be closeable
Singleton behaviour class, used for components that should only have one instance.
Definition: Singleton.cs:14