# Rectangular Field on earth

Hello, could you please explain in detail what this code means? Although I can run this code, I am not clear about the specific meaning, so I am unable to conduct further experiments.

``````public class InAreaStatus implements EventHandler {
private boolean inArea = false;
public Action eventOccurred(SpacecraftState s, EventDetector detector, boolean increasing) {
if (!increasing) {
System.out.println("Visibility begins at " + s.getDate());
inArea = true;
} else {
System.out.println("Visibility ends at " + s.getDate());
System.out.println();
inArea = false;
}
return Action.CONTINUE;
}
public boolean inArea() {
return inArea;
}
}

public class SubPointWriter implements OrekitFixedStepHandler {
private final InAreaStatus status;
private final OneAxisEllipsoid earth;
public SubPointWriter(final InAreaStatus status, final BodyShape earth2) {
this.status = status;
this.earth  = (OneAxisEllipsoid) earth2;
}
public void handleStep(SpacecraftState state) {
if (status.inArea()) {
// we only print satellite sub-point when we know we already are in the area of interest
GeodeticPoint gp = earth.transform(state.getPVCoordinates().getPosition(),
state.getFrame(),
state.getDate());
System.out.format(Locale.US, "%s %10.5f %10.5f%n",
state.getDate(),
FastMath.toDegrees(gp.getLatitude()),
FastMath.toDegrees(gp.getLongitude()));
}
}
}

public class Test {
public static void main(String args[]) {
final File home       = new File(System.getProperty("user.home"));
final File orekitData = new File(home, "orekit-data");
if (!orekitData.exists()) {
System.err.format(Locale.US, "Failed to find %s folder%n",
orekitData.getAbsolutePath());
System.err.format(Locale.US, "You need to download %s from %s, unzip it in %s and rename it 'orekit-data' for this tutorial to work%n",
"orekit-data-master.zip", "https://gitlab.orekit.org/orekit/orekit-data/-/archive/master/orekit-data-master.zip",
home.getAbsolutePath());
System.exit(1);
}
final DataProvidersManager manager = DataContext.getDefault().getDataProvidersManager();

//  Initial state definition : date, orbit
final AbsoluteDate initialDate = new AbsoluteDate(2023, 10, 26, 8, 00, 00.000, TimeScalesFactory.getUTC());
final double mu =  3.986004415e+14; // gravitation coefficient
final Frame inertialFrame = FramesFactory.getEME2000(); // inertial frame for orbit definition
final Vector3D position  = new Vector3D(-7518565.475, 4279265.668, 4816446.308);
final Vector3D velocity  = new Vector3D(-5463.904, -5533.9672, 50.719);
final PVCoordinates pvCoordinates = new PVCoordinates(position, velocity);
final Orbit initialOrbit = new KeplerianOrbit(pvCoordinates, inertialFrame, initialDate, mu);

// Propagator : consider a simple Keplerian motion
final Propagator kepler = new KeplerianPropagator(initialOrbit);

// Earth and frame
final Frame earthFrame = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
final BodyShape earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING,
earthFrame);

//创建一个地面区域

// 创建表示地面区域的SphericalPolygonsSet
SphericalPolygonsSet region = EllipsoidTessellator.buildSimpleZone(1.0e-10, point1, point2, point3, point4);

// Event definition
final double maxcheck  = 60;
final double threshold =  0.001;
final double stepSize = 100;
final InAreaStatus status = new InAreaStatus();
final GeographicZoneDetector zoneDetector =
new GeographicZoneDetector(maxcheck, threshold, earth, region, elevation)
.withHandler(status);
final SubPointWriter subPointWriter = new SubPointWriter(status, earth);
kepler.propagate(initialDate.shiftedBy(36000.));
}

}
``````

This program starts by setting up a lot of configuration for a propagator in order for it to automatically discover on the fly some events (start/end of overflying a geographic zone) and to log the satellite location with respect to ground (i.e. latitude/longitude) while in said geographic zone.

The configuration part is everything before last line. The last line (call to `kepler.propagate`) is where the propagator is really run and all the configured event detection/logging is really performed. The configuration is a complicated one, it involves both events handling and step handling, and they are linked together.

Events handling is what is done in the class `InAreaStatus` as it implements `EventHandler` and is registered as the event handler to be triggered automatically when the `GeographicZoneDetector` discover the satellite enters or leaves the region of interest. So during the configuration phase, we associate one `InAreaStatus` instance with one `GeographicZoneDetector` and we add this detector to the propagator, so when the satellite enters/leaves the region, the `InAreaStatus` method `eventOccurred` method will be called. We store the current status (inside/outside region) in the `InAreaStatus` instance. Please note that in another thread, I suggested to use a `TimeSpanMap<Boolean>` rather than a primitive `boolean` to store this status with its associated time in order to avoid slight problems near region boundary (points considered visible when they are not yet visible).

Logging satellite location is done in the class `SubPointWriter` as it implements `OrekitFixedStepHandler` and is registered as a step handler called regularly throughout propagation, i.e. from start to begin. What we want here, is to output the satellite location but only when the satellite is above the region of interest. So we have to associate the `InAreaStatus` instance (which knows when the satellite is in area and when the satellite is out of area), and we set up a condition to only output the sub-satellite point when the satellite is above region. This means that the propagator will call the `handleStep` method of the `SubPointWriter` class throughout propagation, but due to the `if` statement, it will only display point when the satellite is visible (or close to it, due to the synchronization problem I mentioned in another thread, and for which I suggested to use `TimeSpanMap<Boolean>` for more accurate results.

Thank you for your detailed answer, I will greatly benefit. Wishing you a pleasant work and life！