-
Notifications
You must be signed in to change notification settings - Fork 11
/
threeGeoJSON.js
258 lines (211 loc) · 9.93 KB
/
threeGeoJSON.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/* Draw GeoJSON
Iterates through the latitude and longitude values, converts the values to XYZ coordinates,
and draws the geoJSON geometries.
*/
var THREEGeoJSONGlobeMap=function(){
var x_values = [];
var y_values = [];
var z_values = [];
var scene_;
var lines=new THREE.Object3D();
this.drawThreeGeo = function (/*scene,*/json, radius, shape, options) {
//scene_=scene;
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);
var particle=drawParticle(y_values[0], z_values[0], x_values[0], options);
lines.add(particle);
} 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);
var particle=drawParticle(y_values[0], z_values[0], x_values[0], options);
lines.add(particle);
}
} 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);
}
var line=drawLine(y_values, z_values, x_values, options);
lines.add(line);
} 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);
}
var line=drawLine(y_values, z_values, x_values, options);
lines.add(line);
}
} 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);
}
var line=drawLine(y_values, z_values, x_values, options);
lines.add(line)
}
} 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);
}
var line=drawLine(y_values, z_values, x_values, options);
lines.add(line);
}
}
} else {
throw new Error('The geoJSON is not valid.');
}
}
return lines;
}
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();
return particle;
}
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();
return line;
}
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;
}
}