use of org.hipparchus.geometry.partitioning.RegionFactory in project Orekit by CS-SI.
the class EllipsoidTessellator method tessellate.
/**
* Tessellate a zone of interest into tiles.
* <p>
* The created tiles will completely cover the zone of interest.
* </p>
* <p>
* The distance between a vertex at a tile corner and the vertex at the same corner
* in the next vertex are computed by subtracting the overlap width (resp. overlap length)
* from the full width (resp. full length). If for example the full width is specified to
* be 55 km and the overlap in width is specified to be +5 km, successive tiles would span
* as follows:
* </p>
* <ul>
* <li>tile 1 covering from 0 km to 55 km</li>
* <li>tile 2 covering from 50 km to 105 km</li>
* <li>tile 3 covering from 100 km to 155 km</li>
* <li>...</li>
* </ul>
* <p>
* In order to achieve the same 50 km step but using a 5 km gap instead of an overlap, one would
* need to specify the full width to be 45 km and the overlap to be -5 km. With these settings,
* successive tiles would span as follows:
* </p>
* <ul>
* <li>tile 1 covering from 0 km to 45 km</li>
* <li>tile 2 covering from 50 km to 95 km</li>
* <li>tile 3 covering from 100 km to 155 km</li>
* <li>...</li>
* </ul>
* @param zone zone of interest to tessellate
* @param fullWidth full tiles width as a distance on surface, including overlap (in meters)
* @param fullLength full tiles length as a distance on surface, including overlap (in meters)
* @param widthOverlap overlap between adjacent tiles (in meters), if negative the tiles
* will have a gap between each other instead of an overlap
* @param lengthOverlap overlap between adjacent tiles (in meters), if negative the tiles
* will have a gap between each other instead of an overlap
* @param truncateLastWidth if true, the first tiles strip will be started as close as
* possible to the zone of interest, and the last tiles strip will have its width reduced
* to also remain close to the zone of interest; if false all tiles strip will have the
* same {@code fullWidth} and they will be balanced around zone of interest
* @param truncateLastLength if true, the first tile in each strip will be started as close as
* possible to the zone of interest, and the last tile in each strip will have its length reduced
* to also remain close to the zone of interest; if false all tiles in each strip will have the
* same {@code fullLength} and they will be balanced around zone of interest
* @return a list of lists of tiles covering the zone of interest,
* each sub-list corresponding to a part not connected to the other
* parts (for example for islands)
* @exception OrekitException if the zone cannot be tessellated
*/
public List<List<Tile>> tessellate(final SphericalPolygonsSet zone, final double fullWidth, final double fullLength, final double widthOverlap, final double lengthOverlap, final boolean truncateLastWidth, final boolean truncateLastLength) throws OrekitException {
final double splitWidth = (fullWidth - widthOverlap) / quantization;
final double splitLength = (fullLength - lengthOverlap) / quantization;
final Map<Mesh, List<Tile>> map = new IdentityHashMap<Mesh, List<Tile>>();
final RegionFactory<Sphere2D> factory = new RegionFactory<Sphere2D>();
SphericalPolygonsSet remaining = (SphericalPolygonsSet) zone.copySelf();
S2Point inside = getInsidePoint(remaining);
while (inside != null) {
// find a mesh covering at least one connected part of the zone
final List<Mesh.Node> mergingSeeds = new ArrayList<Mesh.Node>();
Mesh mesh = new Mesh(ellipsoid, zone, aiming, splitLength, splitWidth, inside);
mergingSeeds.add(mesh.getNode(0, 0));
List<Tile> tiles = null;
while (!mergingSeeds.isEmpty()) {
// expand the mesh around the seed
neighborExpandMesh(mesh, mergingSeeds, zone);
// extract the tiles from the mesh
// this further expands the mesh so tiles dimensions are multiples of quantization,
// hence it must be performed here before checking meshes independence
tiles = extractTiles(mesh, zone, lengthOverlap, widthOverlap, truncateLastWidth, truncateLastLength);
// check the mesh is independent from existing meshes
mergingSeeds.clear();
for (final Map.Entry<Mesh, List<Tile>> entry : map.entrySet()) {
if (!factory.intersection(mesh.getCoverage(), entry.getKey().getCoverage()).isEmpty()) {
// the meshes are not independent, they intersect each other!
// merge the two meshes together
mesh = mergeMeshes(mesh, entry.getKey(), mergingSeeds);
map.remove(entry.getKey());
break;
}
}
}
// remove the part of the zone covered by the mesh
remaining = (SphericalPolygonsSet) factory.difference(remaining, mesh.getCoverage());
inside = getInsidePoint(remaining);
map.put(mesh, tiles);
}
// concatenate the lists from the independent meshes
final List<List<Tile>> tilesLists = new ArrayList<List<Tile>>(map.size());
for (final Map.Entry<Mesh, List<Tile>> entry : map.entrySet()) {
tilesLists.add(entry.getValue());
}
return tilesLists;
}
use of org.hipparchus.geometry.partitioning.RegionFactory in project Orekit by CS-SI.
the class EllipsoidTessellator method sample.
/**
* Sample a zone of interest into a grid sample of {@link GeodeticPoint geodetic points}.
* <p>
* The created points will be entirely within the zone of interest.
* </p>
* @param zone zone of interest to sample
* @param width grid sample cells width as a distance on surface (in meters)
* @param length grid sample cells length as a distance on surface (in meters)
* @return a list of lists of points sampling the zone of interest,
* each sub-list corresponding to a part not connected to the other
* parts (for example for islands)
* @exception OrekitException if the zone cannot be sampled
*/
public List<List<GeodeticPoint>> sample(final SphericalPolygonsSet zone, final double width, final double length) throws OrekitException {
final double splitWidth = width / quantization;
final double splitLength = length / quantization;
final Map<Mesh, List<GeodeticPoint>> map = new IdentityHashMap<Mesh, List<GeodeticPoint>>();
final RegionFactory<Sphere2D> factory = new RegionFactory<Sphere2D>();
SphericalPolygonsSet remaining = (SphericalPolygonsSet) zone.copySelf();
S2Point inside = getInsidePoint(remaining);
while (inside != null) {
// find a mesh covering at least one connected part of the zone
final List<Mesh.Node> mergingSeeds = new ArrayList<Mesh.Node>();
Mesh mesh = new Mesh(ellipsoid, zone, aiming, splitLength, splitWidth, inside);
mergingSeeds.add(mesh.getNode(0, 0));
List<GeodeticPoint> sample = null;
while (!mergingSeeds.isEmpty()) {
// expand the mesh around the seed
neighborExpandMesh(mesh, mergingSeeds, zone);
// extract the sample from the mesh
// this further expands the mesh so sample cells dimensions are multiples of quantization,
// hence it must be performed here before checking meshes independence
sample = extractSample(mesh, zone);
// check the mesh is independent from existing meshes
mergingSeeds.clear();
for (final Map.Entry<Mesh, List<GeodeticPoint>> entry : map.entrySet()) {
if (!factory.intersection(mesh.getCoverage(), entry.getKey().getCoverage()).isEmpty()) {
// the meshes are not independent, they intersect each other!
// merge the two meshes together
mesh = mergeMeshes(mesh, entry.getKey(), mergingSeeds);
map.remove(entry.getKey());
break;
}
}
}
// remove the part of the zone covered by the mesh
remaining = (SphericalPolygonsSet) factory.difference(remaining, mesh.getCoverage());
inside = getInsidePoint(remaining);
map.put(mesh, sample);
}
// concatenate the lists from the independent meshes
final List<List<GeodeticPoint>> sampleLists = new ArrayList<List<GeodeticPoint>>(map.size());
for (final Map.Entry<Mesh, List<GeodeticPoint>> entry : map.entrySet()) {
sampleLists.add(entry.getValue());
}
return sampleLists;
}
use of org.hipparchus.geometry.partitioning.RegionFactory in project Orekit by CS-SI.
the class GeographicZoneDetectorTest method buildFrance.
private SphericalPolygonsSet buildFrance() {
final SphericalPolygonsSet continental = buildSimpleZone(new double[][] { { 51.14850, 2.51357 }, { 50.94660, 1.63900 }, { 50.12717, 1.33876 }, { 49.34737, -0.98946 }, { 49.77634, -1.93349 }, { 48.64442, -1.61651 }, { 48.90169, -3.29581 }, { 48.68416, -4.59234 }, { 47.95495, -4.49155 }, { 47.57032, -2.96327 }, { 46.01491, -1.19379 }, { 44.02261, -1.38422 }, { 43.42280, -1.90135 }, { 43.03401, -1.50277 }, { 42.34338, 1.82679 }, { 42.47301, 2.98599 }, { 43.07520, 3.10041 }, { 43.39965, 4.55696 }, { 43.12889, 6.52924 }, { 43.69384, 7.43518 }, { 44.12790, 7.54959 }, { 45.02851, 6.74995 }, { 45.33309, 7.09665 }, { 46.42967, 6.50009 }, { 46.27298, 6.02260 }, { 46.72577, 6.03738 }, { 47.62058, 7.46675 }, { 49.01778, 8.09927 }, { 49.20195, 6.65822 }, { 49.44266, 5.89775 }, { 49.98537, 4.79922 } });
final SphericalPolygonsSet corsica = buildSimpleZone(new double[][] { { 42.15249, 9.56001 }, { 43.00998, 9.39000 }, { 42.62812, 8.74600 }, { 42.25651, 8.54421 }, { 41.58361, 8.77572 }, { 41.38000, 9.22975 } });
return (SphericalPolygonsSet) new RegionFactory<Sphere2D>().union(continental, corsica);
}
use of org.hipparchus.geometry.partitioning.RegionFactory in project Orekit by CS-SI.
the class FootprintOverlapDetectorTest method buildFrance.
private SphericalPolygonsSet buildFrance() {
final SphericalPolygonsSet continental = buildSimpleZone(new double[][] { { 51.14850, 2.51357 }, { 50.94660, 1.63900 }, { 50.12717, 1.33876 }, { 49.34737, -0.98946 }, { 49.77634, -1.93349 }, { 48.64442, -1.61651 }, { 48.90169, -3.29581 }, { 48.68416, -4.59234 }, { 47.95495, -4.49155 }, { 47.57032, -2.96327 }, { 46.01491, -1.19379 }, { 44.02261, -1.38422 }, { 43.42280, -1.90135 }, { 43.03401, -1.50277 }, { 42.34338, 1.82679 }, { 42.47301, 2.98599 }, { 43.07520, 3.10041 }, { 43.39965, 4.55696 }, { 43.12889, 6.52924 }, { 43.69384, 7.43518 }, { 44.12790, 7.54959 }, { 45.02851, 6.74995 }, { 45.33309, 7.09665 }, { 46.42967, 6.50009 }, { 46.27298, 6.02260 }, { 46.72577, 6.03738 }, { 47.62058, 7.46675 }, { 49.01778, 8.09927 }, { 49.20195, 6.65822 }, { 49.44266, 5.89775 }, { 49.98537, 4.79922 } });
final SphericalPolygonsSet corsica = buildSimpleZone(new double[][] { { 42.15249, 9.56001 }, { 43.00998, 9.39000 }, { 42.62812, 8.74600 }, { 42.25651, 8.54421 }, { 41.58361, 8.77572 }, { 41.38000, 9.22975 } });
return (SphericalPolygonsSet) new RegionFactory<Sphere2D>().union(continental, corsica);
}
use of org.hipparchus.geometry.partitioning.RegionFactory in project Orekit by CS-SI.
the class EllipsoidTessellatorTest method buildFrance.
private SphericalPolygonsSet buildFrance() {
final SphericalPolygonsSet continental = buildSimpleZone(1.0e-10, new double[][] { { 51.14850, 2.51357 }, { 50.94660, 1.63900 }, { 50.12717, 1.33876 }, { 49.34737, -0.98946 }, { 49.77634, -1.93349 }, { 48.64442, -1.61651 }, { 48.90169, -3.29581 }, { 48.68416, -4.59234 }, { 47.95495, -4.49155 }, { 47.57032, -2.96327 }, { 46.01491, -1.19379 }, { 44.02261, -1.38422 }, { 43.42280, -1.90135 }, { 43.03401, -1.50277 }, { 42.34338, 1.82679 }, { 42.47301, 2.98599 }, { 43.07520, 3.10041 }, { 43.39965, 4.55696 }, { 43.12889, 6.52924 }, { 43.69384, 7.43518 }, { 44.12790, 7.54959 }, { 45.02851, 6.74995 }, { 45.33309, 7.09665 }, { 46.42967, 6.50009 }, { 46.27298, 6.02260 }, { 46.72577, 6.03738 }, { 47.62058, 7.46675 }, { 49.01778, 8.09927 }, { 49.20195, 6.65822 }, { 49.44266, 5.89775 }, { 49.98537, 4.79922 } });
final SphericalPolygonsSet corsica = EllipsoidTessellator.buildSimpleZone(1.0e-10, new GeodeticPoint(FastMath.toRadians(42.15249), FastMath.toRadians(9.56001), 0.0), new GeodeticPoint(FastMath.toRadians(43.00998), FastMath.toRadians(9.39000), 0.0), new GeodeticPoint(FastMath.toRadians(42.62812), FastMath.toRadians(8.74600), 0.0), new GeodeticPoint(FastMath.toRadians(42.25651), FastMath.toRadians(8.54421), 0.0), new GeodeticPoint(FastMath.toRadians(41.58361), FastMath.toRadians(8.77572), 0.0), new GeodeticPoint(FastMath.toRadians(41.38000), FastMath.toRadians(9.22975), 0.0));
return (SphericalPolygonsSet) new RegionFactory<Sphere2D>().union(continental, corsica);
}
Aggregations