IMHOTEP Framework
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Pages
LabelPositioner.cs
1 using UnityEngine;
2 using System;
3 using System.Collections.Generic;
4 using System.IO;
5 
6 
17 public class LabelPositioner : MonoBehaviour{
18 
19 
20 
21  public struct PlaneVectors
22  {
23  public Vector3 x, y, z, origin;
24 
25  public PlaneVectors(Vector3 x, Vector3 y, Vector3 z, Vector3 o)
26  {
27  this.x = x;
28  this.y = y;
29  this.z = z;
30  this.origin = o;
31  }
32  }
33 
34 
35  private PlaneVectors[] pointPlaneVectors;
36  private PlaneVectors[] labelPlaneVectors;
38  private Plane[] pointPlanes;
39  private Plane[] labelPlanes;
41  //private Plane[] camPlanes; /**< Ebenen des ViewPlaneFrustum */
42 
43 
44 
45 
46  private float[] initialPlaneRadius = new float[4];
48  private Bounds meshBox;
49  private BoundingSphere bSphere;
51  private GameObject meshRotationNode;
52  private GameObject meshNode;
53  private GameObject meshPositionNode;
54  private GameObject meshViewerBase;
55 
56  private List<GameObject> annotationList;
57 
58  public Camera silhouetteCamPrefab;
59  private Texture2D silhouetteImage;
61  private Camera silhouetteCam;
63  public bool autoHideAnnotations = true;
64 
65  private List<Label>[] labelLists = new List<Label>[4];
66  private List<Point>[] pointsOnPlane = new List<Point>[4];
68  private Quaternion meshRotation = Quaternion.identity;
70  private float rotationChange;
72  private float meshScale = 0;
73  private float scaleChange;
75  private int[] energyOfPlanes = new int[4];
77  private bool switchToZoomPlane = false;
79  //private int pointCount = 0; /**< anzahl an Punkten */
80  private int counter = 0;
82  private float[] rads = new float[360];
84  private bool inCalculationOfZoomPlane = false;
85  private bool inCalculationOfPlanes = false;
87  public int iterations = 250;
88  public float weightAngleSizeRatio = 0.2f;
89  public bool middlePlane = false;
91  public float zoomPlaneDistance = 2f;
92  public float zoomPlaneDetectionRadius;
94  private int whichMode = 0;
95 
96  private bool startRepositioning; //dient als interrupt falls die anzahl der annotationen sich ändert
97 
98  void Start()
99  {
100  initialPlaneRadius = new float[4];
101 
102  pointPlanes = new Plane[4];
103  labelPlanes = new Plane[4];
104 
105  pointPlaneVectors = new PlaneVectors[4];
106  labelPlaneVectors = new PlaneVectors[4];
107 
108  meshViewerBase = GameObject.Find("MeshViewerBase");
109  meshRotationNode = GameObject.Find("MeshViewerBase/MeshViewerScale/MeshRotationNode");
110  meshNode = GameObject.Find("MeshViewerBase/MeshViewerScale");
111  meshPositionNode = GameObject.Find("MeshViewerBase/MeshViewerScale/MeshRotationNode/MeshPositionNode");
112 
113  //camPlanes = GeometryUtility.CalculateFrustumPlanes(Camera.main);
114 
115 
116  zoomPlaneDistance = 3f;
117  weightAngleSizeRatio = 0.2f; // wurde experimentell bestimmt
118  iterations = 350;
119  whichMode = 0;
120 
121  silhouetteCam = (Camera)Instantiate(silhouetteCamPrefab, Camera.main.transform.position, Camera.main.transform.rotation);
122  silhouetteCam.transform.parent = this.transform;
123 
124  annotationList = AnnotationControl.instance.getAnnotationList();
125  }
126 
133  void Update()
134  {
135  rotationChange = Quaternion.Angle(meshRotation, meshRotationNode.transform.rotation);
136  scaleChange = Math.Abs(meshNode.transform.localScale.x - meshScale);
137 
138  if(annotationList != null)
139  {
140  if(annotationList.Count != 0)
141  {
142  if (annotationList[annotationList.Count - 1].GetComponent<Annotation>().getLabel() != null)
143  {
144  updateAnnotation();
145  }
146  }
147  }
148 
149  }
150 
151  public void forceRecalculate() {
152  whichMode = 0;
153  rotationChange = 35;
154  startRepositioning = true;
155  inCalculationOfPlanes = false;
156  inCalculationOfZoomPlane = false;
157  if(meshNode != null) {
158  updateAnnotation();
159  }
160  }
161 
162 
167  public void updateAnnotationList(List<GameObject> annoList) {
168  annotationList = annoList;
169  whichMode = 0;
170  rotationChange = 35;
171  startRepositioning = true;
172  inCalculationOfPlanes = false;
173  inCalculationOfZoomPlane = false;
174  if(meshNode != null) {
175  updateAnnotation();
176  }
177 
178  }
179 
180  public void resetAnnotationList() {
181  annotationList = new List<GameObject> ();
182  }
183 
184 
192  private void updateAnnotation()
193  {
194  //things to do every frame
195 
196  createBoundingBox();
197  zoomPlaneDetectionRadius = getInitialPlaneRadius(3);
198 
199  if (meshNode.transform.localScale.x < 1.2f) //hier wird unterschieden ob das Objekt sehr nah ist oder nicht. Jenachdem werden bestimmte labels ausgeblendet oder eingeblendet
200  {
201  bool[] whichPlane = new bool[] { false, middlePlane, true, false };
202 
203  if (switchToZoomPlane)
204  {
205  rotationChange = 35;
206  switchToZoomPlane = false;
207  }
208 
209  if (rotationChange >= 35 || scaleChange >= 0.25f || startRepositioning) //hier wird geprüft ob das Model sich mehr als 35 grad gedreht hat --> labels werden neu angeordnet
210  {
211  if (whichMode == 2)
212  {
213  meshRotation = meshRotationNode.transform.rotation;
214  meshScale = meshNode.transform.localScale.x;
215 
216  inCalculationOfPlanes = true;
217  inCalculationOfZoomPlane = false;
218 
219  calculateEnergy(whichPlane);
220 
221  startRepositioning = false;
222  whichMode = 0;
223  counter = 0; // iterationen zähler
224  }
225  else if (whichMode == 1)
226  {
227  for (int i = 0; i < labelLists.Length; i++)
228  {
229  labelLists[i] = new List<Label>();
230  pointsOnPlane[i] = new List<Point>();
231  }
232  createLabelCircle(switchToZoomPlane);
233 
234  sortListsByAngle(whichPlane);
235 
236  defineNeighbours();
237 
238  whichMode = 2;
239  }
240  else if (whichMode == 0)
241  {
242  createPlanes(zoomPlaneDistance);
243 
244  silhouetteCam.transform.position = Camera.main.transform.position;
245  silhouetteCam.transform.LookAt(meshBox.center);
246  takePicture();
247  createPie();
248  whichMode = 1;
249  //drawPicture();
250  }
251 
252 
253 
254 
255  }
256  else if (inCalculationOfPlanes)
257  {
258  calculateForces(switchToZoomPlane, whichPlane);
259  counter++;
260  if(energyOfPlanes[2] == 0 || counter > iterations)
261  {
262  inCalculationOfPlanes = false;
263  //drawPicture();
264  counter = 0;
265  }
266  }
267  }
268  else
269  {
270 
271  bool[] whichPlane = new bool[] { false, false, false, true };
272 
273  if (!switchToZoomPlane)
274  {
275  rotationChange = 15;
276  switchToZoomPlane = true;
277  }
278  if (rotationChange >= 15 || scaleChange >= 0.1f)
279  {
280  createPlanes(zoomPlaneDistance);
281 
282  inCalculationOfPlanes = false;
283  inCalculationOfZoomPlane = true;
284 
285 
286  meshRotation = meshRotationNode.transform.rotation;
287  meshScale = meshNode.transform.localScale.x;
288 
289  for (int i = 0; i < labelLists.Length; i++)
290  {
291  labelLists[i] = new List<Label>();
292  pointsOnPlane[i] = new List<Point>();
293  }
294 
295  createLabelCircle(switchToZoomPlane);
296 
297  sortListsByAngle(whichPlane);
298 
299  defineNeighbours();
300 
301  calculateEnergy(whichPlane);
302 
303  counter = 0;
304  }
305  else if (inCalculationOfZoomPlane)
306  {
307 
308  switchToZoomPlane = true;
309 
310  calculateForces(switchToZoomPlane, whichPlane);
311 
312  counter++;
313 
314 
315  if(energyOfPlanes[3] == 0 || counter > iterations)
316  {
317  inCalculationOfZoomPlane = false;
318 
319  counter = 0;
320  }
321  }
322  }
323  }
324 
331  private void sortListsByAngle(bool[] whichPlane )
332  {
333 
334  for(int i = 0; i < labelLists.Length; i++)
335  {
336  if (whichPlane[i])
337  {
338  labelLists[i].Sort((s1, s2) => s1.angle.CompareTo(s2.angle));
339  }
340  }
341 
342 
343  }
344 
352  private void createLabelCircle(bool zoomPlane)
353  {
354  int planeNumber;
355 
356  for(int i = 0; i < annotationList.Count; i++)
357  {
358 
359  Point p = new Point();
360 
361 
362  if (annotationList[i] != null)
363  {
364 
365  planeNumber = updateWhichPlaneForPoint(annotationList[i], zoomPlane, middlePlane);
366 
367 
368  p.planeNumber = planeNumber;
369  p = orthoProjectPointOnPlane(annotationList[i].transform.position, planeNumber, labelPlaneVectors[planeNumber], labelPlanes[planeNumber]);
370  p.annotationPoint = annotationList[i];
371 
372  //hier wird der Punkt der zuvor auf eine Ebene projiziert wurde auf einen Kreis in der ebene projiziert
373 
374  float radius = getInitialPlaneRadius(planeNumber);
375 
376  Vector3 pointProjectedOnCircle = labelPlaneVectors[planeNumber].origin + radius * (p.position - labelPlaneVectors[planeNumber].origin).normalized;
377 
378  float y = Vector3.Dot(pointProjectedOnCircle - labelPlaneVectors[planeNumber].origin, labelPlaneVectors[planeNumber].y);
379  float x = Vector3.Dot(pointProjectedOnCircle - labelPlaneVectors[planeNumber].origin, labelPlaneVectors[planeNumber].x);
380 
381  Label l = new Label(y, x, pointProjectedOnCircle, planeNumber, p.angle, annotationList[i]);
382 
383  l.pointOnPlane = p;
384  l.calculateAngleToLeftAndRight(labelPlaneVectors[planeNumber].x, labelPlaneVectors[planeNumber].y, labelPlaneVectors[planeNumber].origin);
385  l.calculateWeight(weightAngleSizeRatio);
386 
387 
388 
389 
390 
391  p.label = l;
392  //check if annotation is not current
393 
394  if (l.annotationLabel != null)
395  {
396  if (AnnotationControl.instance.isCurrentAnnotation (p.annotationPoint)) {
397  l.annotationLabel.SetActive(true);
398  }
399 
400  if (zoomPlane)
401  {
402 
403  if (planeNumber != 3)
404  {
405  if (!AnnotationControl.instance.isCurrentAnnotation (p.annotationPoint)) {
406  if( autoHideAnnotations )
407  l.annotationLabel.SetActive(false);
408  }
409  //l.annotationPoint.SetActive(false);
410  }
411  else
412  {
413  l.annotationLabel.SetActive(true);
414  l.annotationPoint.SetActive(true);
415  labelLists[planeNumber].Add(l);
416  pointsOnPlane[planeNumber].Add(p);
417  }
418  }
419  else
420  {
421  if (middlePlane)
422  {
423  if (planeNumber == 0 || planeNumber == 3)
424  {
425  if (!AnnotationControl.instance.isCurrentAnnotation (p.annotationPoint)) {
426  if( autoHideAnnotations )
427  l.annotationLabel.SetActive(false);
428  }
429  //l.annotationPoint.SetActive(false);
430  }
431  else
432  {
433  l.annotationLabel.SetActive(true);
434  l.annotationPoint.SetActive(true);
435  labelLists[planeNumber].Add(l);
436  pointsOnPlane[planeNumber].Add(p);
437  }
438  }
439  else
440  {
441  if (planeNumber != 2)
442  {
443  if (!AnnotationControl.instance.isCurrentAnnotation (p.annotationPoint)) {
444  if( autoHideAnnotations )
445  l.annotationLabel.SetActive(false);
446  }
447  //l.annotationPoint.SetActive(false);
448  }
449  else
450  {
451  l.annotationLabel.SetActive(true);
452  l.annotationPoint.SetActive(true);
453  labelLists[planeNumber].Add(l);
454  pointsOnPlane[planeNumber].Add(p);
455  }
456  }
457  }
458  }
459  }
460 
461  }
462  if (zoomPlane)
463  {
464  calculateCenterOfZoomPlane(pointsOnPlane[3]);
465  }
466  }
467 
473  private void defineNeighbours()
474  {
475  for (int m = 0; m < labelLists.Length; m++)
476  {
477  for (int j = 0; j < labelLists[m].Count; j++)
478  {
479  if(j == 0)
480  {
481  labelLists[m][j].leftLabel = labelLists[m][labelLists[m].Count - 1];
482 
483  if (labelLists[m].Count >= 2)
484  {
485  labelLists[m][j].rightLabel = labelLists[m][j + 1];
486  }
487  else
488  {
489  labelLists[m][j].rightLabel = labelLists[m][j];
490  }
491  }
492  else if (j == labelLists[m].Count - 1)
493  {
494  labelLists[m][j].rightLabel = labelLists[m][0];
495 
496  if (labelLists[m].Count >= 2)
497  {
498  labelLists[m][j].leftLabel = labelLists[m][j - 1];
499  }
500  else
501  {
502  labelLists[m][j].leftLabel = labelLists[m][j];
503  }
504  }
505  else{
506 
507  labelLists[m][j].rightLabel = labelLists[m][j + 1];
508  labelLists[m][j].leftLabel = labelLists[m][j - 1];
509 
510  }
511 
512  }
513  }
514 
515 
516 
517  }
518 
519 
527  private void calculateForces( bool zoomPlane, bool[] whichPlane)
528  {
529  for (int m = 0; m < labelLists.Length; m++)
530  {
531  if (whichPlane[m])
532  {
533  for (int j = 0; j < labelLists[m].Count; j++)
534  {
535  labelLists[m][j].dispAngle = 0;
536 
537  if (labelLists[m][j].annotationLabel != null)
538  {
539  if (labelLists[m][j].annotationLabel.activeSelf)
540  {
541  for (int u = 0; u < labelLists[m].Count; u++)
542  {
543  if (labelLists[m][u].annotationLabel != null)
544  {
545  if (labelLists[m][u].annotationLabel.activeSelf)
546  {
547  if (j != u)
548  {
549  float angleOfForce = Vector3.Angle(labelLists[m][j].position, labelLists[m][u].position);
550 
551  if (overlapLabelOnLabel(labelLists[m][j], labelLists[m][u]))
552  //if(true)
553  {
554 
555  if (labelLists[m][j].angle > 180)
556  {
557  if (labelLists[m][u].angle < labelLists[m][j].angle - 180)
558  { //Kraft kommt von rechts
559  labelLists[m][j].dispAngle = labelLists[m][j].dispAngle - calculateRepForce(angleOfForce, labelLists[m][u].weight);
560 
561  }
562  else
563  {
564  if (labelLists[m][u].angle > labelLists[m][j].angle)
565  {
566  //Kraft kommt auch von rechts
567  labelLists[m][j].dispAngle = labelLists[m][j].dispAngle - calculateRepForce(angleOfForce, labelLists[m][u].weight);
568 
569  }
570  else
571  {
572  //Kraft kommt von links
573  labelLists[m][j].dispAngle = labelLists[m][j].dispAngle + calculateRepForce(angleOfForce, labelLists[m][u].weight);
574 
575  }
576  }
577  }
578  else
579  {
580  if (labelLists[m][u].angle > labelLists[m][j].angle + 180)
581  {
582  //Kraft kommt von links
583  labelLists[m][j].dispAngle = labelLists[m][j].dispAngle + calculateRepForce(angleOfForce, labelLists[m][u].weight);
584  }
585  else
586  {
587  if (labelLists[m][u].angle < labelLists[m][j].angle)
588  {
589  //kraft kommt von links
590  labelLists[m][j].dispAngle = labelLists[m][j].dispAngle + calculateRepForce(angleOfForce, labelLists[m][u].weight);
591  }
592  else
593  { //kraft kommt von rechts
594  labelLists[m][j].dispAngle = labelLists[m][j].dispAngle - calculateRepForce(angleOfForce, labelLists[m][u].weight);
595  }
596  }
597  }
598  }
599  }
600  }
601  }
602  }
603  }
604  }
605  }
606  applyForcesOnLabels(zoomPlane, whichPlane);
607  }
608  }
609  }
610 
619  private void applyForcesOnLabels(bool zoomPlane, bool[] whichPlane)
620  {
621  for (int m = 0; m < labelLists.Length; m++)
622  {
623  if (whichPlane[m])
624  {
625  calculateEnergy(whichPlane);
626  float maxDispAngle = energyOfPlanes[m];
627 
628  for (int j = 0; j < labelLists[m].Count; j++)
629  {
630  float angleToRight = 0;
631  float angleToLeft = 0;
632 
633  if(labelLists[m][j].rightLabel.angle > labelLists[m][j].angle)
634  {
635  angleToRight = labelLists[m][j].rightLabel.angle - labelLists[m][j].angle;
636  }
637  else
638  {
639  angleToRight = (360 - labelLists[m][j].angle) + labelLists[m][j].rightLabel.angle;
640  }
641 
642  if(labelLists[m][j].angle > labelLists[m][j].leftLabel.angle)
643  {
644  angleToLeft = labelLists[m][j].angle - labelLists[m][j].leftLabel.angle;
645  }
646  else
647  {
648  angleToLeft = (360 - labelLists[m][j].leftLabel.angle) + labelLists[m][j].angle;
649  }
650 
651  labelLists[m][j].angleToLeftLabel = angleToLeft;
652  labelLists[m][j].angleToRightLabel = angleToRight;
653 
654  if (labelLists[m][j].dispAngle > 0)
655  {
656 
657  if (labelLists[m][j].angleToLeftLabel < labelLists[m][j].dispAngle)
658  {
659 
660  labelLists[m][j].dispAngle = labelLists[m][j].angleToLeftLabel;
661 
662  if (labelLists[m][j].dispAngle > maxDispAngle)
663  {
664  labelLists[m][j].dispAngle = maxDispAngle;
665  }
666  }
667  else
668  {
669  if (labelLists[m][j].dispAngle > maxDispAngle)
670  {
671  labelLists[m][j].dispAngle = maxDispAngle;
672  }
673  }
674  }
675  else
676  {
677 
678  if (-labelLists[m][j].angleToRightLabel > labelLists[m][j].dispAngle)
679  {
680  labelLists[m][j].dispAngle = -(labelLists[m][j].angleToRightLabel);
681 
682  if (labelLists[m][j].dispAngle < (-maxDispAngle))
683  {
684  labelLists[m][j].dispAngle = -maxDispAngle;
685  }
686  }
687  else
688  {
689  if (labelLists[m][j].dispAngle < (-maxDispAngle))
690  {
691  labelLists[m][j].dispAngle = -maxDispAngle;
692  }
693  }
694  }
695 
696  labelLists[m][j].dispAngle = labelLists[m][j].dispAngle * Mathf.Deg2Rad;
697 
698  float xNew = labelLists[m][j].x * Mathf.Cos(labelLists[m][j].dispAngle) - labelLists[m][j].y * Mathf.Sin(labelLists[m][j].dispAngle);
699  float yNew = labelLists[m][j].x * Mathf.Sin(labelLists[m][j].dispAngle) + labelLists[m][j].y * Mathf.Cos(labelLists[m][j].dispAngle);
700 
701  labelLists[m][j].y = yNew;
702  labelLists[m][j].x = xNew;
703 
704  labelLists[m][j].position = labelPlaneVectors[m].origin + yNew * labelPlaneVectors[m].y + xNew * labelPlaneVectors[m].x;
705 
706  float angle = Vector3.Angle(labelLists[m][j].position - labelPlaneVectors[m].origin, labelPlaneVectors[m].origin + 2 * labelPlaneVectors[m].y);
707 
708 
709  if (labelLists[m][j].x >= 0)
710  {
711 
712  }
713  else
714  {
715  angle = 360 - angle;
716  }
717 
718  labelLists[m][j].angle = angle;
719  labelLists[m][j].dispAngle = 0;
720 
721  float newRadius = getInitialPlaneRadius(m);
722 
723  labelLists[m][j].calculateCornersOnPlane(meshNode, meshPositionNode, meshViewerBase);
724  labelLists[m][j].calculateAngleToLeftAndRight(labelPlaneVectors[m].x, labelPlaneVectors[m].y, labelPlaneVectors[m].origin);
725 
726 
727  if (!zoomPlane)
728  {
729  if(m == 2)
730  {
731  newRadius = findSmallestPossibleRadius(labelLists[m][j]);
732  }
733 
734  if (newRadius > getInitialPlaneRadius(m))
735  {
736  newRadius = getInitialPlaneRadius(m);
737  }
738  }
739 
740  float offset = 0;
741 
742  /*if (!zoomPlane)
743  {
744  offset = labelLists[m][j].calculateOffset2();
745  }*/
746  newRadius = newRadius + offset;
747 
748  labelLists[m][j].position = labelPlaneVectors[m].origin + newRadius * (labelLists[m][j].position - labelPlaneVectors[m].origin).normalized;
749 
750  labelLists[m][j].y = Vector3.Dot(labelLists[m][j].position - labelPlaneVectors[m].origin, labelPlaneVectors[m].y);
751  labelLists[m][j].x = Vector3.Dot(labelLists[m][j].position - labelPlaneVectors[m].origin, labelPlaneVectors[m].x);
752 
753  labelLists[m][j].calculateCornersOnPlane(meshNode, meshPositionNode, meshViewerBase);
754  labelLists[m][j].calculateAngleToLeftAndRight(labelPlaneVectors[m].x, labelPlaneVectors[m].y, labelPlaneVectors[m].origin);
755 
756  labelLists[m][j].calculateWeight(weightAngleSizeRatio);
757 
758  labelLists[m][j].moveToNewPosition();
759  }
760  }
761  }
762  }
763 
764 
765 
773  private float calculateRepForce(float distance, float k)
774  {
775  float magnitude;
776 
777  if (distance > 0)
778  {
779  magnitude = -(k * k ) / distance;
780  }
781  else
782  {
783  magnitude = -(k * k) / 0.001f;
784  }
785  return magnitude;
786  }
787 
788 
796  private void createPlanes(float zoomPlaneDistance)
797  {
798  Vector3 center = meshNode.transform.position;
799  center = meshBox.center;
800 
801  Vector3 planesNormal = (center - Camera.main.transform.position).normalized;
802 
803  float distanceBetweenPointPlanes = bSphere.radius / 2;
804 
805  Vector3 xAxis = planesNormal; //xAxis zeigt vom Mittelpunkt nach rechts
806  Vector3 yAxis = planesNormal; //YAxis zeigt vom Mittelpunkt nach oben
807  Vector3 zAxis = planesNormal; //zAxis zeigt vom Mittelpunkt nach hinten
808  Vector3.OrthoNormalize(ref zAxis, ref yAxis, ref xAxis); // hier wird die Y-Achse leider umgedreht, daher wird sie bei verwendung wieder umgedreht
809 
810  //Debug.DrawLine(center, center - 5 * yAxis);
811  //Debug.DrawLine(center, center + 5 * zAxis, Color.red, 10);
812  //Debug.DrawLine(center, center + 5 * xAxis);
813 
814  //Fläche 1 hinterste ebene
815  pointPlanes[0] = new Plane();
816  pointPlanes[0].SetNormalAndPosition(planesNormal, center + (planesNormal * distanceBetweenPointPlanes));
817 
818  labelPlanes[0] = new Plane();
819  labelPlanes[0].SetNormalAndPosition(planesNormal, center + (planesNormal * distanceBetweenPointPlanes * 2));
820 
821  pointPlaneVectors[0] = new PlaneVectors(xAxis, -yAxis, zAxis, center + (planesNormal * distanceBetweenPointPlanes));
822  labelPlaneVectors[0] = new PlaneVectors(xAxis, -yAxis, zAxis, center + (planesNormal * distanceBetweenPointPlanes * 2));
823 
824  //Fläche 2 mittlere ebene
825  pointPlanes[1] = new Plane();
826  pointPlanes[1].SetNormalAndPosition(planesNormal, center);
827 
828  labelPlanes[1] = new Plane();
829  labelPlanes[1].SetNormalAndPosition(planesNormal, center);
830 
831  pointPlaneVectors[1] = new PlaneVectors(xAxis, -yAxis, zAxis, center);
832  labelPlaneVectors[1] = new PlaneVectors(xAxis, -yAxis, zAxis, center);
833 
834  //Fläche 3 vordere ebene
835  pointPlanes[2] = new Plane();
836  pointPlanes[2].SetNormalAndPosition(planesNormal, center - (planesNormal * distanceBetweenPointPlanes));
837 
838  labelPlanes[2] = new Plane();
839  labelPlanes[2].SetNormalAndPosition(planesNormal, center - (planesNormal * distanceBetweenPointPlanes * 2));
840 
841  pointPlaneVectors[2] = new PlaneVectors(xAxis, -yAxis, zAxis, center - (planesNormal * distanceBetweenPointPlanes));
842  labelPlaneVectors[2] = new PlaneVectors(xAxis, -yAxis, zAxis, center - (planesNormal * distanceBetweenPointPlanes * 2));
843 
844 
845  //Fläche 4 Zoomebene
846  RaycastHit hit = new RaycastHit();
847 
848  int layerMask = 1 << 9; //Layer 9 for MeshViewerLayer
849 
850  float maxDistance = (Camera.main.transform.position - meshBox.center).magnitude;
851 
852 
853 
854  Ray ray = new Ray(Camera.main.transform.position, meshBox.center - Camera.main.transform.position);
855  Physics.Raycast(ray, out hit, maxDistance, layerMask);
856 
857 
858  Vector3 zoomPlaneLabelCenter = Camera.main.transform.position + zoomPlaneDistance * planesNormal;
859  Vector3 zoomPlanePointCenter = hit.point;
860 
861  Debug.DrawLine(Camera.main.transform.position, zoomPlanePointCenter);
862 
863 
864  pointPlanes[3] = new Plane();
865  pointPlanes[3].SetNormalAndPosition(planesNormal, zoomPlanePointCenter);
866 
867  labelPlanes[3] = new Plane();
868  labelPlanes[3].SetNormalAndPosition(planesNormal, zoomPlaneLabelCenter);
869 
870  pointPlaneVectors[3] = new PlaneVectors(xAxis, -yAxis, zAxis, zoomPlanePointCenter);
871  labelPlaneVectors[3] = new PlaneVectors(xAxis, -yAxis, zAxis, zoomPlaneLabelCenter);
872 
873  }
874 
882  private void calculateCenterOfZoomPlane(List<Point> listOfPointsInZoomPlane)
883  {
884  float yCenter = 0;
885  float xCenter = 0;
886 
887  foreach (Point p in listOfPointsInZoomPlane)
888  {
889  yCenter += p.y;
890  xCenter += p.x;
891  }
892  if (listOfPointsInZoomPlane.Count != 0)
893  {
894  yCenter = yCenter / listOfPointsInZoomPlane.Count;
895  xCenter = xCenter / listOfPointsInZoomPlane.Count;
896  }
897 
898  labelPlaneVectors[3].origin = labelPlaneVectors[3].origin + labelPlaneVectors[3].y * yCenter + labelPlaneVectors[3].x * xCenter;
899  pointPlaneVectors[3].origin = pointPlaneVectors[3].origin + labelPlaneVectors[3].y * yCenter + labelPlaneVectors[3].x * xCenter;
900 
901 
902  for (int i = 0; i < pointsOnPlane[3].Count; i++)
903  {
904  Point p = orthoProjectPointOnPlane(pointsOnPlane[3][i].annotationPoint.transform.position, 3, labelPlaneVectors[3], labelPlanes[3]);
905  pointsOnPlane[3][i].position = p.position;
906  pointsOnPlane[3][i].angle = p.angle;
907  pointsOnPlane[3][i].x = p.x;
908  pointsOnPlane[3][i].y = p.y;
909  pointsOnPlane[3][i].z = p.z;
910 
911  Vector3 pointProjectedOnCircle = labelPlaneVectors[3].origin + initialPlaneRadius[3] * (p.position - labelPlaneVectors[3].origin).normalized;
912  float y = Vector3.Dot(pointProjectedOnCircle - labelPlaneVectors[3].origin, labelPlaneVectors[3].y);
913  float x = Vector3.Dot(pointProjectedOnCircle - labelPlaneVectors[3].origin, labelPlaneVectors[3].x);
914 
915  pointsOnPlane[3][i].label.position = pointProjectedOnCircle;
916  pointsOnPlane[3][i].label.x = x;
917  pointsOnPlane[3][i].label.y = y;
918  pointsOnPlane[3][i].label.angle = p.angle;
919  }
920 
921 
922  sortListsByAngle(new bool[] { false, false, false, true });
923  }
924 
934  private int updateWhichPlaneForPoint(GameObject annoPoint, bool zoomPlane, bool middlePlane)
935  {
936 
937  Vector3 pointPosition = annoPoint.transform.position;
938  //hier wird bestimmt welche Fläche welchem Punkt am nächsten liegt
939  //float d1 = pointPlanes[0].GetDistanceToPoint(pointPosition);
940  //d1 = Mathf.Abs(d1);
941  float d2 = pointPlanes[1].GetDistanceToPoint(pointPosition);
942  //d2 = Mathf.Abs(d2);
943  float d3 = pointPlanes[2].GetDistanceToPoint(pointPosition);
944  //d3 = Mathf.Abs(d3);
945  float d4 = pointPlanes[3].GetDistanceToPoint(pointPosition);
946  d4 = Mathf.Abs(d4);
947 
948 
949  //wertet aus zu welcher Ebene der punkt den geringsten abstand hat
950 
951  float depth = 0.8f; // bei der zoomebene wird eine ebene auf der oberfläche des dargestellten objekts platziert und anschließend wird geprüft welche punkt innerhalb eines kreis auf dieser ebene liegt
952  //da dargestelltes objekt dreidimensional wird zusätzlich noch der abstand in z richtung bestimmt un gepüft ob der punkt nah genug an der ebene dran ist
953 
954 
955  if (zoomPlane)
956  {
957  // punkt gehört in ebene 3 oder in die Blickfeldebene
958  Point p = orthoProjectPointOnPlane(annoPoint.transform.position, 3, pointPlaneVectors[3], pointPlanes[3]);
959  if ((p.x * p.x + p.y * p.y) < zoomPlaneDetectionRadius * zoomPlaneDetectionRadius && d4 <= depth)
960  {
961  //point is in fieldofVision, ebene 4
962  return 3;
963  }
964  else
965  {
966  return 0;
967  }
968  }
969  else
970  {
971  if(d2 > 0)
972  {
973  return 0;
974  }
975  else
976  {
977  if(Mathf.Abs(d3) <= Mathf.Abs(d2))
978  {
979  return 2;
980  }
981  else
982  {
983  if (middlePlane)
984  {
985  return 1;
986  }
987  else
988  {
989  return 0; //nur labels in der vorderen ebene werden angezeigt
990  }
991  }
992  }
993  }
994 
995  }
996 
1004  private float getInitialPlaneRadius(int planeNumber)
1005  {
1006  initialPlaneRadius[0] = 0;
1007  initialPlaneRadius[1] = bSphere.radius * 1.05f;
1008  initialPlaneRadius[2] = bSphere.radius;
1009  initialPlaneRadius[3] = zoomPlaneDistance * Mathf.Tan(1.4f) / 8; //hier wird der radius des sichtfelds einer person berechnet. 1.4f in rad sind 80 grad. 80 grad ist die hälfte vom sichtfeld
1010 
1011  return initialPlaneRadius[planeNumber];
1012  }
1013 
1018  private void createBoundingBox()
1019  {
1020  //Transform child1 = meshPositionNode.transform.GetChild(0);
1021  //Transform childchild1 = child1.GetChild(0);
1022  //MeshRenderer mesh = childchild1.GetComponent<MeshRenderer>();
1023  MeshRenderer mesh = new MeshRenderer();
1024 
1025  meshBox = new Bounds(meshNode.transform.position, Vector3.zero);
1026  bSphere = new BoundingSphere();
1027 
1028  for (int i = 0; i < meshPositionNode.transform.childCount; i++)
1029  {
1030  Transform child = meshPositionNode.transform.GetChild(i);
1031 
1032  if (child.tag != "Annotation")
1033  {
1034 
1035  for (int j = 0; j < child.childCount; j++)
1036  {
1037 
1038  Transform childChild = child.GetChild(j);
1039 
1040  mesh = childChild.GetComponent<MeshRenderer>();
1041 
1042  if (mesh != null)
1043  {
1044  meshBox.Encapsulate(mesh.bounds); //merged alle boundingboxes zu einer großen
1045  }
1046 
1047  }
1048  }
1049  }
1050  bSphere.position = meshBox.center;
1051  bSphere.radius = Mathf.Max(meshBox.extents.x, meshBox.extents.y, meshBox.center.z);
1052 
1053  //Debug.Log(meshBox.extents);
1054 
1055  //Debug.Log(meshBox.center);
1056  //drawBox();
1057 
1058  }
1059 
1060  private void drawPlane()
1061  {
1062  Vector3 y = pointPlaneVectors[0].y;
1063  Vector3 z = pointPlaneVectors[0].z;
1064  y = y.normalized;
1065  z = z.normalized;
1066  Debug.DrawLine(pointPlaneVectors[0].origin + (2 * z + 2 * y), pointPlaneVectors[0].origin + (2 * z - 2 * y), Color.red, 5f);
1067  Debug.DrawLine(pointPlaneVectors[0].origin + (2 * z - 2 * y), pointPlaneVectors[0].origin + (- 2 * z - 2 * y), Color.red, 5f);
1068  Debug.DrawLine(pointPlaneVectors[0].origin + (- 2 * z - 2 * y), pointPlaneVectors[0].origin + (- 2 * z + 2 * y), Color.red, 5f);
1069  Debug.DrawLine(pointPlaneVectors[0].origin + (- 2 * z + 2 * y), pointPlaneVectors[0].origin + (2 * z + 2 * y), Color.red, 5f);
1070  }
1071 
1083  private Point orthoProjectPointOnPlane(Vector3 pointPosition, int planeNumber, PlaneVectors planeVector, Plane plane)
1084  {
1085  Point p = new Point();
1086  float y;
1087  float x;
1088  Vector3 pointPos = pointPosition;
1089  Vector3 planeOrigin = planeVector.origin;
1090  Vector3 planeNormal = planeVector.z;
1091 
1092  //hier wird eine orthogonalprojektion von einem Punkt auf eine Fläche durchgeführt
1093 
1094  float distance = plane.GetDistanceToPoint(pointPos); //hier wird der kürzeste Abstand vom punkt zur fläche bestimmt
1095  distance *= -1;
1096  Vector3 projectedPoint = pointPos + planeNormal * distance;
1097 
1098  //Skalarprodukt ist orthogonalprojektion von einem Vektor auf einen anderen
1099  // x und y koordinaten in der Fläche des projezierten Punktes
1100  y = Vector3.Dot(projectedPoint - planeOrigin, planeVector.y);
1101  x = Vector3.Dot(projectedPoint - planeOrigin, planeVector.x);
1102 
1103  //Winkelberechnung
1104  //Vector3.Angle gibt einen winkel zwischen 0 und 180 grad zurück. Benötigt wird ein Winkel zwischen 0 und 360 grad.
1105  //Es wird geprüft ob der punkt links oder rechts von der Y-Achse liegt. Abhängig davon kann man den Winkel auf die 360 hochrechnen
1106 
1107  float angle = Vector3.Angle(projectedPoint - planeOrigin, planeOrigin + 2 * planeVector.y);
1108 
1109  if (x >= 0)
1110  {
1111 
1112  }
1113  else
1114  {
1115  angle = 360 - angle;
1116  }
1117 
1118  p.y = y;
1119  p.x = x;
1120 
1121  p.planeNumber = planeNumber;
1122  p.position = projectedPoint;
1123  p.angle = angle;
1124 
1125  //Debug.DrawLine(pointPlaneVectors[planeNumber].origin, pointPlaneVectors[planeNumber].origin + z * pointPlaneVectors[planeNumber].z);
1126  //Debug.DrawLine(pointPlaneVectors[planeNumber].origin, pointPlaneVectors[planeNumber].origin + y * pointPlaneVectors[planeNumber].y);
1127  //Debug.DrawLine(pointPlaneVectors[planeNumber].origin, projectedPoint);
1128 
1129  return p;
1130  }
1131 
1132  private void OnDrawGizmos()
1133  {
1134  Gizmos.DrawWireCube(meshBox.center, meshBox.size);
1135  }
1136 
1145  private bool overlapLabelOnLabel(Label li, Label lj)
1146  {
1147  float[] overlap = new float[2];
1148  float widthi = 0;
1149  float heighti = 0;
1150  float widthj = 0;
1151  float heightj = 0;
1152 
1153  GameObject labeli = li.annotationLabel;
1154  GameObject labelj = lj.annotationLabel;
1155 
1156  if (labeli != null && labelj != null)
1157  {
1158 
1159  widthi = labeli.GetComponent<RectTransform>().rect.width * labeli.GetComponent<RectTransform>().localScale.x * labeli.transform.parent.localScale.x * meshNode.transform.localScale.x * meshPositionNode.transform.localScale.x * meshViewerBase.transform.localScale.x;
1160  heighti = labeli.GetComponent<RectTransform>().rect.height * labeli.GetComponent<RectTransform>().localScale.x * labeli.transform.parent.localScale.x * meshNode.transform.localScale.x * meshPositionNode.transform.localScale.x * meshViewerBase.transform.localScale.x;
1161  widthj = labelj.GetComponent<RectTransform>().rect.width * labelj.GetComponent<RectTransform>().localScale.x * labeli.transform.parent.localScale.x * meshNode.transform.localScale.x * meshPositionNode.transform.localScale.x * meshViewerBase.transform.localScale.x;
1162  heightj = labelj.GetComponent<RectTransform>().rect.height * labelj.GetComponent<RectTransform>().localScale.x * labeli.transform.parent.localScale.x * meshNode.transform.localScale.x * meshPositionNode.transform.localScale.x * meshViewerBase.transform.localScale.x;
1163  }
1164 
1165  //daten für i Object
1166  float yi = li.y;
1167  float xi = li.x;
1168 
1169  //Debug.Log(widthi);
1170 
1171  //daten für j Object
1172  float yj = lj.y;
1173  float xj = lj.x;
1174 
1175  //overlap in y richtung
1176 
1177  if (yi == yj)
1178  {
1179  overlap[0] = 1;
1180  }
1181  else if (Mathf.Abs(yi - yj) <= ((heighti / 2) + (heightj / 2)))
1182  {
1183  overlap[0] = 1;
1184  }
1185  else{
1186  overlap[0] = 0;
1187  }
1188 
1189  //overlap in z richtung
1190 
1191  if (xi == xj)
1192  {
1193  overlap[1] = 1;
1194  }
1195  else if (Mathf.Abs(xi - xj) <= ((widthi / 2) + (widthj / 2)))
1196  {
1197  overlap[1] = 1;
1198  }
1199  else{
1200  overlap[1] = 0;
1201  }
1202 
1203  if (overlap[0] == 1 && overlap[1] == 1)
1204  {
1205  return true;
1206  }
1207  else
1208  {
1209  return false;
1210  }
1211 
1212  }
1213 
1220  private void calculateEnergy(bool[] whichPlanes)
1221  {
1222  for (int p = 0; p < labelLists.Length; p++)
1223  {
1224  if (whichPlanes[p])
1225  {
1226  energyOfPlanes[p] = 0;
1227 
1228  for (int j = 0; j < labelLists[p].Count; j++)
1229  {
1230  for (int l = j; l < labelLists[p].Count; l++)
1231  {
1232  if (j != l)
1233  {
1234  if (overlapLabelOnLabel(labelLists[p][j], labelLists[p][l]))
1235  {
1236  energyOfPlanes[p]++;
1237  }
1238  }
1239  }
1240  }
1241  }
1242  }
1243  }
1244 
1254  private float calculateSilouhette(Vector3 position, Camera cam, Texture2D image, int planeNumber)
1255  {
1256  float radius = 0;
1257  float maxRadius = getInitialPlaneRadius(planeNumber);
1258 
1259  //position und das zentrum der Ebene werden auf die Silhouette kameraebene projiziert
1260 
1261  Vector3 centerIn3DOnCamPlane = cam.WorldToScreenPoint(labelPlaneVectors[1].origin);
1262  Vector2 centerIn2D = new Vector2(centerIn3DOnCamPlane.x, centerIn3DOnCamPlane.y);
1263 
1264  float distance = centerIn3DOnCamPlane.z;
1265 
1266 
1267 
1268  Vector3 pointPosIn3D = cam.WorldToScreenPoint(position);
1269  Vector2 pointPosIn2D = new Vector2(pointPosIn3D.x, pointPosIn3D.y);
1270 
1271 
1272 
1273  Vector2 pEdge = bresenhamLine((int)pointPosIn2D.x, (int)pointPosIn2D.y, (int)centerIn2D.x, (int)centerIn2D.y, image);
1274 
1275  Vector3 pEdgeInWorld = cam.ScreenToWorldPoint(new Vector3(pEdge.x, pEdge.y, distance));
1276 
1277  Vector3 centerIn3DInWorld = cam.ScreenToWorldPoint(centerIn3DOnCamPlane);
1278  centerIn3DInWorld = labelPlaneVectors[1].origin;
1279 
1280  radius = (pEdgeInWorld - centerIn3DInWorld).magnitude;
1281 
1282  if(radius <= 0)
1283  {
1284  radius = maxRadius;
1285  }
1286  else if(radius > maxRadius)
1287  {
1288  radius = maxRadius;
1289  }
1290 
1291  //Debug.DrawLine(centerIn3DInWorld, centerIn3DInWorld + ((pEdgeInWorld- centerIn3DInWorld).normalized * radius), Color.red, 0.020f);
1292  Debug.DrawRay(centerIn3DInWorld, (pEdgeInWorld - centerIn3DInWorld).normalized * radius, Color.red, 0.20f);
1293 
1294  return radius;
1295  }
1296 
1307  private Vector2 bresenhamLine(int x, int y, int x2, int y2, Texture2D image)
1308  {
1309  int w = x2 - x;
1310  int h = y2 - y;
1311  int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0;
1312  if (w < 0) dx1 = -1; else if (w > 0) dx1 = 1;
1313  if (h < 0) dy1 = -1; else if (h > 0) dy1 = 1;
1314  if (w < 0) dx2 = -1; else if (w > 0) dx2 = 1;
1315  int longest = Mathf.Abs(w);
1316  int shortest = Mathf.Abs(h);
1317  if (!(longest > shortest))
1318  {
1319  longest = Mathf.Abs(h);
1320  shortest = Mathf.Abs(w);
1321  if (h < 0) dy2 = -1; else if (h > 0) dy2 = 1;
1322  dx2 = 0;
1323  }
1324  int numerator = longest >> 1;
1325 
1326  for (int i = 0; i <= longest; i++)
1327  {
1328 
1329 
1330  if (image.GetPixel(x, y) != Color.white)
1331  {
1332  image.SetPixel(x, y, Color.blue);
1333 
1334  //for (int n = 0; n < 5; n++)
1335  //{
1336  //image.SetPixel(x, y + n, Color.blue);
1337  //image.SetPixel(x + n, y, Color.blue);
1338  //image.SetPixel(x, y - n, Color.blue);
1339  //image.SetPixel(x - n, y, Color.blue);
1340 
1341  //image.SetPixel(x + n, y + n, Color.blue);
1342  //image.SetPixel(x - n, y - n, Color.blue);
1343  //image.SetPixel(x + n, y - n, Color.blue);
1344  //image.SetPixel(x - n, y + n, Color.blue);
1345 
1346  //}
1347 
1348  Vector2 pos = new Vector2(x, y);
1349  return pos;
1350  }
1351  else
1352  {
1353  //image.SetPixel(x, y, Color.red);
1354  //image.SetPixel(x, y + 1, Color.red);
1355  //image.SetPixel(x + 1, y, Color.red);
1356  //image.SetPixel(x, y - 1, Color.red);
1357  //image.SetPixel(x - 1, y, Color.red);
1358 
1359  //image.SetPixel(x2, y2, Color.red);
1360  //image.SetPixel(x2, y2 + 1, Color.red);
1361  //image.SetPixel(x2 + 1, y2, Color.red);
1362  //image.SetPixel(x2, y2 - 1, Color.red);
1363  //image.SetPixel(x2 - 1, y2, Color.red);
1364 
1365  numerator += shortest;
1366  if (!(numerator < longest))
1367  {
1368  numerator -= longest;
1369  x += dx1;
1370  y += dy1;
1371  }
1372  else
1373  {
1374  x += dx2;
1375  y += dy2;
1376  }
1377  }
1378 
1379 
1380  }
1381 
1382  Vector2 center = new Vector2(0, 0);
1383 
1384  return center;
1385  }
1386 
1392  private void takePicture()
1393  {
1394  //hier wird eine Kamera erstellt welche ein Bild nur von den Objekten macht welche auf der "MeshViewer" layer liegen
1395  //aus diesem Bild wird die Silhouette brechnet
1396 
1397 
1398  //RenderTexture currentRT = RenderTexture.active;
1399  RenderTexture.active = silhouetteCam.targetTexture;
1400  silhouetteCam.Render();
1401  silhouetteImage = new Texture2D(silhouetteCam.targetTexture.width, silhouetteCam.targetTexture.height);
1402  silhouetteImage.ReadPixels(new Rect(0, 0, silhouetteCam.targetTexture.width, silhouetteCam.targetTexture.height), 0, 0);
1403  silhouetteImage.Apply();
1404  //RenderTexture.active = currentRT;
1405  }
1406 
1411  private void drawPicture()
1412  {
1413  //draw Picture
1414  Byte[] b = silhouetteImage.EncodeToPNG();
1415 
1416  File.WriteAllBytes("C:/Users/Ben/Desktop/Image.png", b);
1417  }
1418 
1423  private void createPie() // hier werden Kuchenstücke erstellt um die Silhouette zu berechnen. Jedes Kuchenstück hat einen eigenen Radius
1424  {
1425  Point p = new Point();
1426 
1427  p.y = bSphere.radius;
1428  p.position = labelPlaneVectors[1].origin + (initialPlaneRadius[1]) * labelPlaneVectors[1].y;
1429  p.x = 0;
1430  p.z = 0;
1431  float xNew;
1432  float yNew;
1433  float rotangle;
1434 
1435  for (int i = 0; i < rads.Length; i++)
1436  {
1437 
1438  rads[rads.Length - 1 - i] = (((Camera.main.transform.position - labelPlaneVectors[2].origin).magnitude) * calculateSilouhette(p.position, silhouetteCam, silhouetteImage, 1)) / ((Camera.main.transform.position - meshBox.center).magnitude);
1439 
1440  rotangle = 1 * Mathf.Deg2Rad;
1441 
1442  xNew = p.x * Mathf.Cos(rotangle) - p.y * Mathf.Sin(rotangle);
1443  yNew = p.x * Mathf.Sin(rotangle) + p.y * Mathf.Cos(rotangle);
1444 
1445  p.x = xNew;
1446  p.y = yNew;
1447 
1448  p.position = labelPlaneVectors[1].origin + labelPlaneVectors[1].y * p.y + labelPlaneVectors[1].x * p.x;
1449  }
1450  }
1451 
1459  private float findSmallestPossibleRadius(Label l)
1460  {
1461  int angleSize = (int) (l.angleToLeftAndRightCorner[0] + l.angleToLeftAndRightCorner[1]);
1462 
1463  if(angleSize <= 0)
1464  {
1465  angleSize = 1;
1466  }
1467 
1468  int startAngle;
1469 
1470  if(l.angleToLeftAndRightCorner[0] < l.angle)
1471  {
1472  startAngle = (int)(l.angle - l.angleToLeftAndRightCorner[0]);
1473 
1474  }
1475  else
1476  {
1477  startAngle = 360 - Mathf.Abs((int)(l.angle - l.angleToLeftAndRightCorner[0]));
1478 
1479  }
1480 
1481  float[] rads1 = new float[angleSize];
1482 
1483 
1484  if((startAngle + angleSize) < 360)
1485  {
1486  for (int i = 0; i < angleSize; i++)
1487  {
1488 
1489  rads1[i] = rads[startAngle + i];
1490 
1491  }
1492  }
1493  else
1494  {
1495  for (int i = 0; i < 360 - startAngle; i++)
1496  {
1497 
1498  rads1[i] = rads[startAngle + i];
1499  }
1500 
1501  for(int i = 0; i < angleSize - (360 - startAngle); i++)
1502  {
1503 
1504  float ko = rads[i];
1505  rads1[(360 - startAngle) + i] = ko;
1506  }
1507 
1508  }
1509  Array.Sort(rads1);
1510 
1511  return rads1[rads1.Length - 1];
1512  }
1513 }
float[] angleToLeftAndRightCorner
Definition: Label.cs:20
LabelPositioner.
Point.
Definition: Point.cs:8
GameObject annotationPoint
Definition: Point.cs:15
float zoomPlaneDetectionRadius
Label.
Definition: Label.cs:11
float angle
Definition: Point.cs:12
void updateAnnotationList(List< GameObject > annoList)
Called by Annotation Control to update Annotation List when it changes
Camera silhouetteCamPrefab
Vector3 position
Definition: Point.cs:11
float weightAngleSizeRatio