NASA World Wind SDK

Innen: GIS Wiki
A lap korábbi változatát látod, amilyen HB0MT7 (vitalap | szerkesztései) 2017. május 8., 21:44-kor történt szerkesztése után volt. (Szövegek)

Bevezetés

NASA World Wind SDK egy ingyenes, nyílt-forráskódú virtuális földgömb weboldalakhoz és web applikációkhoz. Alapvetően három iránya van : Java,Android,Web. Ezen Wiki oldal témája a Web-es irány.


Web World Wind-et Javascriptben írták és egy Javascript API-t biztosít ahhoz, hogy egy virtuális földgömb összes aspektusát kezelhessük. A Web World Wind lehetővé teszi, hogy a fejlesztők gyorsan és könnyen interaktív vizualizációt készíthessenek különböző földrajzi adatoknak egy 2 dimenziós térképen vagy 3 dimenziós földgömbön.

A világon sok szervezet használja a Web World Wind-et arra, hogy monitorozzanak időjárás mintákat, városoakt vizualizáljanak, járművek mozgását kövessék, földrajzi adatokat elemezzenek vagy oktassák az embereket a Földről.

Néhány lehetőség:

  • Sok előre beépített, magas felbontású képpel rendelkezik
  • Sok beépített alakzat megvalósítható
  • Beépített navigációs lehetőségek
  • Több földgömb is megjeleníthető egy oldalon
  • ShapeFile támogatás
  • stb...


http://people.inf.elte.hu/hagtabi/foldgomb

Koncepció

A Web World Wind egy komponens amely beágyazódik a weboldalba. Ezt a komponenst hívjuk World Windownak.

World Window

A World Window objektum a funkcionalitást egy HTML canvas köré építi. A canvas általában egy "div" és az attribútumként megadott id-val paraméterezzük a World Window objektumot. Egy oldal több World Widow objektumot tartalmazhat, mindegyik canvashoz tartozik egy.

A World Window tartalmaz egy Globe-ot, egy Navigator-t és egy Layer List-et. Ezek automtiusan jönnek létre amikor a World Window konstruálódik. A Globe és Navigator lecserélhető. Ezeken felül a World Window felel még az eseménykezelésért.

Az World Window felépítése:

[1]


1 <div style="position:relative">
2     <canvas id="canvasOne" width="1000" height="1000" style="width: 100%; height: auto">
3     </canvas>
4 </div>

Rétegek

A World Wind mellett a rétegek a legfontosabb objektumok. Ezen rétegek tárolják a World Winden megjelenő összes információt. A képek, alakzatok, dekorációs elemek stb. mind-mind különálló rétegekben tárolódnak.

Minden World Wind objektum tartalmaz egy listát amely a rétegeket tartalmazza. Ezt nevezik Layer List-nek. Ez a lista tartalmazza az összes definiált réteget, és alapesetben üres. Amikor a World Wind rajzol, akkor bejárja ezt a listát és sorrendben megrajzolja a benne lévő rétegeket.

Fontosabb réteg attribútumok:

  • displayName : Szöveg, a réteg nevét adhatjuk meg, és később ez megjeleníthető.
  • enabled : Logikai, lehetővé teszi, hogy a réteget kikapcsoljuk, de közben a listában benne marad.
  • pickEnabled : Logikai, megmondja, hogy a réteg és a tartalma "pickelhető-e".
  • opacity : 0-1 közötti szám a réteg átlátszóságát szabályozza.

Két fontosabb rétegtípus van.

  • Kép réteg: olyan képet tartalmaz amelyet a felszínre vetítünk ki. Ez tipikusan az egész földgömbre kiterjed de ez nem kötelező.
  • Renderelhető réteg: akkor használjuk ha alakzatokat szeretnénk megjeleníteni.
1 // Létrehozzuk a  World Window-t
2 var wwd = new WorldWind.WorldWindow("canvasOne");
3 
4 // Létrehozzuk és hozzáadjuk a layereket
5 wwd.addLayer(new WorldWind.BMNGLayer());
6 wwd.addLayer(new WorldWind.BingAerialWithLabelsLayer(null));
7 wwd.addLayer(new WorldWind.CompassLayer());
8 wwd.addLayer(new WorldWind.CoordinatesDisplayLayer(wwd));
9 wwd.addLayer(new WorldWind.ViewControlsLayer(wwd));

