Search in sources :

Example 6 with S2Point

use of org.hipparchus.geometry.spherical.twod.S2Point in project Orekit by CS-SI.

the class Mesh method addNode.

/**
 * Add a node.
 * <p>
 * This method is similar to {@link #getNode(int, int) getNode} except
 * it creates the node if it doesn't alreay exists. All created nodes
 * have a status set to {@code disabled}.
 * </p>
 * @param alongIndex index in the along direction
 * @param acrossIndex index in the across direction
 * @return node at specified indices, guaranteed to be non-null
 * @exception OrekitException if tile direction cannot be computed
 * @see #getNode(int, int)
 */
public Node addNode(final int alongIndex, final int acrossIndex) throws OrekitException {
    // create intermediate (disabled) nodes, up to specified indices
    Node node = getExistingAncestor(alongIndex, acrossIndex);
    while (node.getAlongIndex() != alongIndex || node.getAcrossIndex() != acrossIndex) {
        final Direction direction;
        if (node.getAlongIndex() < alongIndex) {
            direction = Direction.PLUS_ALONG;
        } else if (node.getAlongIndex() > alongIndex) {
            direction = Direction.MINUS_ALONG;
        } else if (node.getAcrossIndex() < acrossIndex) {
            direction = Direction.PLUS_ACROSS;
        } else {
            direction = Direction.MINUS_ACROSS;
        }
        final S2Point s2p = node.move(direction.motion(node, alongGap, acrossGap));
        node = new Node(s2p, direction.neighborAlongIndex(node), direction.neighborAcrossIndex(node));
        store(node);
    }
    return node;
}
Also used : S2Point(org.hipparchus.geometry.spherical.twod.S2Point)

Example 7 with S2Point

use of org.hipparchus.geometry.spherical.twod.S2Point in project Orekit by CS-SI.

the class FieldOfViewTest method testSerialization.

@Test
public void testSerialization() throws IOException, ClassNotFoundException {
    FieldOfView fov = new FieldOfView(new SphericalPolygonsSet(1.0e-12, new S2Point(Vector3D.PLUS_I), new S2Point(Vector3D.PLUS_J), new S2Point(Vector3D.PLUS_K)), 0.001);
    Assert.assertEquals(0.5 * FastMath.PI, fov.getZone().getSize(), 1.0e-15);
    Assert.assertEquals(1.5 * FastMath.PI, fov.getZone().getBoundarySize(), 1.0e-15);
    Assert.assertEquals(0.001, fov.getMargin(), 1.0e-15);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(fov);
    Assert.assertTrue(bos.size() > 400);
    Assert.assertTrue(bos.size() < 450);
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bis);
    FieldOfView deserialized = (FieldOfView) ois.readObject();
    Assert.assertEquals(0.5 * FastMath.PI, deserialized.getZone().getSize(), 1.0e-15);
    Assert.assertEquals(1.5 * FastMath.PI, deserialized.getZone().getBoundarySize(), 1.0e-15);
    Assert.assertEquals(0.001, deserialized.getMargin(), 1.0e-15);
}
Also used : S2Point(org.hipparchus.geometry.spherical.twod.S2Point) ByteArrayInputStream(java.io.ByteArrayInputStream) SphericalPolygonsSet(org.hipparchus.geometry.spherical.twod.SphericalPolygonsSet) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ObjectOutputStream(java.io.ObjectOutputStream) ObjectInputStream(java.io.ObjectInputStream) Test(org.junit.Test)

Example 8 with S2Point

use of org.hipparchus.geometry.spherical.twod.S2Point in project Orekit by CS-SI.

the class Mesh method getCoverage.

/**
 * Get the zone covered by the mesh.
 * @return mesh coverage
 */
