Giter Site home page Giter Site logo

worldwindearth / worldwindjs Goto Github PK

View Code? Open in Web Editor NEW

This project forked from nasaworldwind/webworldwind

37.0 37.0 9.0 65.09 MB

WorldWindJS is a community maintained fork of the WebWorldWind virtual globe SDK from NASA - an interactive 3D globe library featuring maps, imagery and terrain plus 2D map projections.

Home Page: https://worldwind.earth/worldwindjs/

JavaScript 98.62% HTML 1.00% CSS 0.34% Shell 0.03%
3d geojson geospatial gis globe imagery kml maps nasa-worldwind sdk-js shapefile shapes terrain visualization webgl wms wmts worldwind

worldwindjs's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

worldwindjs's Issues

Fix failing unit tests

Several unit tests were fixed in the upstream NASAWorldWind#804 PR.

Subtle errors in unit tests fixed. WorldWind's geometric unit tests erroneously modified global variables, such as Location.ZERO. These values shouldn't be encoded as global variables, but solving that is out of scope here. Previous versions of Jasmine concealed this problem but these unit tests fail with Jasmine 3.x, likely due to a change in the Jasmine interpreter lifecycle between tests.

These fixes should be migrated to this fork.

Improve MercatorTiledImageLayer

MercatorTiledImageLayer can be improved by translating following TS to JS:

export abstract class MercatorTiledImageLayer extends WorldWind.MercatorTiledImageLayer {

  private static readonly FULL_SPHERE = 360;

  private readonly firstLevelOffset;

  private static gudermannian(percent: number): number {
    return Math.atan(Math.sinh(percent * Math.PI)) * 180 / Math.PI;
  }

  private static levelZeroDelta(firstLevelOffset: number): WorldWind.Location {
    const levelZeroDelta = MercatorTiledImageLayer.FULL_SPHERE / (1 << firstLevelOffset);
    return new WorldWind.Location(levelZeroDelta / 2, levelZeroDelta);
  }

  protected constructor(name: string, numLevels: number, firstLevelOffset: number, tileSize: number, overlay: boolean, imageFormat: string){
    super(new WorldWind.Sector(
        MercatorTiledImageLayer.gudermannian(-1), MercatorTiledImageLayer.gudermannian(1),
        - MercatorTiledImageLayer.FULL_SPHERE / 2, MercatorTiledImageLayer.FULL_SPHERE / 2
      ), MercatorTiledImageLayer.levelZeroDelta(firstLevelOffset), numLevels - firstLevelOffset,
      imageFormat, name, tileSize, tileSize);
    this.firstLevelOffset = firstLevelOffset;
    (this as WorldWind.Layer).pickEnabled = false;
    (this as WorldWind.Layer).displayName = name;
    (this as WorldWind.MercatorTiledImageLayer).detectBlankImages = overlay;
    (this as WorldWind.MercatorTiledImageLayer).imageSize = tileSize;
  }

  protected mapSizeForLevel(levelNumber: number): number {
    return (this as WorldWind.MercatorTiledImageLayer).imageSize << (levelNumber + this.firstLevelOffset);
  }

  protected resourceUrlForTile(tile: WorldWind.ImageTile, imageFormat: string): string {
    return this.getImageSourceUrl(tile.column, tile.row, tile.level.levelNumber + this.firstLevelOffset);
  }

  protected abstract getImageSourceUrl(x: number, y: number, z: number): string;

}

This code makes Mercator layers processing the same as in Android and Java.

Unable to get WebWorldWind-StandaloneData.tar.gz from worldwind32.arc.nasa.gov

Description

Hello Team,

I try to install worldwindjs locally using following example: https://worldwind.arc.nasa.gov/web/tutorials/standalone-example/

All steps are working well but I am unable to download archive with data from worldwind32.arc.nasa.gov host.
The link from the instruction is: https://worldwind32.arc.nasa.gov/WebWorldWind-StandaloneData.tar.gz

Could someone assist me and provide correct link to the archive with the data?

Steps to Reproduce

  1. wget https://worldwind32.arc.nasa.gov/WebWorldWind-StandaloneData.tar.gz
    --2019-09-11 20:00:03-- https://worldwind32.arc.nasa.gov/WebWorldWind-StandaloneData.tar.gz
    Resolving worldwind32.arc.nasa.gov (worldwind32.arc.nasa.gov)... 128.102.22.152
    Connecting to worldwind32.arc.nasa.gov (worldwind32.arc.nasa.gov)|128.102.22.152|:443...

  2. failed: Connection timed out. Retrying.

Expected behavior:Archive have been downloaded

Actual behavior:failed: Connection timed out. Retrying.

Reproduces how often: Always

Operating System and Browser

