Updated to worldwind release 20070817
[worldwind-tracker.git] / gov / nasa / worldwind / view / OrbitViewModel.java
blobab0d41465c7aa18e9f71f50e2da10ecf41a1f96b
1 /*
2 Copyright (C) 2001, 2006 United States Government as represented by
3 the Administrator of the National Aeronautics and Space Administration.
4 All Rights Reserved.
5 */
6 package gov.nasa.worldwind.view;
8 import gov.nasa.worldwind.geom.*;
9 import gov.nasa.worldwind.globes.Globe;
10 import gov.nasa.worldwind.render.DrawContext;
11 import gov.nasa.worldwind.util.Logging;
13 /**
14 * @author dcollins
15 * @version $Id: OrbitViewModel.java 2503 2007-08-03 23:22:10Z dcollins $
17 class OrbitViewModel
19 private Matrix transformMatrix = null;
21 public OrbitViewModel(DrawContext dc)
23 this(dc, Angle.ZERO, Angle.ZERO, Angle.ZERO, Angle.ZERO, 0);
26 public OrbitViewModel(DrawContext dc,
27 Angle latitude, Angle longitude,
28 Angle heading, Angle pitch,
29 double altitude)
31 this(dc, createInitTransform(
32 dc,
33 latitude, longitude,
34 heading, pitch,
35 altitude));
38 public OrbitViewModel(DrawContext dc, Matrix transformMatrix)
40 if (dc == null)
42 String message = Logging.getMessage("nullValue.DrawContextIsNull");
43 Logging.logger().severe(message);
44 throw new IllegalArgumentException(message);
46 if (transformMatrix == null)
48 String message = Logging.getMessage("nullValue.MatrixIsNull");
49 Logging.logger().severe(message);
50 throw new IllegalArgumentException(message);
53 this.setTransform(dc, transformMatrix);
56 public Matrix getTransformMatrix()
58 return this.transformMatrix;
61 private void onTransformChange(DrawContext dc, Matrix newTransformMatrix)
65 public void setTransform(DrawContext dc, Matrix newTransformMatrix)
67 if (dc == null)
69 String message = Logging.getMessage("nullValue.DrawContextIsNull");
70 Logging.logger().severe(message);
71 throw new IllegalArgumentException(message);
73 if (newTransformMatrix == null)
75 String message = Logging.getMessage("nullValue.MatrixIsNull");
76 Logging.logger().severe(message);
77 throw new IllegalArgumentException(message);
80 this.transformMatrix = newTransformMatrix;
81 this.onTransformChange(dc, newTransformMatrix);
84 public void transform(DrawContext dc, Matrix transformMatrix)
86 if (dc == null)
88 String message = Logging.getMessage("nullValue.DrawContextIsNull");
89 Logging.logger().severe(message);
90 throw new IllegalArgumentException(message);
92 if (transformMatrix == null)
94 String message = Logging.getMessage("nullValue.MatrixIsNull");
95 Logging.logger().severe(message);
96 throw new IllegalArgumentException(message);
99 if (this.transformMatrix == null)
100 return;
102 Matrix newTransformMatrix = this.transformMatrix.multiply(transformMatrix);
103 this.setTransform(dc, newTransformMatrix);
106 public void transformLatitude(DrawContext dc, Angle amount)
108 if (dc == null)
110 String message = Logging.getMessage("nullValue.DrawContextIsNull");
111 Logging.logger().severe(message);
112 throw new IllegalArgumentException(message);
114 if (amount == null)
116 String message = Logging.getMessage("nullValue.AngleIsNull");
117 Logging.logger().severe(message);
118 throw new IllegalArgumentException(message);
121 Matrix latTransform = this.createLatitudeTransform(dc, amount);
122 if (latTransform == null)
123 return;
125 if (this.transformMatrix == null)
126 return;
128 // Test transform application.
129 Matrix newTransformMatrix = this.transformMatrix.multiply(latTransform);
130 Vec4 center = computeLookAtPoint(dc, this.transformMatrix);
131 Vec4 newCenter = computeLookAtPoint(dc, newTransformMatrix);
132 Position centerPos = dc.getGlobe().computePositionFromPoint(center);
133 Position newCenterPos = dc.getGlobe().computePositionFromPoint(newCenter);
134 // Abort the transform when it causes model errors.
135 final double EPSILON = 1e-10;
136 if (Math.abs(newCenterPos.getLongitude().subtract(centerPos.getLongitude()).degrees) > EPSILON)
137 return;
139 this.transform(dc, latTransform);
142 public void transformLongitude(DrawContext dc, Angle amount)
144 if (dc == null)
146 String message = Logging.getMessage("nullValue.DrawContextIsNull");
147 Logging.logger().severe(message);
148 throw new IllegalArgumentException(message);
150 if (amount == null)
152 String message = Logging.getMessage("nullValue.AngleIsNull");
153 Logging.logger().severe(message);
154 throw new IllegalArgumentException(message);
157 Matrix lonTransform = this.createLongitudeTransform(dc, amount);
158 if (lonTransform == null)
159 return;
161 this.transform(dc, lonTransform);
164 public void transformAltitude(DrawContext dc, double amount)
166 if (dc == null)
168 String message = Logging.getMessage("nullValue.DrawContextIsNull");
169 Logging.logger().severe(message);
170 throw new IllegalArgumentException(message);
173 Matrix altTransform = this.createAltitudeTransform(dc, amount);
174 if (altTransform == null)
175 return;
177 this.transform(dc, altTransform);
180 public void transformHeading(DrawContext dc, Angle amount)
182 if (dc == null)
184 String message = Logging.getMessage("nullValue.DrawContextIsNull");
185 Logging.logger().severe(message);
186 throw new IllegalArgumentException(message);
188 if (amount == null)
190 String message = Logging.getMessage("nullValue.AngleIsNull");
191 Logging.logger().severe(message);
192 throw new IllegalArgumentException(message);
195 Matrix headingTransform = this.createHeadingTransform(dc, amount);
196 if (headingTransform == null)
197 return;
199 this.transform(dc, headingTransform);
202 public void transformPitch(DrawContext dc, Angle amount)
204 if (dc == null)
206 String message = Logging.getMessage("nullValue.DrawContextIsNull");
207 Logging.logger().severe(message);
208 throw new IllegalArgumentException(message);
210 if (amount == null)
212 String message = Logging.getMessage("nullValue.AngleIsNull");
213 Logging.logger().severe(message);
214 throw new IllegalArgumentException(message);
217 Matrix pitchTransform = this.createPitchTransform(dc, amount);
218 if (pitchTransform == null)
219 return;
221 if (this.transformMatrix == null)
222 return;
224 // Test transform application.
225 Matrix newTransformMatrix = this.transformMatrix.multiply(pitchTransform);
226 Vec4 centerVec = computeLookAtPoint(dc, this.transformMatrix);
227 Vec4 newHeading = computeHeadingVector(newTransformMatrix, centerVec);
228 Vec4 newForward = Vec4.UNIT_NEGATIVE_Z.transformBy3(newTransformMatrix.getInverse());
229 // Abort the transform when it causes model errors.
230 if (newHeading.dot3(newForward) < 0)
231 return;
233 this.transform(dc, pitchTransform);
236 public void transformZoom(DrawContext dc, double amount)
238 if (dc == null)
240 String message = Logging.getMessage("nullValue.DrawContextIsNull");
241 Logging.logger().severe(message);
242 throw new IllegalArgumentException(message);
245 Matrix zoomTransform = this.createZoomTransform(dc, amount);
246 if (zoomTransform == null)
247 return;
249 this.transform(dc, zoomTransform);
252 public Quaternion getRotation()
254 return Quaternion.fromMatrix(this.transformMatrix);
257 public void setRotation(DrawContext dc, Quaternion newRotation)
259 if (dc == null)
261 String message = Logging.getMessage("nullValue.DrawContextIsNull");
262 Logging.logger().severe(message);
263 throw new IllegalArgumentException(message);
265 if (newRotation == null)
267 String message = Logging.getMessage("nullValue.QuaternionIsNull");
268 Logging.logger().severe(message);
269 throw new IllegalArgumentException(message);
272 if (this.transformMatrix == null)
273 return;
275 Matrix posMatrix = Matrix.fromTranslation(
276 this.transformMatrix.m14,
277 this.transformMatrix.m24,
278 this.transformMatrix.m34);
279 Matrix rotMatrix = Matrix.fromQuaternion(newRotation);
280 Matrix newTransformMatrix = posMatrix.multiply(rotMatrix);
281 this.setTransform(dc, newTransformMatrix);
284 public void transformRotation(DrawContext dc, Quaternion rotation)
286 if (dc == null)
288 String message = Logging.getMessage("nullValue.DrawContextIsNull");
289 Logging.logger().severe(message);
290 throw new IllegalArgumentException(message);
292 if (rotation == null)
294 String message = Logging.getMessage("nullValue.QuaternionIsNull");
295 Logging.logger().severe(message);
296 throw new IllegalArgumentException(message);
299 Quaternion transformRotation = Quaternion.fromMatrix(this.transformMatrix);
300 Quaternion newTransformRotation = transformRotation.multiply(rotation);
301 this.setRotation(dc, newTransformRotation);
304 // ============== Model Transforms ======================= //
305 // ============== Model Transforms ======================= //
306 // ============== Model Transforms ======================= //
308 private static Matrix createInitTransform(
309 DrawContext dc,
310 Angle latitude, Angle longitude,
311 Angle heading, Angle pitch,
312 double altitude)
314 if (dc == null
315 || dc.getGlobe() == null
316 || latitude == null
317 || longitude == null
318 || heading == null
319 || pitch == null)
320 return null;
322 Globe globe = dc.getGlobe();
323 // Vec4 globeOrigin = globe.getCenter();
324 Matrix initTransform = Matrix.IDENTITY;
325 // Not sure why this isn't necessary, but when globeOrigin!=0 View is still centered on the Globe,
326 // without this code.
327 // initTransform = initTransform.multiply(Matrix.fromTranslation(
328 // globeOrigin.x,
329 // globeOrigin.y,
330 // globeOrigin.z));
331 initTransform = initTransform.multiply(Matrix.fromTranslation(
332 0.0,
333 0.0,
334 0.0 - globe.getRadiusAt(latitude, longitude)));
335 initTransform = initTransform.multiply(Matrix.fromRotationX(heading.multiply(-1)));
336 initTransform = initTransform.multiply(Matrix.fromRotationZ(pitch));
337 initTransform = initTransform.multiply(Matrix.fromTranslation(
338 0.0,
339 0.0,
340 0.0 - altitude));
341 initTransform = initTransform.multiply(Matrix.fromRotationX(latitude));
342 initTransform = initTransform.multiply(Matrix.fromRotationY(longitude.multiply(-1)));
344 return initTransform;
347 public Matrix createLatitudeTransform(DrawContext dc, Angle amount)
349 if (dc == null)
351 String message = Logging.getMessage("nullValue.DrawContextIsNull");
352 Logging.logger().severe(message);
353 throw new IllegalArgumentException(message);
355 if (amount == null)
357 String message = Logging.getMessage("nullValue.AngleIsNull");
358 Logging.logger().severe(message);
359 throw new IllegalArgumentException(message);
362 Vec4 centerVec = this.getLookAtVector(dc);
363 if (centerVec == null)
364 return null;
366 Vec4 surfaceNormal = centerVec.normalize3();
367 Vec4 axis = Vec4.UNIT_Y.cross3(surfaceNormal);
368 return Matrix.fromAxisAngle(amount, axis);
371 public Matrix createLongitudeTransform(DrawContext dc, Angle amount)
373 if (dc == null)
375 String message = Logging.getMessage("nullValue.DrawContextIsNull");
376 Logging.logger().severe(message);
377 throw new IllegalArgumentException(message);
379 if (amount == null)
381 String message = Logging.getMessage("nullValue.AngleIsNull");
382 Logging.logger().severe(message);
383 throw new IllegalArgumentException(message);
386 Vec4 axis = Vec4.UNIT_Y;
387 return Matrix.fromAxisAngle(amount.multiply(-1), axis);
390 public Matrix createAltitudeTransform(DrawContext dc, double amount)
392 if (dc == null)
394 String message = Logging.getMessage("nullValue.DrawContextIsNull");
395 Logging.logger().severe(message);
396 throw new IllegalArgumentException(message);
399 Vec4 altVec = this.getEyeVector();
400 if (altVec == null)
401 return null;
403 altVec = altVec.normalize3();
404 altVec = altVec.multiply3(-amount);
405 return Matrix.fromTranslation(altVec);
408 public Matrix createHeadingTransform(DrawContext dc, Angle amount)
410 if (dc == null)
412 String message = Logging.getMessage("nullValue.DrawContextIsNull");
413 Logging.logger().severe(message);
414 throw new IllegalArgumentException(message);
416 if (amount == null)
418 String message = Logging.getMessage("nullValue.AngleIsNull");
419 Logging.logger().severe(message);
420 throw new IllegalArgumentException(message);
423 Vec4 centerVec = this.getLookAtVector(dc);
424 if (centerVec == null)
425 return null;
427 Vec4 axis = centerVec.normalize3();
428 Matrix axisAngleTransform = Matrix.fromAxisAngle(amount, axis);
429 return this.createTransformAboutPivot(axisAngleTransform, centerVec);
432 public Matrix createPitchTransform(DrawContext dc, Angle amount)
434 if (dc == null)
436 String message = Logging.getMessage("nullValue.DrawContextIsNull");
437 Logging.logger().severe(message);
438 throw new IllegalArgumentException(message);
440 if (amount == null)
442 String message = Logging.getMessage("nullValue.AngleIsNull");
443 Logging.logger().severe(message);
444 throw new IllegalArgumentException(message);
447 if (this.transformMatrix == null)
448 return null;
450 Vec4 centerVec = this.getLookAtVector(dc);
451 if (centerVec == null)
452 return null;
454 Vec4 axis = Vec4.UNIT_X.transformBy3(this.transformMatrix.getInverse());
455 Matrix axisAngleTransform = Matrix.fromAxisAngle(amount.multiply(-1), axis);
456 return this.createTransformAboutPivot(axisAngleTransform, centerVec);
459 public Matrix createZoomTransform(DrawContext dc, double amount)
461 if (dc == null)
463 String message = Logging.getMessage("nullValue.DrawContextIsNull");
464 Logging.logger().severe(message);
465 throw new IllegalArgumentException(message);
468 if (this.transformMatrix == null)
469 return null;
471 Vec4 zoomVec = Vec4.UNIT_NEGATIVE_Z.transformBy3(this.transformMatrix.getInverse());
472 zoomVec = zoomVec.normalize3();
473 zoomVec = zoomVec.multiply3(amount);
474 return Matrix.fromTranslation(zoomVec);
477 private Matrix createTransformAboutPivot(Matrix transform, Vec4 pivot)
479 if (transform == null || pivot == null)
480 return null;
482 Matrix matrix = Matrix.IDENTITY;
483 matrix = matrix.multiply(Matrix.fromTranslation(pivot.x, pivot.y, pivot.z));
484 matrix = matrix.multiply(transform);
485 matrix = matrix.multiply(Matrix.fromTranslation(-pivot.x, -pivot.y, -pivot.z));
486 return matrix;
489 // ============== Rotation Transforms ======================= //
490 // ============== Rotation Transforms ======================= //
491 // ============== Rotation Transforms ======================= //
493 public Quaternion createRotationBetweenPositions(DrawContext dc, Position beginPosition, Position endPosition)
495 if (dc == null)
497 String message = Logging.getMessage("nullValue.DrawContextIsNull");
498 Logging.logger().severe(message);
499 throw new IllegalArgumentException(message);
501 if (beginPosition == null || endPosition == null)
503 String message = Logging.getMessage("nullValue.PositionIsNull");
504 Logging.logger().severe(message);
505 throw new IllegalArgumentException(message);
508 Globe globe = dc.getGlobe();
509 if (globe == null)
510 return null;
512 Vec4 beginPoint = globe.computePointFromPosition(beginPosition);
513 Vec4 endPoint = globe.computePointFromPosition(endPosition);
514 if (beginPoint == null || endPoint == null)
515 return null;
517 Angle angle = beginPoint.angleBetween3(endPoint);
518 if (angle == null)
519 return null;
521 Vec4 axis = beginPoint.cross3(endPoint);
522 return Quaternion.fromAxisAngle(angle, axis);
525 public Quaternion createRotationForward(DrawContext dc, Angle amount)
527 if (amount == null)
529 String message = Logging.getMessage("nullValue.AngleIsNull");
530 Logging.logger().severe(message);
531 throw new IllegalArgumentException(message);
534 if (this.transformMatrix == null)
535 return null;
537 Vec4 xAxis = Vec4.UNIT_X.transformBy3(this.transformMatrix.getInverse());
538 return Quaternion.fromAxisAngle(amount, xAxis);
541 public Quaternion createRotationRight(DrawContext dc, Angle amount)
543 if (amount == null)
545 String message = Logging.getMessage("nullValue.AngleIsNull");
546 Logging.logger().severe(message);
547 throw new IllegalArgumentException(message);
550 if (this.transformMatrix == null)
551 return null;
553 Vec4 xAxis = Vec4.UNIT_X.transformBy3(this.transformMatrix.getInverse());
554 Vec4 centerVec = this.getLookAtVector(dc);
555 centerVec = centerVec.normalize3();
556 Vec4 yAxisNoTilt = centerVec.cross3(xAxis);
557 return Quaternion.fromAxisAngle(amount.multiply(-1), yAxisNoTilt);
560 // ============== Viewing Attributes ======================= //
561 // ============== Viewing Attributes ======================= //
562 // ============== Viewing Attributes ======================= //
564 public Vec4 getEyeVector()
566 if (this.transformMatrix == null)
567 return null;
569 return Vec4.UNIT_W.transformBy4(this.transformMatrix.getInverse());
572 public Position getEyePosition(DrawContext dc)
574 if (dc == null)
576 String message = Logging.getMessage("nullValue.DrawContextIsNull");
577 Logging.logger().severe(message);
578 throw new IllegalArgumentException(message);
581 Vec4 eyeVec = this.getEyeVector();
582 if (eyeVec == null)
583 return null;
585 if (dc.getGlobe() == null)
586 return null;
588 return dc.getGlobe().computePositionFromPoint(eyeVec);
591 public Vec4 getLookAtVector(DrawContext dc)
593 if (dc == null)
595 String message = Logging.getMessage("nullValue.DrawContextIsNull");
596 Logging.logger().severe(message);
597 throw new IllegalArgumentException(message);
600 if (this.transformMatrix == null)
601 return null;
603 return computeLookAtPoint(dc, this.transformMatrix);
606 public Position getLookAtPosition(DrawContext dc)
608 if (dc == null)
610 String message = Logging.getMessage("nullValue.DrawContextIsNull");
611 Logging.logger().severe(message);
612 throw new IllegalArgumentException(message);
615 Vec4 centerVec = this.getLookAtVector(dc);
616 if (centerVec == null)
617 return null;
619 if (dc.getGlobe() == null)
620 return null;
622 return dc.getGlobe().computePositionFromPoint(centerVec);
625 public Angle getHeading(DrawContext dc)
627 if (dc == null)
629 String message = Logging.getMessage("nullValue.DrawContextIsNull");
630 Logging.logger().severe(message);
631 throw new IllegalArgumentException(message);
634 if (this.transformMatrix == null)
635 return null;
637 Vec4 centerVec = this.getLookAtVector(dc);
638 if (centerVec == null)
639 return null;
641 HeadingCoordinates headingCoordinates = computeHeadingCoordinates(centerVec);
642 if (headingCoordinates == null)
643 return null;
645 return computeHeading(headingCoordinates, this.transformMatrix, centerVec);
648 public Angle getPitch(DrawContext dc)
650 if (dc == null)
652 String message = Logging.getMessage("nullValue.DrawContextIsNull");
653 Logging.logger().severe(message);
654 throw new IllegalArgumentException(message);
657 if (this.transformMatrix == null)
658 return null;
660 Vec4 centerVec = this.getLookAtVector(dc);
661 if (centerVec == null)
662 return null;
664 return computePitch(this.transformMatrix, centerVec);
667 public Double getZoom(DrawContext dc)
669 if (dc == null)
671 String message = Logging.getMessage("nullValue.DrawContextIsNull");
672 Logging.logger().severe(message);
673 throw new IllegalArgumentException(message);
676 if (this.transformMatrix == null)
677 return null;
679 Vec4 centerVec = this.getLookAtVector(dc);
680 if (centerVec == null)
681 return null;
683 return computeZoom(this.transformMatrix, centerVec);
686 // ============== Attribute Computation Support ======================= //
687 // ============== Attribute Computation Support ======================= //
688 // ============== Attribute Computation Support ======================= //
690 private static Vec4 computeLookAtPoint(DrawContext dc, Matrix transformMatrix)
692 if (dc == null
693 || dc.getGlobe() == null
694 || transformMatrix == null)
695 return null;
697 Globe globe = dc.getGlobe();
698 Vec4 eyeVec = Vec4.UNIT_W.transformBy4(transformMatrix.getInverse());
699 Vec4 forwardVec = Vec4.UNIT_NEGATIVE_Z.transformBy3(transformMatrix.getInverse());
700 forwardVec = forwardVec.normalize3();
702 Position centerPos = globe.getIntersectionPosition(new Line(eyeVec, forwardVec));
703 if (centerPos == null)
704 return computeHorizonPoint(globe, transformMatrix);
706 Angle centerLat = centerPos.getLatitude();
707 Angle centerLon = centerPos.getLongitude();
708 double centerElevation = dc.getVerticalExaggeration() * globe.getElevation(centerLat, centerLon);
709 return globe.computePointFromPosition(centerLat, centerLon, centerElevation);
712 private static Vec4 computeHorizonPoint(Globe globe, Matrix transformMatrix)
714 if (globe == null || transformMatrix == null)
715 return null;
717 Vec4 globeOrigin = globe.getCenter();
718 Vec4 eyeVec = Vec4.UNIT_W.transformBy4(transformMatrix.getInverse());
719 Vec4 forward = Vec4.UNIT_NEGATIVE_Z.transformBy3(transformMatrix.getInverse());
720 Vec4 origin_sub_eye = globeOrigin.subtract3(eyeVec);
722 double r = globe.getRadius();
723 double dSquared = origin_sub_eye.getLengthSquared3() - (r * r);
724 if (dSquared < 0)
725 return null;
727 double d = Math.sqrt(dSquared);
728 return forward.normalize3().multiply3(d).add3(eyeVec);
731 private static Angle computeHeading(HeadingCoordinates headingCoords, Matrix transformMatrix, Vec4 lookAtPoint)
733 if (headingCoords == null
734 || transformMatrix == null
735 || lookAtPoint == null)
736 return null;
738 Vec4 heading = computeHeadingVector(transformMatrix, lookAtPoint);
740 double dot = headingCoords.north.dot3(heading);
741 // Compute the sum of magnitudes.
742 double length = headingCoords.north.getLength3() * heading.getLength3();
743 // Normalize the dot product, if necessary.
744 if ((length != 0) && (length != 1.0))
745 dot /= length;
747 if (dot < -1) // Angle is positive 180.
749 return Angle.POS180;
751 else if (dot > 1) // Angle is zero.
753 return Angle.ZERO;
756 double degrees = Math.toDegrees(Math.acos(dot));
757 if (Double.isNaN(degrees))
758 return null;
760 if (headingCoords.east.dot3(heading) < 0)
761 degrees = 360 - degrees;
763 // Collapses duplicate values for North heading.
764 if (degrees == 360)
765 degrees = 0;
767 return Angle.fromDegrees(degrees);
770 private static class HeadingCoordinates
772 public final Vec4 north;
773 public final Vec4 east;
775 public HeadingCoordinates(Vec4 north, Vec4 east)
777 this.north = north;
778 this.east = east;
782 private static HeadingCoordinates computeHeadingCoordinates(Vec4 lookAtPoint)
784 if (lookAtPoint == null)
785 return null;
787 Vec4 surfaceNormal = lookAtPoint.normalize3();
788 Vec4 y_sub_normal = Vec4.UNIT_Y.subtract3(surfaceNormal);
789 y_sub_normal = y_sub_normal.normalize3();
790 Vec4 eastVec = y_sub_normal.cross3(surfaceNormal);
791 Vec4 northVec = surfaceNormal.cross3(eastVec);
792 eastVec = northVec.cross3(surfaceNormal);
794 return new HeadingCoordinates(northVec, eastVec);
797 private static Vec4 computeHeadingVector(Matrix transformMatrix, Vec4 surfacePoint)
799 if (transformMatrix == null || surfacePoint == null)
800 return null;
802 Vec4 surfaceNormal = surfacePoint.normalize3();
803 Vec4 forward = Vec4.UNIT_NEGATIVE_Z.transformBy3(transformMatrix.getInverse());
804 Vec4 up = Vec4.UNIT_Y.transformBy3(transformMatrix.getInverse());
806 final double EPSILON = 0.1;
807 Vec4 heading = forward.cross3(surfaceNormal);
808 if (heading.getLength3() < EPSILON)
809 heading = up.cross3(surfaceNormal);
810 heading = surfaceNormal.cross3(heading);
811 heading = heading.normalize3();
813 return heading;
816 private static Angle computePitch(Matrix transformMatrix, Vec4 lookAtPoint)
818 if (transformMatrix == null || lookAtPoint == null)
819 return null;
821 Vec4 surfaceNormal = lookAtPoint.normalize3();
822 Vec4 forward = Vec4.UNIT_Z.transformBy3(transformMatrix.getInverse());
823 forward = forward.normalize3();
825 double dot = surfaceNormal.dot3(forward);
826 // Compute the sum of magnitudes.
827 double length = surfaceNormal.getLength3() * forward.getLength3();
828 // Normalize the dot product, if necessary.
829 if ((length != 0) && (length != 1))
830 dot /= length;
832 if (dot <= 0) // Angle is positive 90.
834 return Angle.POS90;
836 else if (dot >= 1) // Angle is zero.
838 return Angle.ZERO;
840 else // Angle is arc-cosine of dot product.
842 double radians = Math.acos(dot);
843 if (!Double.isNaN(radians))
844 return Angle.fromRadians(radians);
847 return null;
850 private static Double computeZoom(Matrix transformMatrix, Vec4 lookAtPoint)
852 if (transformMatrix == null || lookAtPoint == null)
853 return null;
855 Vec4 eyeVec = Vec4.UNIT_W.transformBy4(transformMatrix.getInverse());
856 return lookAtPoint.subtract3(eyeVec).getLength3();
859 // private static class SurfaceAttributes
860 // {
861 // public final Vec4 center;
862 // public final Position centerPos;
863 // public final Vec4 north;
864 // public final Vec4 east;
866 // public SurfaceAttributes(Vec4 centerVec, Position centerPos, Vec4 headingUp, Vec4 headingRight)
867 // {
868 // this.center = centerVec;
869 // this.centerPos = centerPos;
870 // this.north = headingUp;
871 // this.east = headingRight;
872 // }
873 // }
875 // private static SurfaceAttributes computeSurfaceAttributes(DrawContext dc, Matrix transformMatrix)
876 // {
877 // if (dc == null || dc.getGlobe() == null)
878 // return null;
880 // if (transformMatrix == null)
881 // return null;
883 // Globe globe = dc.getGlobe();
884 // Vec4 eyeVec = Vec4.UNIT_W.transformBy4(transformMatrix.getInverse());
885 // Vec4 forwardVec = Vec4.UNIT_NEGATIVE_Z.transformBy3(transformMatrix.getInverse());
886 // forwardVec = forwardVec.normalize3();
888 // Vec4 centerVec;
889 // Position centerPos = globe.getIntersectionPosition(new Line(eyeVec, forwardVec));
890 // if (centerPos != null)
891 // {
892 // Angle centerLat = centerPos.getLatitude();
893 // Angle centerLon = centerPos.getLongitude();
894 // double centerElevation = dc.getVerticalExaggeration() * globe.getElevation(centerLat, centerLon);
895 // centerVec = globe.computePointFromPosition(centerLat, centerLon, centerElevation);
896 // }
897 // else
898 // {
899 // centerVec = computeHorizonPoint(globe, transformMatrix);
900 // centerPos = globe.computePositionFromPoint(centerVec);
901 // }
903 // if (centerVec == null)
904 // return null;
906 // Vec4 normalVec = centerVec.normalize3();
908 // Vec4 y_sub_normal = Vec4.UNIT_Y.subtract3(normalVec);
909 // y_sub_normal = y_sub_normal.normalize3();
910 // Vec4 headingRight = y_sub_normal.cross3(normalVec);
911 // Vec4 headingUp = normalVec.cross3(headingRight);
912 // headingRight = headingUp.cross3(normalVec);
914 // return new SurfaceAttributes(centerVec, centerPos, headingUp.normalize3(), headingRight.normalize3());
915 // }