Alakzatok

Alakzatok reprezentálják azokat az információkat amit meg szeretnénk jeleníteni és a földgömbhöz kapcsolódik. Egy ilyen objektum sokféle lehet, az egyszerű helyzet-jelölőtől kezdve a komplex rajzolt alakzatokig. Minden alakzat egy rétegben tárolódik és ez a réteg pedig megtalálható a World Wind Layer List-jében. Minden World Wind alakzathoz sokféle attribútum kapcsolható, ezzel vezérelve pl: a színt vagy láthatóságot. A legtöbb alakzathoz ez egy ShapeAttributes osztály, de például a helyjelzőnél a szöveget lehet formázni.

Ha egy ilyen attribútum osztály konstruktorának null értéket adunk paraméterül, akkor automatikusan úgy veszi, hogy mindenből a default értéket szeretnénk használni. Ide megadható egy már korábban vagy frissen létrehozott objektum. Fontos, hogy ha egy alakzathoz hozzárendelünk egy attribútumot az nem másolódik le, így minden változás adott esetben több alakzatot is érinthet. Ezt elkerülendő érdemes minden alakzathoz saját attribútumokat definiálni. (Viszont ez kihasználható, hogy ha több alakzatnak szeretnénk ugyanazokat az attribútumokat beállítani, akkor maradhat egy és azt állítjuk be az alakzatokhoz.)

Az alakzatok kétféle attribútumhalmazt tárolnak. Egyet saját magának, egyet pedig az alakzat kiemelésének. Minden alakzatnak egy egy logikai értéke amely megmondja, hogy az kiemelhető-e (highlighted). Ha ez igaz, akkor érvényesek a kiemelés attribútumai. Kezdetben a kiemelés attribútumai null-ok és amennyiben nem adunk meg ilyet, de kiválasztjuk, hogy az alakzat kiemelhető, akkor az alakzat saját attribútumait veszi figyelembe.

Út típus

Némely alakzatnak van olyan attribútuma amely meghatározza, hogy milyen módon kerül megrajzolásra.

  • WorldWind.GREAT_CIRCLE : Az alakzat útjai/élei egy nagy körutat követnek a definiáló pozíciók között. A földgömb görbületét figyelembe veszi.
  • WorldWind.RHUMB_LINE : Az alakzat útjai/élei egy loxodroma-t (egy gömb felületére írt csavarvonal) követnek a definiáló pontok között. A földgömb görbületét figyelembe veszi.
  • WorldWind.LINEAR : Az alakzat útjai vagy élei egy szimla egyenes vonalat követnek a definiáló pozíciók között. A földgömb görbületét figyelembe veszi.

Minden alakzatra az alapértelmezett érték WorldWind.GREAT_CIRCLE.

Magasság típus

Minden alakzat amely a geológiai pozíciójával van megadva, létezik egy attribútum amely megmondja az alakzatát magasságának kapcsolatát a tereppel.

  • WorldWind.ABSOLUTE : A magasságot relatív távolságként kezeli az elipszoid felszínéhez képest.
  • WorldWind.RELATIVE_TO_GROUND : A magasságot a terepen lévő pozíció koordinátáitól vett távolságként kezeli.
  • WorldWind.CLAMP_TO_GROUND : A magasságot nem veszi figyelembe és úgy veszi mint ha terepen lenne.

Minden alakzat esetén az alapérték a WorldWind.ABSOLUTE.

Glóbusz

Globe reprezentál egy WGS84 elipszoidot és a területet. továbbá kezeli a különböző 2D-s projekciókat, ami használhatóak a +D-s glóbusz helyett. Alapesetben ezen kívül az alkalmazás nem nagyon lép interakcióba a glóbusszal. Ez alól kivétel például ha az alkalmazásunk a terület emelkedésével szeretne számolni.

Minden World Window-nak eg Globe-ja van és automatikusan létrejön, amikor a World Window is. Az alkalmazásban a Globe lecserélhető egy másikra.