Linux Ubuntu 18.04, wget, Chrome, Firefox

SurfaceShape picking is unpredictable

Picking of any SurfaceShapes is unpredictable, because JS canvas still does not allow to switch off anti-aliasing for strokes during rendering of pick frame.
This issue makes picking of SurfaceShapes unusable (see animation below).

  1. Create several SurfacePolylines close to each other so that they will be located on the same terrain tile.
  2. Try to pick one of them on mouse move.
  3. You will see that it picks random shape located on this tile.
    54945856-7a020f00-4f3f-11e9-8266-25d8852dc801

This problem appears because anti-aliasing not only make contour pixels transparent, but also make color value average between shape color and background. This average color is equal to pick color of some other shape in tile.

54986976-58933880-4fbc-11e9-9671-5188d9b4cc32

To fix this issue you need to do three steps:

  1. Disable anti-aliasing for path stroke on canvas to avoid appearance of semi-transparent pixels with wrong average color on the edge of the shape.

As I have researched - there is no possibility to disable canvas anti-aliasing for shapes. There is an option only for images. That's why we have two possibilities: ignore pick color with alpha != 1 during pick procedure or remove semi-transparent pixels which may contain wrong color from resulted tile. First approach is faster, but require changes in several places and may have some side effect on other renderables selection except surface shapes. That's why I propose to go with second approach - remove semi transparent pixels in SurfaceShapeTile.prototype.updateTexture.

                shape.renderToTexture(dc, ctx2D, xScale, yScale, xOffset, yOffset);
            }

            // Remove semi-transparent pixels which may contain wrong pick color
            if (dc.pickingMode) {
              const imageData = ctx2D.getImageData(0, 0, canvas.width, canvas.height);
              for (let i = 3, n = canvas.width * canvas.height * 4; i < n; i += 4) {
                if (imageData.data[i] < 255) {
                  imageData.data[i - 3] = 0;
                  imageData.data[i - 2] = 0;
                  imageData.data[i - 1] = 0;
                  imageData.data[i] = 0;
                }
              }
              ctx2D.putImageData(imageData, 0, 0);
            }

            this.gpuCacheKey = this.getCacheKey();
  1. We need to use NEAREST value for TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER in pickingMode the same way as in WorldWindAndroid, to avoid appearance of average color pixels during texture filtering in WebGL.
        Texture.prototype.applyTexParameters = function (dc) {
            var gl = dc.currentGlContext;

            // Configure the OpenGL texture minification function. Use nearest in pickingMode or linear by default.
            var textureMinFilter = dc.pickingMode ? gl.NEAREST : this.texParameters[gl.TEXTURE_MIN_FILTER] || gl.LINEAR;
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, textureMinFilter);

            // Configure the OpenGL texture magnification function. Use nearest in pickingMode or linear by default.
            var textureMagFilter = dc.pickingMode ? gl.NEAREST : this.texParameters[gl.TEXTURE_MAG_FILTER] || gl.LINEAR;
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, textureMagFilter);

            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.texParameters[gl.TEXTURE_WRAP_S] || gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.texParameters[gl.TEXTURE_WRAP_T] || gl.CLAMP_TO_EDGE);

            // Try to enable the anisotropic texture filtering only if we have a linear magnification filter.
            // This can't be enabled all the time because Windows seems to ignore the TEXTURE_MAG_FILTER parameter when
            // this extension is enabled.
            if (textureMagFilter === gl.LINEAR) {
                // Setup 4x anisotropic texture filtering when this feature is available.
                if (this.anisotropicFilterExt) {
                    gl.texParameteri(gl.TEXTURE_2D, this.anisotropicFilterExt.TEXTURE_MAX_ANISOTROPY_EXT, 4);
                }
            }
        };
  1. Remove texture parameters setting from Texture constructor, as it now located in applyTextParameters.
            gl.bindTexture(gl.TEXTURE_2D, textureId);

            gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
            gl.texImage2D(gl.TEXTURE_2D, 0,
                gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
            gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0);

            if (isPowerOfTwo) {
                gl.generateMipmap(gl.TEXTURE_2D);
            }

            this.textureId = textureId;

            /**
             * The time at which this texture was created.
             * @type {Date}
             */
            this.creationTime = new Date();

            // Internal use only. Intentionally not documented.
            this.texParameters = {};
            this.texParameters[gl.TEXTURE_MIN_FILTER] = isPowerOfTwo ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR;
            this.texParameters[gl.TEXTURE_WRAP_S] = wrapMode;
            this.texParameters[gl.TEXTURE_WRAP_T] = wrapMode;

Second and third part is a 100% MUST, but first part of my fix is little bit performance ineffective. So if anybody knows better way to avoid wrong color pixels during shape anti-alising or knows how to disable anti-alising, please, let me know.