public SphericalPolygonsSet getCoverage() {
    if (coverage == null) {
        // lazy build of mesh coverage
        final List<Mesh.Node> boundary = getTaxicabBoundary(true);
        final S2Point[] vertices = new S2Point[boundary.size()];
        for (int i = 0; i < vertices.length; ++i) {
            vertices[i] = boundary.get(i).getS2P();
        }
        coverage = new SphericalPolygonsSet(zone.getTolerance(), vertices);
    }
    // as caller may modify the BSP tree, we must provide a copy of our safe instance
    return (SphericalPolygonsSet) coverage.copySelf();
}
Also used : S2Point(org.hipparchus.geometry.spherical.twod.S2Point) SphericalPolygonsSet(org.hipparchus.geometry.spherical.twod.SphericalPolygonsSet) S2Point(org.hipparchus.geometry.spherical.twod.S2Point) GeodeticPoint(org.orekit.bodies.GeodeticPoint)

Example 9 with S2Point

use of org.hipparchus.geometry.spherical.twod.S2Point in project Orekit by CS-SI.

the class FieldOfView method getFootprint.

/**
 * Get the footprint of the field Of View on ground.
 * <p>
 * This method assumes the Field Of View is centered on some carrier,
 * which will typically be a spacecraft or a ground station antenna.
 * The points in the footprint boundary loops are all at altitude zero
 * with respect to the ellipsoid, they correspond either to projection
 * on ground of the edges of the Field Of View, or to points on the body
 * limb if the Field Of View goes past horizon. The points on the limb
 * see the carrier origin at zero elevation. If the Field Of View is so
 * large it contains entirely the body, all points will correspond to
 * points at limb. If the Field Of View looks away from body, the
 * boundary loops will be an empty list. The points within footprint
 * the loops are sorted in trigonometric order as seen from the carrier.
 * This implies that someone traveling on ground from one point to the
 * next one will have the points visible from the carrier on his left
 * hand side, and the points not visible from the carrier on his right
 * hand side.
 * </p>
 * <p>
 * The truncation of Field Of View at limb can induce strange results
 * for complex Fields Of View. If for example a Field Of View is a
 * ring with a hole and part of the ring goes past horizon, then instead
 * of having a single loop with a C-shaped boundary, the method will
 * still return two loops truncated at the limb, one clockwise and one
 * counterclockwise, hence "closing" the C-shape twice. This behavior
 * is considered acceptable.
 * </p>
 * <p>
 * If the carrier is a spacecraft, then the {@code fovToBody} transform
 * can be computed from a {@link org.orekit.propagation.SpacecraftState}
 * as follows:
 * </p>
 * <pre>
 * Transform inertToBody = state.getFrame().getTransformTo(body.getBodyFrame(), state.getDate());
 * Transform fovToBody   = new Transform(state.getDate(),
 *                                       state.toTransform().getInverse(),
 *                                       inertToBody);
 * </pre>
 * <p>
 * If the carrier is a ground station, located using a topocentric frame
 * and managing its pointing direction using a transform between the
 * dish frame and the topocentric frame, then the {@code fovToBody} transform
 * can be computed as follows:
 * </p>
 * <pre>
 * Transform topoToBody = topocentricFrame.getTransformTo(body.getBodyFrame(), date);
 * Transform topoToDish = ...
 * Transform fovToBody  = new Transform(date,
 *                                      topoToDish.getInverse(),
 *                                      topoToBody);
 * </pre>
 * <p>
 * Only the raw zone is used, the angular margin is ignored here.
 * </p>
 * @param fovToBody transform between the frame in which the Field Of View
 * is defined and body frame.
 * @param body body surface the Field Of View will be projected on
 * @param angularStep step used for boundary loops sampling (radians)
 * @return list footprint boundary loops (there may be several independent
 * loops if the Field Of View shape is complex)
 * @throws OrekitException if some frame conversion fails or if carrier is
 * below body surface
 */