Navigátor

A Navigator objektum felelős azért, hogy a felhasználói interakciókat átalakítsa a földgömbön megjelenő változásokká. Folyamatosan figyeli az egér eseményeket és ezeket alakítja át mozgássá, forgatássá vagy zoomolássá. A Navigator segítségével lehet egy adott pozícióra navigálni.

Minden World Wind objektumnak megvan a saját Navigator objektuma, Ez a Navigator automatikusan jön létre, akkor amikor a World Wind objektumok létrejön. Ez a Navigator lecserélhető, ha a fejlesztő készített egy másképp működőt amely jobban megfelel az igényeknek.

Főbb funkcionalitások

Alakzatok

Szövegek

Egy adott földrajzi ponthoz tartozó szöveget reprezentál.

 1 // Példa adat
 2 var peaks =
 3 		[
 4 			{
 5 				'name': "Mount McKinley\n(Denali)", // Mount McKinley
 6 				'state': "Alaska",
 7 				'elevation': 6194,
 8 				'latitude': 63.0690,
 9 				'longitude': -151.0063
10 			},
11 			{
12 				'name': "Mauna\nKea",
13 				'state': "Hawaii",
14 				'elevation': 4205,
15 				'latitude': 19.8207,
16 				'longitude': -155.4680
17 			}];
18 
19 
20 
21 var text,
22     textAttributes = new WorldWind.TextAttributes(null),
23     textLayer = new WorldWind.RenderableLayer("Fölrajzi szöveg");
24 
25 //Alap attribútumok beállítása (pl: szín)
26 textAttributes.color = WorldWind.Color.RED;
27 textAttributes.depthTest = false;
28 
29 //Létrehozzuk a szöveg "alakzatokat"
30 for (var i = 0, len = peaks.length; i < len; i++) {
31     var peak = peaks[i],
32     peakPosition = new WorldWind.Position(peak.latitude, peak.longitude, peak.elevation);
33     text = new WorldWind.GeographicText(peakPosition, peak.name + "\n" + peak.state);
34 
35     //Beállítjuk az alakzatohoz a szöveget
36     text.attributes = textAttributes;
37 
38     //Hozzáadjuk a szöveget a layerhez
39     textLayer.addRenderable(text);
40 }
41 
42 //A szöveg layert hozzáadjuk a globál layerhez
43 wwd.addLayer(textLayer);
44 
45 //Létrehozunk egy managert, hogy tudjuk vezérelni a szöveg réteget.
46 var layerManger = new LayerManager(wwd);

Utak

Egyenes vagy görbe vonalat reprezentál előre megadott pozíciók között. A megrajzolt vonal az alábbi típusú lehet:

  • WorldWind.GREAT_CIRCLE
  • WorldWind.RHUMB_LINE
  • WorldWind.LINEAR

Az utat alkotó pontok közötti magasságot meghatározza az út magasság módja amely az alábbiak lehetnek:

  • WorldWind.ABSOLUTE
  • WorldWind.RELATIVE_TO_GROUND
  • WorldWind.CLAMP_TO_GROUND

Külön attribútumok tartoznak a normál és a kiemelt megjelenítéshez.

 1 // Úthoz tartozó poziciók létrehozása
 2 var pathPositions = [];
 3 pathPositions.push(new WorldWind.Position(40, -100, 1e4));
 4 pathPositions.push(new WorldWind.Position(45, -110, 1e4));
 5 pathPositions.push(new WorldWind.Position(46, -122, 1e4));
 6 
 7 // Az út létrehozása
 8 var path = new WorldWind.Path(pathPositions, null);
 9 path.altitudeMode = WorldWind.RELATIVE_TO_GROUND;