Free camera navigation is missing

Basic LookAtNavigator implementation allows to change view point based on surface point and view angles of this surface point only. Camera can not view above horizon.

New feature is required to control camera independently. This feature will allow to implement UAV perspective view according to its telemetry or any other solution required free camera angles from eye point specification.

I propose to add this feature via PR.

Applying Placemark.imageRotation to non-squre images stretch them

Description

Applying Placemark.imageRotation to non-squre images stretch them.
120925094-df67f380-c6a4-11eb-8a66-fa78e91450ab
120925104-f575b400-c6a4-11eb-92b3-f65c1264f0b0
120925132-2229cb80-c6a5-11eb-984c-83c136ece8e0

Steps to Reproduce

Specify any non-square image as source of Placemark and set any non-zero imageRotation.

Expected behavior: Image should save its proportions

Actual behavior: Image stretch to original width and height

Reproduces how often: always

Additional info

Android code base has the same issue. Java code base use GL2 instead of Matrix for rotation and has no issue.
WorldWindEarth/WorldWindAndroid#31

Globe is not displayed in Firefox 63

Description

The globe is not displayed after upgrading to Firefox 63 (from 62).

Actual results:

The HTML canvas does not display the WebGL-based globe. Instead, a blank canvas is displayed (no globe) and the globe's screen annotations (text, symbols) are all displayed in the upper right-hand corner (stretched, distorted and on top of each other)

Expected results:

An interactive 3D view of the earth should have been displayed in the center of the canvas, with screen annotations (text, symbols) anchored in various positions around the periphery of the canvas.

There is no possibility to get canvas coordinates of some geographic location

There is no possibility to get canvas coordinates of some geographic location - oposite procedure to picking of some location by canvas coordinates.

This functionality is required when somebody requires to move some HTML UI elements according to Position on globe determining its pixel coordinates.

