You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
8.7 KiB
244 lines
8.7 KiB
|
4 months ago
|
/* Draw GeoJSON
|
||
|
|
|
||
|
|
Iterates through the latitude and longitude values, converts the values to XYZ coordinates,
|
||
|
|
and draws the geoJSON geometries.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
var x_values = [];
|
||
|
|
var y_values = [];
|
||
|
|
var z_values = [];
|
||
|
|
|
||
|
|
function drawThreeGeo(json, radius, shape, options) {
|
||
|
|
|
||
|
|
var json_geom = createGeometryArray(json);
|
||
|
|
//An array to hold the feature geometries.
|
||
|
|
var convertCoordinates = getConversionFunctionName(shape);
|
||
|
|
//Whether you want to convert to spherical or planar coordinates.
|
||
|
|
var coordinate_array = [];
|
||
|
|
//Re-usable array to hold coordinate values. This is necessary so that you can add
|
||
|
|
//interpolated coordinates. Otherwise, lines go through the sphere instead of wrapping around.
|
||
|
|
|
||
|
|
for (var geom_num = 0; geom_num < json_geom.length; geom_num++) {
|
||
|
|
|
||
|
|
if (json_geom[geom_num].type == 'Point') {
|
||
|
|
convertCoordinates(json_geom[geom_num].coordinates, radius);
|
||
|
|
drawParticle(y_values[0], z_values[0], x_values[0], options);
|
||
|
|
|
||
|
|
} else if (json_geom[geom_num].type == 'MultiPoint') {
|
||
|
|
for (var point_num = 0; point_num < json_geom[geom_num].coordinates.length; point_num++) {
|
||
|
|
convertCoordinates(json_geom[geom_num].coordinates[point_num], radius);
|
||
|
|
drawParticle(y_values[0], z_values[0], x_values[0], options);
|
||
|
|
}
|
||
|
|
|
||
|
|
} else if (json_geom[geom_num].type == 'LineString') {
|
||
|
|
coordinate_array = createCoordinateArray(json_geom[geom_num].coordinates);
|
||
|
|
|
||
|
|
for (var point_num = 0; point_num < coordinate_array.length; point_num++) {
|
||
|
|
convertCoordinates(coordinate_array[point_num], radius);
|
||
|
|
}
|
||
|
|
drawLine(y_values, z_values, x_values, options);
|
||
|
|
|
||
|
|
} else if (json_geom[geom_num].type == 'Polygon') {
|
||
|
|
for (var segment_num = 0; segment_num < json_geom[geom_num].coordinates.length; segment_num++) {
|
||
|
|
coordinate_array = createCoordinateArray(json_geom[geom_num].coordinates[segment_num]);
|
||
|
|
|
||
|
|
for (var point_num = 0; point_num < coordinate_array.length; point_num++) {
|
||
|
|
convertCoordinates(coordinate_array[point_num], radius);
|
||
|
|
}
|
||
|
|
drawLine(y_values, z_values, x_values, options);
|
||
|
|
}
|
||
|
|
|
||
|
|
} else if (json_geom[geom_num].type == 'MultiLineString') {
|
||
|
|
for (var segment_num = 0; segment_num < json_geom[geom_num].coordinates.length; segment_num++) {
|
||
|
|
coordinate_array = createCoordinateArray(json_geom[geom_num].coordinates[segment_num]);
|
||
|
|
|
||
|
|
for (var point_num = 0; point_num < coordinate_array.length; point_num++) {
|
||
|
|
convertCoordinates(coordinate_array[point_num], radius);
|
||
|
|
}
|
||
|
|
drawLine(y_values, z_values, x_values, options);
|
||
|
|
}
|
||
|
|
|
||
|
|
} else if (json_geom[geom_num].type == 'MultiPolygon') {
|
||
|
|
for (var polygon_num = 0; polygon_num < json_geom[geom_num].coordinates.length; polygon_num++) {
|
||
|
|
for (var segment_num = 0; segment_num < json_geom[geom_num].coordinates[polygon_num].length; segment_num++) {
|
||
|
|
coordinate_array = createCoordinateArray(json_geom[geom_num].coordinates[polygon_num][segment_num]);
|
||
|
|
|
||
|
|
for (var point_num = 0; point_num < coordinate_array.length; point_num++) {
|
||
|
|
convertCoordinates(coordinate_array[point_num], radius);
|
||
|
|
}
|
||
|
|
drawLine(y_values, z_values, x_values, options);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
throw new Error('The geoJSON is not valid.');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function createGeometryArray(json) {
|
||
|
|
var geometry_array = [];
|
||
|
|
|
||
|
|
if (json.type == 'Feature') {
|
||
|
|
geometry_array.push(json.geometry);
|
||
|
|
} else if (json.type == 'FeatureCollection') {
|
||
|
|
for (var feature_num = 0; feature_num < json.features.length; feature_num++) {
|
||
|
|
geometry_array.push(json.features[feature_num].geometry);
|
||
|
|
}
|
||
|
|
} else if (json.type == 'GeometryCollection') {
|
||
|
|
for (var geom_num = 0; geom_num < json.geometries.length; geom_num++) {
|
||
|
|
geometry_array.push(json.geometries[geom_num]);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
throw new Error('The geoJSON is not valid.');
|
||
|
|
}
|
||
|
|
//alert(geometry_array.length);
|
||
|
|
return geometry_array;
|
||
|
|
}
|
||
|
|
|
||
|
|
function getConversionFunctionName(shape) {
|
||
|
|
var conversionFunctionName;
|
||
|
|
|
||
|
|
if (shape == 'sphere') {
|
||
|
|
conversionFunctionName = convertToSphereCoords;
|
||
|
|
} else if (shape == 'plane') {
|
||
|
|
conversionFunctionName = convertToPlaneCoords;
|
||
|
|
} else {
|
||
|
|
throw new Error('The shape that you specified is not valid.');
|
||
|
|
}
|
||
|
|
return conversionFunctionName;
|
||
|
|
}
|
||
|
|
|
||
|
|
function createCoordinateArray(feature) {
|
||
|
|
//Loop through the coordinates and figure out if the points need interpolation.
|
||
|
|
var temp_array = [];
|
||
|
|
var interpolation_array = [];
|
||
|
|
|
||
|
|
for (var point_num = 0; point_num < feature.length; point_num++) {
|
||
|
|
var point1 = feature[point_num];
|
||
|
|
var point2 = feature[point_num - 1];
|
||
|
|
|
||
|
|
if (point_num > 0) {
|
||
|
|
if (needsInterpolation(point2, point1)) {
|
||
|
|
interpolation_array = [point2, point1];
|
||
|
|
interpolation_array = interpolatePoints(interpolation_array);
|
||
|
|
|
||
|
|
for (var inter_point_num = 0; inter_point_num < interpolation_array.length; inter_point_num++) {
|
||
|
|
temp_array.push(interpolation_array[inter_point_num]);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
temp_array.push(point1);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
temp_array.push(point1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return temp_array;
|
||
|
|
}
|
||
|
|
|
||
|
|
function needsInterpolation(point2, point1) {
|
||
|
|
//If the distance between two latitude and longitude values is
|
||
|
|
//greater than five degrees, return true.
|
||
|
|
var lon1 = point1[0];
|
||
|
|
var lat1 = point1[1];
|
||
|
|
var lon2 = point2[0];
|
||
|
|
var lat2 = point2[1];
|
||
|
|
var lon_distance = Math.abs(lon1 - lon2);
|
||
|
|
var lat_distance = Math.abs(lat1 - lat2);
|
||
|
|
|
||
|
|
if (lon_distance > 5 || lat_distance > 5) {
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function interpolatePoints(interpolation_array) {
|
||
|
|
//This function is recursive. It will continue to add midpoints to the
|
||
|
|
//interpolation array until needsInterpolation() returns false.
|
||
|
|
var temp_array = [];
|
||
|
|
var point1, point2;
|
||
|
|
|
||
|
|
for (var point_num = 0; point_num < interpolation_array.length - 1; point_num++) {
|
||
|
|
point1 = interpolation_array[point_num];
|
||
|
|
point2 = interpolation_array[point_num + 1];
|
||
|
|
|
||
|
|
if (needsInterpolation(point2, point1)) {
|
||
|
|
temp_array.push(point1);
|
||
|
|
temp_array.push(getMidpoint(point1, point2));
|
||
|
|
} else {
|
||
|
|
temp_array.push(point1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
temp_array.push(interpolation_array[interpolation_array.length - 1]);
|
||
|
|
|
||
|
|
if (temp_array.length > interpolation_array.length) {
|
||
|
|
temp_array = interpolatePoints(temp_array);
|
||
|
|
} else {
|
||
|
|
return temp_array;
|
||
|
|
}
|
||
|
|
return temp_array;
|
||
|
|
}
|
||
|
|
|
||
|
|
function getMidpoint(point1, point2) {
|
||
|
|
var midpoint_lon = (point1[0] + point2[0]) / 2;
|
||
|
|
var midpoint_lat = (point1[1] + point2[1]) / 2;
|
||
|
|
var midpoint = [midpoint_lon, midpoint_lat];
|
||
|
|
|
||
|
|
return midpoint;
|
||
|
|
}
|
||
|
|
|
||
|
|
function convertToSphereCoords(coordinates_array, sphere_radius) {
|
||
|
|
var lon = coordinates_array[0];
|
||
|
|
var lat = coordinates_array[1];
|
||
|
|
|
||
|
|
x_values.push(Math.cos(lat * Math.PI / 180) * Math.cos(lon * Math.PI / 180) * sphere_radius);
|
||
|
|
y_values.push(Math.cos(lat * Math.PI / 180) * Math.sin(lon * Math.PI / 180) * sphere_radius);
|
||
|
|
z_values.push(Math.sin(lat * Math.PI / 180) * sphere_radius);
|
||
|
|
}
|
||
|
|
|
||
|
|
function convertToPlaneCoords(coordinates_array, radius) {
|
||
|
|
var lon = coordinates_array[0];
|
||
|
|
var lat = coordinates_array[1];
|
||
|
|
|
||
|
|
z_values.push((lat / 180) * radius);
|
||
|
|
y_values.push((lon / 180) * radius);
|
||
|
|
}
|
||
|
|
|
||
|
|
function drawParticle(x, y, z, options) {
|
||
|
|
var particle_geom = new THREE.Geometry();
|
||
|
|
particle_geom.vertices.push(new THREE.Vector3(x, y, z));
|
||
|
|
|
||
|
|
var particle_material = new THREE.ParticleSystemMaterial(options);
|
||
|
|
|
||
|
|
var particle = new THREE.ParticleSystem(particle_geom, particle_material);
|
||
|
|
scene.add(particle);
|
||
|
|
|
||
|
|
clearArrays();
|
||
|
|
}
|
||
|
|
|
||
|
|
function drawLine(x_values, y_values, z_values, options) {
|
||
|
|
var line_geom = new THREE.Geometry();
|
||
|
|
createVertexForEachPoint(line_geom, x_values, y_values, z_values);
|
||
|
|
|
||
|
|
var line_material = new THREE.LineBasicMaterial(options);
|
||
|
|
var line = new THREE.Line(line_geom, line_material);
|
||
|
|
scene.add(line);
|
||
|
|
|
||
|
|
clearArrays();
|
||
|
|
}
|
||
|
|
|
||
|
|
function createVertexForEachPoint(object_geometry, values_axis1, values_axis2, values_axis3) {
|
||
|
|
for (var i = 0; i < values_axis1.length; i++) {
|
||
|
|
object_geometry.vertices.push(new THREE.Vector3(values_axis1[i],
|
||
|
|
values_axis2[i], values_axis3[i]));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function clearArrays() {
|
||
|
|
x_values.length = 0;
|
||
|
|
y_values.length = 0;
|
||
|
|
z_values.length = 0;
|
||
|
|
}
|