List<List<GeodeticPoint>> getFootprint(final Transform fovToBody, final OneAxisEllipsoid body, final double angularStep) throws OrekitException {
    final Frame bodyFrame = body.getBodyFrame();
    final Vector3D position = fovToBody.transformPosition(Vector3D.ZERO);
    final double r = position.getNorm();
    if (body.isInside(position)) {
        throw new OrekitException(OrekitMessages.POINT_INSIDE_ELLIPSOID);
    }
    final List<List<GeodeticPoint>> footprint = new ArrayList<List<GeodeticPoint>>();
    final List<Vertex> boundary = zone.getBoundaryLoops();
    for (final Vertex loopStart : boundary) {
        int count = 0;
        final List<GeodeticPoint> loop = new ArrayList<GeodeticPoint>();
        boolean intersectionsFound = false;
        for (Edge edge = loopStart.getOutgoing(); count == 0 || edge.getStart() != loopStart; edge = edge.getEnd().getOutgoing()) {
            ++count;
            final int n = (int) FastMath.ceil(edge.getLength() / angularStep);
            final double delta = edge.getLength() / n;
            for (int i = 0; i < n; ++i) {
                final Vector3D awaySC = new Vector3D(r, edge.getPointAt(i * delta));
                final Vector3D awayBody = fovToBody.transformPosition(awaySC);
                final Line lineOfSight = new Line(position, awayBody, 1.0e-3);
                GeodeticPoint gp = body.getIntersectionPoint(lineOfSight, position, bodyFrame, null);
                if (gp != null && Vector3D.dotProduct(awayBody.subtract(position), body.transform(gp).subtract(position)) < 0) {
                    // the intersection is in fact on the half-line pointing
                    // towards the back side, it is a spurious intersection
                    gp = null;
                }
                if (gp != null) {
                    // the line of sight does intersect the body
                    intersectionsFound = true;
                } else {
                    // the line of sight does not intersect body
                    // we use a point on the limb
                    gp = body.transform(body.pointOnLimb(position, awayBody), bodyFrame, null);
                }
                // add the point in front of the list
                // (to ensure the loop will be in trigonometric orientation)
                loop.add(0, gp);
            }
        }
        if (intersectionsFound) {
            // at least some of the points did intersect the body,
            // this loop contributes to the footprint
            footprint.add(loop);
        }
    }
    if (footprint.isEmpty()) {
        // none of the Field Of View loops cross the body
        // either the body is outside of Field Of View, or it is fully contained
        // we check the center
        final Vector3D bodyCenter = fovToBody.getInverse().transformPosition(Vector3D.ZERO);
        if (zone.checkPoint(new S2Point(bodyCenter)) != Region.Location.OUTSIDE) {
            // the body is fully contained in the Field Of View
            // we use the full limb as the footprint
            final Vector3D x = bodyCenter.orthogonal();
            final Vector3D y = Vector3D.crossProduct(bodyCenter, x).normalize();
            final double sinEta = body.getEquatorialRadius() / r;
            final double sinEta2 = sinEta * sinEta;
            final double cosAlpha = (FastMath.cos(angularStep) + sinEta2 - 1) / sinEta2;
            final int n = (int) FastMath.ceil(MathUtils.TWO_PI / FastMath.acos(cosAlpha));
            final double delta = MathUtils.TWO_PI / n;
            final List<GeodeticPoint> loop = new ArrayList<GeodeticPoint>(n);
            for (int i = 0; i < n; ++i) {
                final Vector3D outside = new Vector3D(r * FastMath.cos(i * delta), x, r * FastMath.sin(i * delta), y);
                loop.add(body.transform(body.pointOnLimb(position, outside), bodyFrame, null));
            }
            footprint.add(loop);
        }
    }
    return footprint;
}
Also used : Vertex(org.hipparchus.geometry.spherical.twod.Vertex) Frame(org.orekit.frames.Frame) S2Point(org.hipparchus.geometry.spherical.twod.S2Point) ArrayList(java.util.ArrayList) S2Point(org.hipparchus.geometry.spherical.twod.S2Point) GeodeticPoint(org.orekit.bodies.GeodeticPoint) Line(org.hipparchus.geometry.euclidean.threed.Line) Vector3D(org.hipparchus.geometry.euclidean.threed.Vector3D) OrekitException(org.orekit.errors.OrekitException) ArrayList(java.util.ArrayList) List(java.util.List) GeodeticPoint(org.orekit.bodies.GeodeticPoint) Edge(org.hipparchus.geometry.spherical.twod.Edge)