10 path.followTerrain = true;
11 path.extrude = true;
12 path.useSurfaceShapeFor2D = true;
13 
14 // Az úthoz tartozó attribútumok étrehozása
15 var pathAttributes = new WorldWind.ShapeAttributes(null);
16 pathAttributes.outlineColor = WorldWind.Color.BLUE;
17 pathAttributes.interiorColor = new WorldWind.Color(0, 1, 1, 0.5);
18 pathAttributes.drawVerticals = path.extrude;
19 path.attributes = pathAttributes;
20 
21 
22 // Kiemelés létrehozása
23 var highlightAttributes = new WorldWind.ShapeAttributes(pathAttributes);
24 highlightAttributes.outlineColor = WorldWind.Color.RED;
25 highlightAttributes.interiorColor = new WorldWind.Color(1, 1, 1, 0.5);
26 path.highlightAttributes = highlightAttributes;
27 
28 //Az utat hozzáadjuk egy layerhez, és betesszük a globális layerbe
29 var pathsLayer = new WorldWind.RenderableLayer();
30 pathsLayer.displayName = "Paths";
31 pathsLayer.addRenderable(path);
32 wwd.addLayer(pathsLayer);
33 
34 //Layermanager létrehozása
35 var layerManger = new LayerManager(wwd);
36 
37 //Eseménykezelés a kiemeléshez
38 var highlightController = new WorldWind.HighlightController(wwd);

Poligonok

Egy 3D-s poligont reprezentál. A poligonnak több határt is beállíthatunk, ezzel üres területeteket képezve. A poligon magassága az alábbiak lehetnek:

  • WorldWind.WorldWind.ABSOLUTE
  • WorldWind.RELATIVE_TO_GROUND
  • WorldWind.CLAMP_TO_GROUND

Külön attribútumok tartoznak a normál és a kiemelt megjelenítéshez.

 1 //Létrehozzuk a poligonokat tároló réteget
 2 var polygonsLayer = new WorldWind.RenderableLayer();
 3 polygonsLayer.displayName = "Polygons";
 4 wwd.addLayer(polygonsLayer);
 5 
 6 //Létrehozzuk a poligon határait
 7 var boundaries = [];
 8 boundaries[0] = []; // külső határ
 9 boundaries[0].push(new WorldWind.Position(40, -100, 1e5));
10 boundaries[0].push(new WorldWind.Position(45, -110, 1e5));
11 boundaries[0].push(new WorldWind.Position(40, -120, 1e5));
12 
13 boundaries[1] = []; // belső határ
14 boundaries[1].push(new WorldWind.Position(41, -103, 1e5));
15 boundaries[1].push(new WorldWind.Position(44, -110, 1e5));
16 boundaries[1].push(new WorldWind.Position(41, -117, 1e5));
17 
18 //Létrehozzuka a poligont és hozzáadjuk az attribútumait.
19 
20 var polygon = new WorldWind.Polygon(boundaries, null);
21 polygon.altitudeMode = WorldWind.ABSOLUTE;
22 polygon.extrude = true; 
23 
24 var polygonAttributes = new WorldWind.ShapeAttributes(null);
25 polygonAttributes.drawInterior = true;
26 polygonAttributes.drawOutline = true;
27 polygonAttributes.outlineColor = WorldWind.Color.BLUE;
28 polygonAttributes.interiorColor = new WorldWind.Color(0, 1, 1, 0.5);
29 polygonAttributes.drawVerticals = polygon.extrude;
30 polygonAttributes.applyLighting = true;
31 polygon.attributes = polygonAttributes;
32 
33 //Létrehozzuk a poligonhoz tartozó kiemelést
34 var highlightAttributes = new WorldWind.ShapeAttributes(polygonAttributes);
35 highlightAttributes.outlineColor = WorldWind.Color.RED;
36 highlightAttributes.interiorColor = new WorldWind.Color(1, 1, 1, 0.5);
37 polygon.highlightAttributes = highlightAttributes;
38 
39 //Hozzáadjuk a layerhez
40 polygonsLayer.addRenderable(polygon);


Helyjelző

Bármilyen pozíción megjelenő képet/címkét reprezentál. Lehet használni a beépített képeket vagy használhatunk sajátot, illetve a html-el is lehet rajzolni.

 1 // Definiáljuk a képeket amiket helyjelzőnek használunk.
 2 var images = [
 3 	"plain-black.png",
 4 	"plain-blue.png"
 5 ];
 6 
 7 var pinLibrary = WorldWind.configuration.baseUrl + "images/pushpins/", // a képek helye
 8 	placemark,
 9 	placemarkAttributes = new WorldWind.PlacemarkAttributes(null),