Android version has this functionality. So I propose to port it on JS in the following way...

  1. Add project function in Matrix:
        /**
         * Projects a Cartesian point to screen coordinates. This method assumes this matrix represents an inverse
         * modelview-projection matrix. The result of this method is undefined if this matrix is not an inverse
         * modelview-projection matrix.
         * <p/>
         * The resultant screen point is in OpenGL screen coordinates, with the origin in the bottom-left corner and axes
         * that extend up and to the right from the origin.
         * <p/>
         * This stores the projected point in the result argument, and returns a boolean value indicating whether or not the
         * projection is successful. This returns false if the Cartesian point is clipped by the near clipping plane or the
         * far clipping plane.
         *
         * @param {Number}    x the Cartesian point's X component
         * @param {Number}    y the Cartesian point's y component
         * @param {Number}    z the Cartesian point's z component
         * @param {Rectangle} viewport the viewport defining the screen point's coordinate system
         * @param {Vec3}    result a pre-allocated {@link Vec3} in which to return the projected point
         *
         * @return {boolean} true if the transformation is successful, otherwise false
         *
         * @throws {ArgumentError} If any argument is null
         */
        Matrix.prototype.project = function (x, y, z, viewport, result) {
            if (!viewport) {
                throw new ArgumentError(Logger.logMessage(Logger.ERROR, "Matrix", "project",
                    "missingViewport"));
            }

            if (!result) {
                throw new ArgumentError(Logger.logMessage(Logger.ERROR, "Matrix", "project",
                    "missingResult"));
            }

            // Transform the model point from model coordinates to eye coordinates then to clip coordinates. This inverts
            // the Z axis and stores the negative of the eye coordinate Z value in the W coordinate.
            var sx = this[0] * x + this[1] * y + this[2] * z + this[3];
            var sy = this[4] * x + this[5] * y + this[6] * z + this[7];
            var sz = this[8] * x + this[9] * y + this[10] * z + this[11];
            var sw = this[12] * x + this[13] * y + this[14] * z + this[15];

            if (sw === 0) {
                return false;
            }

            // Complete the conversion from model coordinates to clip coordinates by dividing by W. The resultant X, Y
            // and Z coordinates are in the range [-1,1].
            sx /= sw;
            sy /= sw;
            sz /= sw;

            // Clip the point against the near and far clip planes.
            if (sz < -1 || sz > 1) {
                return false;
            }

            // Convert the point from clip coordinate to the range [0,1]. This enables the X and Y coordinates to be
            // converted to screen coordinates, and the Z coordinate to represent a depth value in the range[0,1].
            sx = sx * 0.5 + 0.5;
            sy = sy * 0.5 + 0.5;
            sz = sz * 0.5 + 0.5;

            // Convert the X and Y coordinates from the range [0,1] to screen coordinates.
            sx = sx * viewport.width + viewport.x;
            sy = sy * viewport.height + viewport.y;

            result[0] = sx;
            result[1] = sy;
            result[2] = sz;

            return true;
        };
  1. Add scratch point to WorldWindow attributes:
            // Internal. Intentionally not documented.
            this.scratchPoint = new Vec3(0, 0, 0);
  1. Add geograpficToScreen and cartesianToScreen functions to WorldWindow:
        /**
         * Transforms a Cartesian coordinate point to coordinates relative to this WorldWindow's canvas.
         * <p/>
         * This stores the converted point in the result argument, and returns a boolean value indicating whether or not the
         * converted is successful. This returns false if the Cartesian point is clipped by either the WorldWindow's near
         * clipping plane or far clipping plane.
         *
         * @param {Number} x      the Cartesian point's x component in meters
         * @param {Number} y      the Cartesian point's y component in meters
         * @param {Number} z      the Cartesian point's z component in meters
         * @param {Vec2}   result a pre-allocated {@link Vec2} in which to return the screen point
         *
         * @return {boolean} true if the transformation is successful, otherwise false
         *
         * @throws {ArgumentError} If the result is null
         */
        WorldWindow.prototype.cartesianToScreenPoint = function (x, y, z, result) {
            if (!result) {
                throw new ArgumentError(Logger.logMessage(Logger.ERROR, "WorldWindow", "cartesianToScreenPoint",
                    "missingResult"));
            }

            // Compute the WorldWindow's modelview-projection matrix.
            this.computeViewingTransform(this.scratchProjection, this.scratchModelview);
            this.scratchProjection.multiplyMatrix(this.scratchModelview);

            // Transform the Cartesian point to OpenGL screen coordinates. Complete the transformation by converting to
            // Android screen coordinates and discarding the screen Z component.
            if (this.scratchProjection.project(x, y, z, this.viewport, this.scratchPoint)) {
                result[0] = this.scratchPoint[0];
                result[1] = this.viewport.height - this.scratchPoint[1];
                return true;
            }

            return false;
        };

        /**
         * Transforms a geographic position to coordinates relative to this WorldWindow's canvas.
         * <p/>
         * This stores the converted point in the result argument, and returns a boolean value indicating whether or not the
         * converted is successful. This returns false if the Cartesian point is clipped by either of the WorldWindow's
         * near clipping plane or far clipping plane.
         *
         * @param {Number} latitude  the position's latitude in degrees
         * @param {Number} longitude the position's longitude in degrees
         * @param {Number} altitude  the position's altitude in meters
         * @param {Vec2}   result    a pre-allocated {@link Vec2} in which to return the screen point
         *
         * @return {boolean} true if the transformation is successful, otherwise false
         *
         * @throws {ArgumentError} If the result is null
         */
        WorldWindow.prototype.geographicToScreenPoint = function (latitude, longitude, altitude, result) {
            if (!result) {
                throw new ArgumentError(Logger.logMessage(Logger.ERROR, "WorldWindow", "geographicToScreenPoint",
                    "missingResult"));
            }

            // Convert the position from geographic coordinates to Cartesian coordinates.
            this.globe.computePointFromPosition(latitude, longitude, altitude, this.scratchPoint);

            // Convert the position from Cartesian coordinates to screen coordinates.
            return this.cartesianToScreenPoint(this.scratchPoint[0], this.scratchPoint[1], this.scratchPoint[2], result);
        };

Add Symbology features from WorldWind Java

Prerequisites

Enhancement

Description

WorldWind Java has features for annotating textures and other custom placemarks under symbology. A 1 to 1 copy may be doable in typescript.

Add outline to Annotation shape

Draw an optional outline around the Annotation background shape. An outline would improve the clarity of overlapping annotations.

Placemark level of details selection is missing

WorldWindJS implementation of Placemark is missing level of details selection for placemark image source, depending on camera distance, as it was already done in Java and Android implementations.

Function makeOrderedRenderable in Placemark should execute some selectLod(dc, this, this.eyeDistance) function before this.determineActiveAttributes(dc) to allow application to define placemark attributes selection depending on this.eyeDistance.

You can look at example in Android repository.

Limit the size of the compass

The compass scales to the size of the canvas. A limit to the size should be imposed to prevent it from becoming too big on large screen displays.

Update npm build dependencies

The Travis-CI builds are failing on a deprecated option used by phantomjs. Meanwhile, the upstream WebWorldWind repo has updated its build dependencies. We should incorporate the updated dependencies found in the upstream NASAWorldWind#804 PR into this fork.

Add "always on top" as option to Annotation

Make the always on top behavior of an annotation optional. The current behavior is set to always on top, which may be out of sync with the drawing behavior of the placemark or shape being annotated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.