Example 10 with S2Point

use of org.hipparchus.geometry.spherical.twod.S2Point in project Orekit by CS-SI.

the class FieldOfView method offsetFromBoundary.

/**
 * Get the angular offset of target point with respect to the Field Of View Boundary.
 * <p>
 * The offset is roughly an angle with respect to the closest boundary point,
 * corrected by the margin and using some approximation far from the Field Of View.
 * It is positive if the target is outside of the Field Of view, negative inside,
 * and zero if the point is exactly on the boundary (always taking the margin
 * into account).
 * </p>
 * <p>
 * As Field Of View can have complex shapes that may require long computation,
 * when the target point can be proven to be outside of the Field Of View, a
 * faster but approximate computation is done, that underestimate the offset.
 * This approximation is only performed about 0.01 radians outside of the zone
 * and is designed to still return a positive value if the full accurate computation
 * would return a positive value. When target point is close to the zone (and
 * furthermore when it is inside the zone), the full accurate computation is
 * performed. This setup allows this offset to be used as a reliable way to
 * detect Field Of View boundary crossings, which correspond to sign changes of
 * the offset.
 * </p>
 * @param lineOfSight line of sight from the center of the Field Of View support
 * unit sphere to the target in Field Of View canonical frame
 * @return an angular offset negative if the target is visible within the Field Of
 * View and positive if it is outside of the Field Of View, including the margin
 * (note that this cannot take into account interposing bodies)
 */
public double offsetFromBoundary(final Vector3D lineOfSight) {
    final S2Point los = new S2Point(lineOfSight);
    // for faster computation, we start using only the surrounding cap, to filter out
    // far away points (which correspond to most of the points if the Field Of View is small)
    final double crudeDistance = cap.getCenter().distance(los) - cap.getRadius();
    if (crudeDistance - margin > FastMath.max(FastMath.abs(margin), 0.01)) {
        // use the crude distance to compute the (positive) return value
        return crudeDistance - margin;
    }
    // we project the point to the closest zone boundary
    return zone.projectToBoundary(los).getOffset() - margin;
}
Also used : S2Point(org.hipparchus.geometry.spherical.twod.S2Point)

Aggregations

S2Point (org.hipparchus.geometry.spherical.twod.S2Point)13 GeodeticPoint (org.orekit.bodies.GeodeticPoint)8 SphericalPolygonsSet (org.hipparchus.geometry.spherical.twod.SphericalPolygonsSet)7 ArrayList (java.util.ArrayList)5 List (java.util.List)4 Vector3D (org.hipparchus.geometry.euclidean.threed.Vector3D)4 Edge (org.hipparchus.geometry.spherical.twod.Edge)3 Sphere2D (org.hipparchus.geometry.spherical.twod.Sphere2D)3 Vertex (org.hipparchus.geometry.spherical.twod.Vertex)3 IdentityHashMap (java.util.IdentityHashMap)2 LinkedList (java.util.LinkedList)2 Map (java.util.Map)2 RegionFactory (org.hipparchus.geometry.partitioning.RegionFactory)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 ObjectInputStream (java.io.ObjectInputStream)1 ObjectOutputStream (java.io.ObjectOutputStream)1 Line (org.hipparchus.geometry.euclidean.threed.Line)1 Test (org.junit.Test)1 OrekitException (org.orekit.errors.OrekitException)1