10 	highlightAttributes,
11 	placemarkLayer = new WorldWind.RenderableLayer("Placemarks"),
12 	latitude = 47.684444,
13 	longitude = -121.129722;
14 
15 // Létrehozzuk a közös attribútumokat.
16 placemarkAttributes.imageScale = 1;
17 placemarkAttributes.imageOffset = new WorldWind.Offset(
18 	WorldWind.OFFSET_FRACTION, 0.3,
19 	WorldWind.OFFSET_FRACTION, 0.0);
20 placemarkAttributes.imageColor = WorldWind.Color.WHITE;
21 placemarkAttributes.labelAttributes.offset = new WorldWind.Offset(
22 	WorldWind.OFFSET_FRACTION, 0.5,
23 	WorldWind.OFFSET_FRACTION, 1.0);
24 placemarkAttributes.labelAttributes.color = WorldWind.Color.YELLOW;
25 placemarkAttributes.drawLeaderLine = true;
26 placemarkAttributes.leaderLineAttributes.outlineColor = WorldWind.Color.RED;
27 
28 // Minden képhez létrehozunk egy Placemarkot és címkét
29 for (var i = 0, len = images.length; i < len; i++) {
30 	
31 	
32 	placemark = new WorldWind.Placemark(new WorldWind.Position(latitude, longitude + i, 1e2), true, null);
33 	placemark.label = "Placemark " + i.toString() + "\n"
34 	+ "Lat " + placemark.position.latitude.toPrecision(4).toString() + "\n"
35 	+ "Lon " + placemark.position.longitude.toPrecision(5).toString();
36 	placemark.altitudeMode = WorldWind.RELATIVE_TO_GROUND;
37 
38 	.
39 	placemarkAttributes = new WorldWind.PlacemarkAttributes(placemarkAttributes);
40 	placemarkAttributes.imageSource = pinLibrary + images[i];
41 	placemark.attributes = placemarkAttributes;
42 
43 	//Létrehozzuk a kiemeléshez tartozó attribútumokat
44 	highlightAttributes = new WorldWind.PlacemarkAttributes(placemarkAttributes);
45 	highlightAttributes.imageScale = 1.2;
46 	placemark.highlightAttributes = highlightAttributes;
47 
48 	//Hozzáadjuk a réteghez.
49 	placemarkLayer.addRenderable(placemark);
50 }
51 
52 // Hozzáadjuk a réteget a globális réteghez.
53 wwd.addLayer(placemarkLayer);
54 
55 // Létrehozunk egy Layermanagert a kezelhetőségért
56 var layerManger = new LayerManager(wwd);


További alakzatok

  • Felszíni alakzatok: Hasonlóak a fent taglalt Poligonokhoz. (Surface Shapes)
  • Képernyő kép: Segítségével képernyő-re képet rajzolhatunk. (Screen Image)
  • Képernyő szöveg : Segítségével szöveget helyezhetünk el a képernyőn. (Screen Text)

Eseménykezelés

A legtöbb alkalmazás általában figyeli és reagál a különböző Javascript eseményekre. Mivel itt azonban a Navigator objektum figyeli az egér és kézmozdulat eseményeket amivel a felhasználó manipulálhatja a földgömböt, ezért kénytelen vagyunk valamiféle koordinációt végezni az alkalmazás és a Navigator eseménykezelése között. Fontos, hogy a Web World Wind nem figyeli a billentyűzet eseményeit, így ezt nem kell koordinálni.

Ha az alkalmazásunk mobilon is fut akkor az egér mellett az érzékelés eseményeit is figyelni kell.


Egér eseménykezelés

Az esemény kezelőt be kell regisztrálni a World Window addEventListener metódusával.


1 var wwd = new WorldWind.WorldWindow("canvasOne");
2 wwd.addEventListener("mousemove", function (event) {...});

