1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.geometry.fov;
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.hipparchus.geometry.euclidean.threed.Line;
23 import org.hipparchus.geometry.euclidean.threed.Vector3D;
24 import org.hipparchus.util.FastMath;
25 import org.hipparchus.util.MathUtils;
26 import org.orekit.bodies.GeodeticPoint;
27 import org.orekit.bodies.OneAxisEllipsoid;
28 import org.orekit.errors.OrekitException;
29 import org.orekit.errors.OrekitMessages;
30 import org.orekit.frames.Frame;
31 import org.orekit.frames.Transform;
32 import org.orekit.propagation.events.VisibilityTrigger;
33
34
35
36
37
38 public abstract class SmoothFieldOfView extends AbstractFieldOfView {
39
40
41 private final Vector3D center;
42
43
44 private final Vector3D xAxis;
45
46
47 private final Vector3D yAxis;
48
49
50 private final Vector3D zAxis;
51
52
53
54
55
56
57
58
59
60
61 protected SmoothFieldOfView(final Vector3D center, final Vector3D primaryMeridian,
62 final double margin) {
63
64 super(margin);
65
66 this.center = center;
67 this.zAxis = center.normalize();
68 this.yAxis = Vector3D.crossProduct(center, primaryMeridian).normalize();
69 this.xAxis = Vector3D.crossProduct(yAxis, center).normalize();
70
71 }
72
73
74
75
76 public Vector3D getCenter() {
77 return center;
78 }
79
80
81
82
83 public Vector3D getX() {
84 return xAxis;
85 }
86
87
88
89
90 public Vector3D getY() {
91 return yAxis;
92 }
93
94
95
96
97 public Vector3D getZ() {
98 return zAxis;
99 }
100
101
102
103 @Override
104 public List<List<GeodeticPoint>> getFootprint(final Transform fovToBody,
105 final OneAxisEllipsoid body,
106 final double angularStep) {
107
108 final Frame bodyFrame = body.getBodyFrame();
109 final Vector3D position = fovToBody.transformPosition(Vector3D.ZERO);
110 final double r = position.getNorm();
111 if (body.isInside(position)) {
112 throw new OrekitException(OrekitMessages.POINT_INSIDE_ELLIPSOID);
113 }
114
115
116 boolean intersectionsFound = false;
117 final int nbPoints = (int) FastMath.ceil(MathUtils.TWO_PI / angularStep);
118 final List<GeodeticPoint> loop = new ArrayList<>(nbPoints);
119
120
121 final double step = MathUtils.TWO_PI / nbPoints;
122 for (int i = 0; i < nbPoints; ++i) {
123 final Vector3D direction = directionAt(-i * step);
124 final Vector3D awaySC = new Vector3D(r, direction);
125 final Vector3D awayBody = fovToBody.transformPosition(awaySC);
126 final Line lineOfSight = new Line(position, awayBody, 1.0e-3);
127 GeodeticPoint gp = body.getIntersectionPoint(lineOfSight, position, bodyFrame, null);
128 if (gp != null &&
129 Vector3D.dotProduct(awayBody.subtract(position), body.transform(gp).subtract(position)) < 0) {
130
131
132 gp = null;
133 }
134
135 if (gp != null) {
136
137 intersectionsFound = true;
138 } else {
139
140
141 gp = body.transform(body.pointOnLimb(position, awayBody), bodyFrame, null);
142 }
143
144
145 loop.add(gp);
146
147 }
148
149 final List<List<GeodeticPoint>> footprint = new ArrayList<>();
150 if (intersectionsFound) {
151
152 footprint.add(loop);
153 } else {
154
155
156
157 final Vector3D bodyCenter = fovToBody.getInverse().transformPosition(Vector3D.ZERO);
158 if (offsetFromBoundary(bodyCenter, 0.0, VisibilityTrigger.VISIBLE_ONLY_WHEN_FULLY_IN_FOV) < 0.0) {
159
160
161 footprint.add(loop);
162 }
163 }
164
165 return footprint;
166
167 }
168
169
170
171
172
173 protected abstract Vector3D directionAt(double angle);
174
175 }