Az így hozzáadott listenerek a Navigator eseménykezelése előtt hívódnak meg. Azok az eseménykezelők akik választoktak az eseményre meg kell hívniuk a preventDefault -ot, hogy ezzel jelezzék a Navigatornak és a többi eseménykezelőnek, hogy ignorálják az eseményt. Továbbá az eseménykezelőknek érdemes megvizsgálni, hogy az eseményre válaszolt-e már valaki.

A fentiek alól kivétel a kattintás, mivel azt ClickRecognizer-el érdemes lekezelni. Ez kapcsolatban áll a Navigator-ral és kézmozdulat felismerőkkel, így elkerülve a duplikált eseménykezelést.


1 var clickRecognizer = new WorldWind.ClickRecognizer(wwd, 
2     function(recognizer) {
3         ...
4 });

Kézmozdulat eseménykezelés

Itt is érdemes a beépített TapRecognizer osztályt használni. Ez képes felismerni a különböző képernyőt ért kézmozdulatokat.


 1 // Általános kézmozdulat kezelő function
 2 var handleClick = function (recognizer) {
 3     // Obtain the event location.
 4     var x = recognizer.clientX,
 5         y = recognizer.clientY;
 6 
 7     //A felhasználó valahová mutat
 8     var pickList = wwd.pick(wwd.canvasCoordinates(x, y));
 9 
10     //Ha terepre mutatott akkor menjünk oda
11     if (pickList.objects.length == 1 && pickList.objects[0].isTerrain) {
12         var position = pickList.objects[0].position;
13         goToAnimator.goTo(new WorldWind.Location(position.latitude, position.longitude));
14     }
15 };
16 
17 // Figyeljük az egér kattintásokat
18 var clickRecognizer = new WorldWind.ClickRecognizer(wwd, handleClick);
19 
20 // Figyeljük a kézmozdulatokat
21 var tapRecognizer = new WorldWind.TapRecognizer(wwd, handleClick);

Navigáció

Hacsak nem szeretnénk a felhasználó nézetét programmal változtatni, akkor sose kell interakcióba lépni a navigátorral. De természetesen lehetséges a navigátort az alkalmazásból irányítani.

A Navigator objektumnak elsődlegesen kettő attribútuma felel az irányításért:

  • LookAtLocation: Jelzi a szélességet és hosszúságot ahová a felhasználó nézőpontja néz
  • range: Jelzi a szem távolságát az ellipszoidtól.
1 // Beállítjuk, hogy a Navigator erre pontra nézzen és ilyen magasan legyen.
2 wwd.navigator.lookAtLocation.latitude = 65;
3 wwd.navigator.lookAtLocation.longitude = -150;
4 wwd.navigator.range = 2e6; // 2 millió méterrel az ellipsziod felett

Ez azonban azonnal az új nézethez ugrik. Viszont szebben néz ki, fokozatosan és simán mozog oda ahová szeretnénk. Ehhez használhatjuk a GoToAnimator-t.

Shape File

A World Wind Web támogatja a Shape File-opk használatát egy beépített ShapeFile osztály segítségével. Ez értelmezési a kapott Shape File-t és tartalmából alakzatokat készít. A pontokból helyjelzők, a vonalalkból utak, a poligonokból poligonokat csinál.Az értelmezés végén definiálható egy hívás ami akkor történik miután az egészet értelmeztük, de még nem készültek el az alakzatok.

Amennyiben a Shape File mellett található attribútm file is (.dbf), azt automatikusan felismeri és értelmezi a Shape File-al együtt.

 1 // Honnan vegye a file-okat
 2 var shapefileLibrary = "http://worldwindserver.net/webworldwind/data/shapefiles/naturalearth";
 3 
 4 // Létrehozzuk a réteget azt adatoknak.
 5 var worldLayer = new WorldWind.RenderableLayer("Countries");
 6 
 7 // Létrehozzuk a file-t feldolgozó osztályt
 8 var worldShapefile = new WorldWind.Shapefile(shapefileLibrary + "/ne_110m_admin_0_countries/ne_110m_admin_0_countries.shp");
 9 
10 //Betöltjük a file-t
11 worldShapefile.load(null, shapeConfigurationCallback, worldLayer);
12 
13 //Hozzáadjuk a réteget
14 wwd.addLayer(worldLayer);